commit 399835a06f35dacff2c80e919428787f37ab6c42 Author: gunpitimac Date: Fri Aug 4 14:16:52 2023 +0700 [init] -init version 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 0000000..36ac46e Binary files /dev/null and b/src/assets/images/preview.png differ diff --git a/src/assets/logo/default.png b/src/assets/logo/default.png new file mode 100644 index 0000000..bfbbc23 Binary files /dev/null and b/src/assets/logo/default.png differ diff --git a/src/assets/logo/etest-logo.png b/src/assets/logo/etest-logo.png new file mode 100644 index 0000000..77569ab Binary files /dev/null and b/src/assets/logo/etest-logo.png differ diff --git a/src/assets/templates/ru_student_template_paid.xlsx b/src/assets/templates/ru_student_template_paid.xlsx new file mode 100644 index 0000000..bc1431d Binary files /dev/null and b/src/assets/templates/ru_student_template_paid.xlsx differ diff --git a/src/assets/templates/ru_student_template_wait.xlsx b/src/assets/templates/ru_student_template_wait.xlsx new file mode 100644 index 0000000..ce52303 Binary files /dev/null and b/src/assets/templates/ru_student_template_wait.xlsx differ diff --git a/src/assets/templates/student_import.xlsx b/src/assets/templates/student_import.xlsx new file mode 100644 index 0000000..10357f3 Binary files /dev/null and b/src/assets/templates/student_import.xlsx differ diff --git a/src/environments/environment.prod.ts b/src/environments/environment.prod.ts new file mode 100644 index 0000000..feb6a5e --- /dev/null +++ b/src/environments/environment.prod.ts @@ -0,0 +1,20 @@ +export const environment = { + hideForm: true, + production: true, + openidPath: 'https://ru-iam-api.71dev.com', + adminApi: 'https://ru.71dev.com/etest-admin', + storeApi: 'https://ru.71dev.com/etest-question', + enrollmentApi: 'https://ru.71dev.com/etest-enrollment', + uploadApi:'https://ru.71dev.com/etest-admin', + apiVersion: 'v1', + clientSettings: { + authority: 'https://ru-iam.71dev.com/', + client_id: 'ru-manage-testing-frontend-client-prod', + redirect_uri: 'https://ru.71dev.com/manage-testing/auth', + post_logout_redirect_uri: 'https://ru.71dev.com/manage-testing/', + response_type: "id_token token", + scope: "manage openid profile", + filterProtocolClaims: true, + loadUserInfo: true + }, +}; diff --git a/src/environments/environment.ru.ts b/src/environments/environment.ru.ts new file mode 100644 index 0000000..4cade21 --- /dev/null +++ b/src/environments/environment.ru.ts @@ -0,0 +1,20 @@ +export const environment = { + hideForm: true, + production: true, + openidPath: 'https://ru-iam.ru.ac.th', + adminApi: 'https://etesting.ru.ac.th/etest-admin', + storeApi: 'https://etesting.ru.ac.th/etest-question', + enrollmentApi: 'https://etesting.ru.ac.th/etest-enrollment', + uploadApi:'https://exam.ru.ac.th/etest-question', + apiVersion: 'v2', + clientSettings: { + authority: 'https://ru-iam.ru.ac.th/', + client_id: 'ru-manage-testing-frontend-client-prod', + redirect_uri: 'https://etesting.ru.ac.th/backoffice/auth', + post_logout_redirect_uri: 'https://etesting.ru.ac.th/backoffice/', + response_type: "id_token token", + scope: "manage openid profile", + filterProtocolClaims: true, + loadUserInfo: true + }, +}; diff --git a/src/environments/environment.ts b/src/environments/environment.ts new file mode 100644 index 0000000..38e6edc --- /dev/null +++ b/src/environments/environment.ts @@ -0,0 +1,20 @@ +export const environment = { + hideForm: false, + production: false, + openidPath: 'https://ru-iam-api.71dev.com', + adminApi: 'https://ru.71dev.com/etest-admin', + storeApi: 'https://ru.71dev.com/etest-question', + enrollmentApi: 'https://ru.71dev.com/etest-enrollment', + uploadApi: 'https://ru.71dev.com/etest-admin', + apiVersion: 'v1', + clientSettings: { + authority: 'https://ru-iam.71dev.com/', + client_id: 'ru-manage-testing-frontend-client-dev', + redirect_uri: 'http://localhost:4200/auth', + post_logout_redirect_uri: 'http://localhost:4200/', + response_type: "id_token token", + scope: "manage openid profile", + filterProtocolClaims: true, + loadUserInfo: true + }, +}; diff --git a/src/favicon.ico b/src/favicon.ico new file mode 100644 index 0000000..5a76904 Binary files /dev/null and b/src/favicon.ico differ diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..4435d2a --- /dev/null +++ b/src/index.html @@ -0,0 +1,18 @@ + + + + + RU-BACKOFFICE + + + + + + + + + + + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..9d9067c --- /dev/null +++ b/src/main.ts @@ -0,0 +1,12 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.error(err)); diff --git a/src/polyfills.ts b/src/polyfills.ts new file mode 100644 index 0000000..b930a40 --- /dev/null +++ b/src/polyfills.ts @@ -0,0 +1,63 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/guide/browser-support + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** + * Web Animations `@angular/platform-browser/animations` + * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. + * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). + */ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + +/** + * By default, zone.js will patch all possible macroTask and DomEvents + * user can disable parts of macroTask/DomEvents patch by setting following flags + * because those flags need to be set before `zone.js` being loaded, and webpack + * will put import in the top of bundle, so user need to create a separate file + * in this directory (for example: zone-flags.ts), and put the following flags + * into that file, and then add the following code before importing zone.js. + * import './zone-flags.ts'; + * + * The flags allowed in zone-flags.ts are listed here. + * + * The following flags will work for all browsers. + * + * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame + * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick + * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + * + * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js + * with the following flag, it will bypass `zone.js` patch for IE/Edge + * + * (window as any).__Zone_enable_cross_context_check = true; + * + */ + +/*************************************************************************************************** + * Zone JS is required by default for Angular itself. + */ +import 'zone.js/dist/zone'; // Included with Angular CLI. + + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ diff --git a/src/styles.scss b/src/styles.scss new file mode 100644 index 0000000..88e6b17 --- /dev/null +++ b/src/styles.scss @@ -0,0 +1,483 @@ +/* You can add global styles to this file, and also import other style files */ +@import "tailwindcss/base"; +@import "tailwindcss/components"; +@import "tailwindcss/utilities"; + +html, +body { + height: 100%; +} +body { + margin: 0; +} + +*:not(.material-icons) { + font-family: "Sarabun" !important; + font-size: 16px; + // font-weight: 100; + font-style: normal; + line-height: 26px; +} + +mat-icon { + @apply cursor-pointer; +} + +*:focus { + outline: 0 !important; +} + +select { + @apply form-select appearance-none px-4 py-2 border focus:ring-gray-500 focus:border-gray-900 w-full border-gray-300 rounded-md focus:outline-none text-gray-600; +} + +textarea { + @apply form-textarea px-4 py-2 border focus:ring-gray-500 focus:border-gray-900 w-full border-gray-300 rounded-md focus:outline-none text-gray-600; +} + +input { + @apply form-input px-4 py-2 border focus:ring-gray-500 focus:border-gray-900 w-full border-gray-300 rounded-md focus:outline-none text-gray-600 disabled:opacity-50; +} + +textarea.ng-invalid { + @apply form-textarea px-4 py-2 border-2 focus:ring-red-300 focus:border-red-300 w-full border-red-300 rounded-md focus:outline-none text-gray-600; +} + +input.ng-invalid { + @apply form-input px-4 py-2 border-2 focus:ring-red-300 focus:border-red-300 w-full border-red-300 rounded-md focus:outline-none text-gray-600 disabled:opacity-50 ; +} + +select.ng-invalid { + @apply form-select appearance-none px-4 py-2 border-2 focus:ring-red-300 focus:border-red-300 w-full border-red-300 rounded-md focus:outline-none text-gray-600; +} + +input::placeholder { + @apply text-gray-400; + line-height: 26px; +} + +input:read-only { + @apply bg-gray-300 cursor-pointer; +} + +editor { + @apply mt-2; +} + +::-webkit-scrollbar { + width: 5px; + height: 10px; +} + +::-webkit-scrollbar-track { + background: #f1f1f1; +} + +::-webkit-scrollbar-thumb { + background: #888; +} + +::-webkit-scrollbar-track:horizontal { + background: #f1f1f1; + border-radius: 10px; +} + +::-webkit-scrollbar-thumb:horizontal{ + background: #888; + border-radius: 10px; +} + +.custom-modalbox { + mat-dialog-container { + padding: unset; + } +} + +.tox-notifications-container { + display: none !important; +} + +.error-text{ + @apply text-red-500 text-xs +} + +.search-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #54c6ec; + min-width: 100px !important; +} + +.confirm-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #609b35; + min-width: 100px !important; +} + +.payment-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #2a56c6; + min-width: 100px !important; +} + +.clear-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #576071; + min-width: 100px !important; +} + +.add-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #ec8d4b; + min-width: 100px !important; +} + +.copy-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #666666; + min-width: 100px !important; +} + +.copy-button-active { + @apply rounded h-10 text-white disabled:opacity-50; + background: #3176d7; + min-width: 100px !important; +} + +.cancel-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: #9a9fa1; + min-width: 100px !important; +} + +.cancel-button-active { + @apply rounded h-10 text-white disabled:opacity-50; + background: #ec8d4b; + min-width: 100px !important; +} + +.delete-button { + @apply rounded h-10 text-white disabled:opacity-50; + background: darkred; + min-width: 100px !important; +} + +.delete-button-brown { + @apply rounded h-10 text-white disabled:opacity-50; + background: #666666; + min-width: 100px !important; +} + +.del-but{ + @apply rounded h-10 text-white disabled:opacity-50; + background: #666666; +} + +.add-but{ + @apply rounded h-10 text-white disabled:opacity-50; + background: #ec8d4b; +} + +.main { + @apply bg-gray-200 p-3 space-y-4; +} + +.title { + @apply font-light text-xl; +} + +.dafalut-page { + @apply font-light text-2xl; +} + +table { + overflow-x: auto; + // min-width: 100vh; + // max-width: 100vw; + width: 100% +} + +.card { + @apply shadow bg-white rounded-md p-6; +} + +.mat-form-field-appearance-outline .mat-form-field-infix { + border-top: none; + padding: 1em 0 0.8em 0; +} +.mat-form-field-appearance-outline.mat-form-field-can-float.mat-form-field-should-float + .mat-form-field-label { + transform: translateY(-1.1em) scale(0.75); + width: 133.33333%; +} + +.mat-form-field-label-wrapper { + top: -0.5em; +} +.mat-form-field-appearance-fill .mat-form-field-flex { + padding: 0 0.5em 0 0.5em !important; +} + +.mat-form-field { + line-height: 1.32; +} + +.mat-form-field-appearance-fill .mat-select-arrow-wrapper { + transform: translateY(0%) !important; +} + +.mat-accordion .mat-expansion-panel:last-of-type { + border-radius: 0px !important; +} + +.mat-expansion-panel:not([class*="mat-elevation-z"]) { + box-shadow: unset; +} + +.mat-expansion-panel-body { + background-color: #576071; + padding: 0 !important; +} + +.mat-expansion-panel-header { + background-color: #576071 !important; + padding: 0 10px 0 0 !important; + min-height: 60px; +} + +.mat-expansion-panel-content { + background-color: #576071; +} + +.mat-expanded { + background-color: #576071; +} + +.mat-expansion-indicator::after { + content: ""; +} + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + margin: 0; +} + +.swal2-title { + line-height: 40px !important; +} + +.mat-form-field-wrapper { + // change sapce bottom input + margin-bottom: 10px; + padding-bottom: 0 !important; + + .mat-form-field-flex { + input { + @apply form-input px-4 py-2 border focus:ring-transparent focus:border-transparent w-full border-gray-300 rounded-md focus:outline-none text-gray-600 disabled:opacity-50; + } + position: relative; + display: flex; + align-items: stretch; + min-height: 44px !important; + border-radius: 6px; + padding: 0 16px; + border-width: 1px; + @apply bg-white border-gray-300 #{'!important'}; + + .mat-form-field-prefix { + > .mat-icon { + margin-right: 12px !important; + } + + > .mat-icon-button { + margin: 0 4px 0 -10px !important; + } + + > .mat-select { + margin-right: 10px !important; + } + + > .mat-datepicker-toggle { + margin-left: -8px !important; + } + + > *:not(.mat-icon):not(.mat-icon-button):not(.mat-select):not(.mat-datepicker-toggle) { + margin-right: 12px !important; + } + } + + .mat-form-field-suffix { + > .mat-icon { + margin-left: 12px; + } + + > .mat-icon-button { + margin: 0 -10px 0 4px; + } + + > .mat-select { + margin-left: 10px; + } + + > .mat-datepicker-toggle { + margin-right: -8px; + margin-top: 5px; + } + } + + .mat-form-field-prefix, + .mat-form-field-suffix { + display: inline-flex; + align-items: center; + justify-content: center; + .mat-datepicker-toggle-default-icon { + width: 1.5rem; + height: 1.5rem; + min-width: 1.5rem; + min-height: 1.5rem; + font-size: 1.5rem; + line-height: 1.5rem; + } + } + + .mat-form-field-infix { + position: static; + display: flex; + align-items: center; + width: 88px; + padding: 0; + border: 0; + // change text input size here + .mat-input-element { + padding: 0; + font-size: 18px; + margin-top: 0; + } + + /* Select */ + .mat-select { + font-size: 18px; + display: inline-flex; + + .mat-select-trigger { + display: inline-flex; + align-items: center; + width: 100%; + + .mat-select-value { + display: flex; + position: relative; + max-width: none; + + .mat-select-value-text { + display: inline-flex; + + > * { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + } + } + } + + .mat-select-arrow-wrapper { + transform: translateY(0); + + .mat-select-arrow { + margin: 0 0 0 8px; + } + } + } + + .mat-chip-list { + width: 100%; + margin: 0 -8px; + + .mat-chip-input { + margin: 0 0 0 8px; + } + } + + .mat-chip-list { + width: 100%; + margin: 0 -8px; + + .mat-chip-input { + margin: 0 0 0 8px; + } + } + } + } + + /* Remove the underline */ + .mat-form-field-underline { + display: none; + } + + +} + + + +.mat-paginator { + .mat-paginator-container { + padding: 8px 16px; + justify-content: space-between; + + @screen sm { + justify-content: flex-end; + } + + /* Page size select */ + .mat-paginator-page-size { + align-items: center; + min-height: 40px; + margin: 8px; + + .mat-paginator-page-size-label { + display: none; + margin-right: 12px; + + @screen sm { + display: block; + } + } + + .mat-paginator-page-size-select { + margin: 0; + width: 70px !important; + + .mat-form-field-wrapper { + margin-bottom: 0; + + .mat-form-field-flex { + min-height: 32px; + padding: 0 10px; + } + } + } + } + + /* Range actions */ + .mat-paginator-range-actions { + margin: 8px 0; + + .mat-paginator-range-label { + margin-right: 16px; + } + } + } +} + +.mat-paginator-container { + display: flex; + align-items: center; + justify-content: flex-end; +} + +.error { + @apply text-red-500 text-xs; +} diff --git a/src/test.ts b/src/test.ts new file mode 100644 index 0000000..1c2f3fc --- /dev/null +++ b/src/test.ts @@ -0,0 +1,20 @@ +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'zone.js/dist/zone-testing'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting +} from '@angular/platform-browser-dynamic/testing'; + +declare const require: any; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() +); +// Then we find all the tests. +const context = require.context('./', true, /\.spec\.ts$/); +// And load the modules. +context.keys().map(context); diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..228abf7 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,50 @@ +module.exports = { + important: true, + + prefix: '', + purge: { + content: [ + './src/**/*.{html,ts}', + ] + }, + darkMode: 'class', // or 'media' or 'class' + theme: { + extend: { + spacing: + { + menu: '255px', + '33%': '33%', + '48%': '48%', + '24%': '24%' + }, + }, + screens: { + 'sm': '640px', + // => @media (min-width: 640px) { ... } + + 'md': '768px', + // => @media (min-width: 768px) { ... } + + 'lg': '1024px', + // => @media (min-width: 1024px) { ... } + + 'xl': '1280px', + // => @media (min-width: 1280px) { ... } + + '2xl': '1536px', + // => @media (min-width: 1536px) { ... } + } + }, + variants: { + extend: { + opacity: ['disabled'], + }, + }, + plugins: [ + require("@tailwindcss/forms")({ + strategy: 'class', + }), + require('@tailwindcss/line-clamp'), + require('@tailwindcss/typography') + ], +}; diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..7ef944d --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": [] + }, + "files": [ + "src/main.ts", + "src/polyfills.ts" + ], + "include": [ + "src/**/*.d.ts" + ] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..759209d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "skipLibCheck": true, + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, + "module": "es2020", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "importHelpers": true, + "target": "es2015", + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2018", + "dom" + ] + } +} diff --git a/tsconfig.spec.json b/tsconfig.spec.json new file mode 100644 index 0000000..f3d7d22 --- /dev/null +++ b/tsconfig.spec.json @@ -0,0 +1,18 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "src/test.ts", + "src/polyfills.ts" + ], + "include": [ + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000..3cc643e --- /dev/null +++ b/tslint.json @@ -0,0 +1,155 @@ +{ + "extends": "tslint:recommended", + "rules": { + "align": { + "options": [ + "parameters", + "statements" + ] + }, + "array-type": false, + "arrow-parens": false, + "arrow-return-shorthand": true, + "curly": true, + "deprecation": { + "severity": "warn" + }, + "component-class-suffix": true, + "contextual-lifecycle": true, + "directive-class-suffix": true, + "directive-selector": [ + true, + "attribute", + "app", + "camelCase" + ], + "component-selector": [ + true, + "element", + "app", + "kebab-case" + ], + "eofline": true, + "import-blacklist": [ + true, + "rxjs/Rx" + ], + "import-spacing": true, + "indent": { + "options": [ + "spaces" + ] + }, + "interface-name": false, + "max-classes-per-file": false, + "max-line-length": [ + true, + 140 + ], + "member-access": false, + "member-ordering": [ + true, + { + "order": [ + "static-field", + "instance-field", + "static-method", + "instance-method" + ] + } + ], + "no-consecutive-blank-lines": false, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-empty": false, + "no-inferrable-types": [ + true, + "ignore-params" + ], + "no-non-null-assertion": true, + "no-redundant-jsdoc": true, + "no-switch-case-fall-through": true, + "no-var-requires": false, + "object-literal-key-quotes": [ + true, + "as-needed" + ], + "object-literal-sort-keys": false, + "ordered-imports": false, + "quotemark": [ + true, + "single" + ], + "semicolon": { + "options": [ + "always" + ] + }, + "space-before-function-paren": { + "options": { + "anonymous": "never", + "asyncArrow": "always", + "constructor": "never", + "method": "never", + "named": "never" + } + }, + "trailing-comma": false, + "no-conflicting-lifecycle": true, + "no-host-metadata-property": true, + "no-input-rename": true, + "no-inputs-metadata-property": true, + "no-output-native": true, + "no-output-on-prefix": true, + "no-output-rename": true, + "no-outputs-metadata-property": true, + "template-banana-in-box": true, + "template-no-negated-async": true, + "typedef-whitespace": { + "options": [ + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + }, + { + "call-signature": "onespace", + "index-signature": "onespace", + "parameter": "onespace", + "property-declaration": "onespace", + "variable-declaration": "onespace" + } + ] + }, + "use-lifecycle-interface": true, + "use-pipe-transform-interface": true + , "variable-name": { + "options": [ + "ban-keywords", + "check-format", + "allow-pascal-case" + ] + }, + "whitespace": { + "options": [ + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type", + "check-typecast" + ] + } +}, + "rulesDirectory": [ + "codelyzer" + ] +} diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..8a28ad9 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,11 @@ +const { addTailwindPlugin } = require("@ngneat/tailwind"); +const tailwindConfig = require("./tailwind.config.js"); + +module.exports = (config) => { + addTailwindPlugin({ + webpackConfig: config, + tailwindConfig, + patchComponentsStyles: true + }); + return config; +};