From 05dced334fa1c07d46620ccf5a47c1b6512e2379 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 4 Jul 2022 20:40:02 +0900 Subject: [PATCH 0001/1011] =?UTF-8?q?feat:=20=EA=B0=9C=EB=B0=9C=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=20=EA=B5=AC=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/.eslintrc.json | 16 + frontend/.gitignore | 2 + frontend/.prettierrc.json | 12 + frontend/babel.config.js | 4 + frontend/package.json | 58 + frontend/src/App.tsx | 3 + frontend/src/index.html | 11 + frontend/src/index.tsx | 5 + frontend/tsconfig.json | 13 + frontend/webpack.config.js | 45 + frontend/yarn.lock | 11417 +++++++++++++++++++++++++++++++++++ 11 files changed, 11586 insertions(+) create mode 100644 frontend/.eslintrc.json create mode 100644 frontend/.gitignore create mode 100644 frontend/.prettierrc.json create mode 100644 frontend/babel.config.js create mode 100644 frontend/package.json create mode 100644 frontend/src/App.tsx create mode 100644 frontend/src/index.html create mode 100644 frontend/src/index.tsx create mode 100644 frontend/tsconfig.json create mode 100644 frontend/webpack.config.js create mode 100644 frontend/yarn.lock diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json new file mode 100644 index 00000000..39f13408 --- /dev/null +++ b/frontend/.eslintrc.json @@ -0,0 +1,16 @@ +{ + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint", "prettier"], + "extends": [ + "plugin:react/recommended", + "plugin:import/errors", + "plugin:import/warnings", + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended" + ], + "rules": { + "react/react-in-jsx-scope": "off", + "import/no-unresolved": "off", + "@typescript-eslint/no-var-requires": "off" + } +} diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 00000000..76add878 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json new file mode 100644 index 00000000..b5b29cff --- /dev/null +++ b/frontend/.prettierrc.json @@ -0,0 +1,12 @@ +{ + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "trailingComma": "es5", + "bracketSpacing": true, + "bracketSameLine": false, + "arrowParens": "always", + "endofLine": "auto" +} diff --git a/frontend/babel.config.js b/frontend/babel.config.js new file mode 100644 index 00000000..01db9fa0 --- /dev/null +++ b/frontend/babel.config.js @@ -0,0 +1,4 @@ +module.exports = { + presets: ['@babel/preset-react', '@babel/preset-env', '@babel/preset-typescript'], + plugins: ['@emotion'], +}; diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 00000000..170eeb1c --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,58 @@ +{ + "name": "dallog", + "version": "1.0.0", + "description": "share calendar dallog", + "main": "index.js", + "scripts": { + "dev": "webpack serve --mode development --open --hot", + "build": "webpack --mode production", + "prestart": "npm build", + "start": "webpack --mode development", + "storybook": "start-storybook -p 6006", + "build-storybook": "build-storybook" + }, + "dependencies": { + "@emotion/react": "^11.9.3", + "@emotion/styled": "^11.9.3", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@babel/core": "^7.18.6", + "@babel/preset-env": "^7.18.6", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.18.6", + "@emotion/babel-plugin": "^11.9.2", + "@storybook/addon-actions": "^6.5.9", + "@storybook/addon-essentials": "^6.5.9", + "@storybook/addon-interactions": "^6.5.9", + "@storybook/addon-links": "^6.5.9", + "@storybook/builder-webpack5": "^6.5.9", + "@storybook/manager-webpack5": "^6.5.9", + "@storybook/react": "^6.5.9", + "@storybook/testing-library": "^0.0.13", + "@types/body-parser": "^1.19.2", + "@types/graceful-fs": "^4.1.5", + "@types/node": "^18.0.1", + "@types/react": "^18.0.14", + "@types/react-dom": "^18.0.5", + "@typescript-eslint/eslint-plugin": "^5.30.4", + "@typescript-eslint/parser": "^5.30.4", + "babel-loader": "^8.2.5", + "clean-webpack-plugin": "^4.0.0", + "css-loader": "^6.7.1", + "eslint": "^8.19.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.30.1", + "html-webpack-plugin": "^5.5.0", + "prettier": "^2.7.1", + "style-loader": "^3.3.1", + "ts-loader": "^9.3.1", + "typescript": "^4.7.4", + "webpack": "^5.73.0", + "webpack-cli": "^4.10.0", + "webpack-dev-server": "^4.9.3" + } +} diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx new file mode 100644 index 00000000..f27a8c76 --- /dev/null +++ b/frontend/src/App.tsx @@ -0,0 +1,3 @@ +const App = () => <>Dallog; + +export default App; diff --git a/frontend/src/index.html b/frontend/src/index.html new file mode 100644 index 00000000..020ed219 --- /dev/null +++ b/frontend/src/index.html @@ -0,0 +1,11 @@ + + + + + + 달록 + + +
+ + diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx new file mode 100644 index 00000000..48b5a1e3 --- /dev/null +++ b/frontend/src/index.tsx @@ -0,0 +1,5 @@ +import ReactDOM from 'react-dom'; +import App from './App'; + +const rootElement = document.getElementById('root'); +ReactDOM.render(, rootElement); diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 00000000..eb62d456 --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "ESNext", + "jsx": "react-jsx", + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "esModuleInterop": true + }, + "exclude": ["node_modules"], + "include": ["src"] +} diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js new file mode 100644 index 00000000..512a3bc3 --- /dev/null +++ b/frontend/webpack.config.js @@ -0,0 +1,45 @@ +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const path = require('path'); +const webpack = require('webpack'); +const { CleanWebpackPlugin } = require('clean-webpack-plugin'); + +const prod = process.env.NODE_ENV === 'production'; + +module.exports = { + mode: prod ? 'production' : 'development', + devtool: prod ? 'hidden-source-map' : 'eval', + entry: './src/index.tsx', + resolve: { + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + module: { + rules: [ + { + test: /\.tsx?$/, + use: ['babel-loader', 'ts-loader'], + }, + { + test: /\\.css$/, + use: ['style-loader', 'css-loader'], + }, + ], + }, + output: { + path: path.join(__dirname, '/dist'), + filename: 'bundle.js', + }, + plugins: [ + new webpack.ProvidePlugin({ + React: 'react', + }), + new HtmlWebpackPlugin({ + template: './src/index.html', + }), + new CleanWebpackPlugin(), + ], + devServer: { + historyApiFallback: true, + port: 3000, + hot: true, + }, +}; diff --git a/frontend/yarn.lock b/frontend/yarn.lock new file mode 100644 index 00000000..d7e4d0e1 --- /dev/null +++ b/frontend/yarn.lock @@ -0,0 +1,11417 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + dependencies: + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.6.tgz#8b37d24e88e8e21c499d4328db80577d8882fa53" + integrity sha512-tzulrgDT0QD6U7BJ4TKVk2SDDg7wlP39P9yAx1RfLy7vP/7rsDRlWVfbWxElslu56+r7QOhB2NSDsabYYruoZQ== + +"@babel/core@7.12.9": + version "7.12.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" + integrity sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.5" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.7" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.9" + "@babel/types" "^7.12.7" + 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" + +"@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.18.6", "@babel/core@^7.7.5": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.6.tgz#54a107a3c298aee3fe5e1947a6464b9b6faca03d" + integrity sha512-cQbWBpxcbbs/IUredIPkHiAGULLV8iwgNRMFzvbhEXISp4f3rUUXE5+TIw6KwUWUR3DwyI6gmBRnmAtYaWehwQ== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.18.6" + "@babel/helper-compilation-targets" "^7.18.6" + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helpers" "^7.18.6" + "@babel/parser" "^7.18.6" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.1" + semver "^6.3.0" + +"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.18.6": + version "7.18.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.7.tgz#2aa78da3c05aadfc82dbac16c99552fc802284bd" + integrity sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A== + dependencies: + "@babel/types" "^7.18.7" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" + +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.6.tgz#f14d640ed1ee9246fb33b8255f08353acfe70e6a" + integrity sha512-KT10c1oWEpmrIRYnthbzHgoOf6B+Xd6a5yhdbNtdhtG7aO1or5HViuf1TQR36xY/QprXA5nvxO6nAjhJ4y38jw== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz#18d35bfb9f83b1293c22c55b3d576c1315b6ed96" + integrity sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg== + dependencies: + "@babel/compat-data" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.20.2" + semver "^6.3.0" + +"@babel/helper-create-class-features-plugin@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.6.tgz#6f15f8459f3b523b39e00a99982e2c040871ed72" + integrity sha512-YfDzdnoxHGV8CzqHGyCbFvXg5QESPFkXlHtvdCkesLjjVMT2Adxe4FGUR5ChIb3DxSaXO12iIOCWoXdsUVwnqw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-member-expression-to-functions" "^7.18.6" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + +"@babel/helper-create-regexp-features-plugin@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz#3e35f4e04acbbf25f1b3534a657610a000543d3c" + integrity sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + regexpu-core "^5.1.0" + +"@babel/helper-define-polyfill-provider@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz#3c2f91b7971b9fc11fe779c945c014065dea340e" + integrity sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg== + dependencies: + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + +"@babel/helper-define-polyfill-provider@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" + integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== + dependencies: + "@babel/helper-compilation-targets" "^7.13.0" + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-plugin-utils" "^7.13.0" + "@babel/traverse" "^7.13.0" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + semver "^6.1.2" + +"@babel/helper-environment-visitor@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz#b7eee2b5b9d70602e59d1a6cad7dd24de7ca6cd7" + integrity sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q== + +"@babel/helper-explode-assignable-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" + integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-function-name@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz#8334fecb0afba66e6d87a7e8c6bb7fed79926b83" + integrity sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw== + dependencies: + "@babel/template" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-member-expression-to-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.6.tgz#44802d7d602c285e1692db0bad9396d007be2afc" + integrity sha512-CeHxqwwipekotzPDUuJOfIMtcIHBuc7WAzLmTYWctVigqS5RktNMQ5bEwQSuGewzYnCtTWa3BARXeiLxDTv+Ng== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.6.tgz#57e3ca669e273d55c3cda55e6ebf552f37f483c8" + integrity sha512-L//phhB4al5uucwzlimruukHB3jRd5JGClwRMD/ROrVjXfLqovYnvQrK/JK36WYyVwGGO7OD3kMyVTjx+WVPhw== + dependencies: + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.18.6" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-optimise-call-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-plugin-utils@7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz#9448974dd4fb1d80fefe72e8a0af37809cd30d6d" + integrity sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg== + +"@babel/helper-remap-async-to-generator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.6.tgz#fa1f81acd19daee9d73de297c0308783cd3cfc23" + integrity sha512-z5wbmV55TveUPZlCLZvxWHtrjuJd+8inFhk7DG0WW87/oJuGDcjDiu7HIvGcpf5464L6xKCg3vNkmlVVz9hwyQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-wrap-function" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-replace-supers@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.18.6.tgz#efedf51cfccea7b7b8c0f00002ab317e7abfe420" + integrity sha512-fTf7zoXnUGl9gF25fXCWE26t7Tvtyn6H4hkLSYhATwJvw2uYxd3aoXplMSe0g9XbwK7bmxNes7+FGO0rB/xC0g== + dependencies: + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-member-expression-to-functions" "^7.18.6" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-simple-access@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" + integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-skip-transparent-expression-wrappers@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.6.tgz#7dff00a5320ca4cf63270e5a0eca4b268b7380d9" + integrity sha512-4KoLhwGS9vGethZpAhYnMejWkX64wsnHPDwvOsKWU6Fg4+AlK2Jz3TyjQLMEPvz+1zemi/WBdkYxCD0bAfIkiw== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-validator-identifier@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" + integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helper-wrap-function@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.18.6.tgz#ec44ea4ad9d8988b90c3e465ba2382f4de81a073" + integrity sha512-I5/LZfozwMNbwr/b1vhhuYD+J/mU+gfGAj5td7l5Rv9WYmH6i3Om69WGKNmlIpsVW/mF6O5bvTKbvDQZVgjqOw== + dependencies: + "@babel/helper-function-name" "^7.18.6" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helpers@^7.12.5", "@babel/helpers@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.6.tgz#4c966140eaa1fcaa3d5a8c09d7db61077d4debfd" + integrity sha512-vzSiiqbQOghPngUYt/zWGvK3LAsPhz55vc9XNN0xAl2gV4ieShI2OQli5duxWHD+72PZPTKAcfcZDE1Cwc5zsQ== + dependencies: + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.6.tgz#845338edecad65ebffef058d3be851f1d28a63bc" + integrity sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw== + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" + integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.6.tgz#b4e4dbc2cd1acd0133479918f7c6412961c9adb8" + integrity sha512-Udgu8ZRgrBrttVz6A0EVL0SJ1z+RLbIeqsu632SA1hf0awEppD6TvdznoH+orIF8wtFFAV/Enmw9Y+9oV8TQcw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.6" + "@babel/plugin-proposal-optional-chaining" "^7.18.6" + +"@babel/plugin-proposal-async-generator-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz#aedac81e6fc12bb643374656dd5f2605bf743d17" + integrity sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w== + dependencies: + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-remap-async-to-generator" "^7.18.6" + "@babel/plugin-syntax-async-generators" "^7.8.4" + +"@babel/plugin-proposal-class-properties@^7.12.1", "@babel/plugin-proposal-class-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-class-static-block@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" + integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + +"@babel/plugin-proposal-decorators@^7.12.12": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.18.6.tgz#68e9fd0f022b944f84a8824bb28bfaee724d2595" + integrity sha512-gAdhsjaYmiZVxx5vTMiRfj31nB7LhwBJFMSLzeDxc7X4tKLixup0+k9ughn0RcpBrv9E3PBaXJW7jF5TCihAOg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/plugin-syntax-decorators" "^7.18.6" + +"@babel/plugin-proposal-dynamic-import@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" + integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + +"@babel/plugin-proposal-export-default-from@^7.12.1": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.18.6.tgz#121b3ba0152d0020865bc86271c8150e5115abc7" + integrity sha512-oTvzWB16T9cB4j5kX8c8DuUHo/4QtR2P9vnUNKed9xqFP8Jos/IRniz1FiIryn6luDYoltDJSYF7RCpbm2doMg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-export-default-from" "^7.18.6" + +"@babel/plugin-proposal-export-namespace-from@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.6.tgz#1016f0aa5ab383bbf8b3a85a2dcaedf6c8ee7491" + integrity sha512-zr/QcUlUo7GPo6+X1wC98NJADqmy5QTFWWhqeQWiki4XHafJtLl/YMGkmRB2szDD2IYJCCdBTd4ElwhId9T7Xw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" + integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-json-strings" "^7.8.3" + +"@babel/plugin-proposal-logical-assignment-operators@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.6.tgz#3b9cac6f1ffc2aa459d111df80c12020dfc6b665" + integrity sha512-zMo66azZth/0tVd7gmkxOkOjs2rpHyhpcFo565PUP37hSp6hSd9uUKIfTDFMz58BwqgQKhJ9YxtM5XddjXVn+Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" + integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-proposal-numeric-separator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" + integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-proposal-object-rest-spread@7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" + integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== + dependencies: + "@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-object-rest-spread@^7.12.1", "@babel/plugin-proposal-object-rest-spread@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.6.tgz#ec93bba06bfb3e15ebd7da73e953d84b094d5daf" + integrity sha512-9yuM6wr4rIsKa1wlUAbZEazkCrgw2sMPEXCr4Rnwetu7cEW1NydkCWytLuYletbf8vFxdJxFhwEZqMpOx2eZyw== + dependencies: + "@babel/compat-data" "^7.18.6" + "@babel/helper-compilation-targets" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.18.6" + +"@babel/plugin-proposal-optional-catch-binding@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" + integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-proposal-optional-chaining@^7.12.7", "@babel/plugin-proposal-optional-chaining@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.6.tgz#46d4f2ffc20e87fad1d98bc4fa5d466366f6aa0b" + integrity sha512-PatI6elL5eMzoypFAiYDpYQyMtXTn+iMhuxxQt5mAXD4fEmKorpSI3PHd+i3JXBJN3xyA6MvJv7at23HffFHwA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.6" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + +"@babel/plugin-proposal-private-methods@^7.12.1", "@babel/plugin-proposal-private-methods@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" + integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-proposal-private-property-in-object@^7.12.1", "@babel/plugin-proposal-private-property-in-object@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503" + integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + +"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" + integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-class-static-block@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-decorators@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.18.6.tgz#2e45af22835d0b0f8665da2bfd4463649ce5dbc1" + integrity sha512-fqyLgjcxf/1yhyZ6A+yo1u9gJ7eleFQod2lkaUsF9DQ7sbbY3Ligym3L0+I2c0WmqNKDpoD9UTb1AKP3qRMOAQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-default-from@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.18.6.tgz#8df076711a4818c4ce4f23e61d622b0ba2ff84bc" + integrity sha512-Kr//z3ujSVNx6E9z9ih5xXXMqK07VVTuqPmqGe6Mss/zW5XPeLZeSDZoP9ab/hT4wPKqAgjl2PnhPrcpk8Seew== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-flow@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.18.6.tgz#774d825256f2379d06139be0c723c4dd444f3ca1" + integrity sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-import-assertions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz#cd6190500a4fa2fe31990a963ffab4b63e4505e4" + integrity sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@7.12.1": + version "7.12.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" + integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-jsx@^7.12.13", "@babel/plugin-syntax-jsx@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" + integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@7.8.3", "@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-private-property-in-object@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-top-level-await@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz#1c09cd25795c7c2b8a4ba9ae49394576d4133285" + integrity sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-arrow-functions@^7.12.1", "@babel/plugin-transform-arrow-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" + integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-async-to-generator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" + integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== + dependencies: + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-remap-async-to-generator" "^7.18.6" + +"@babel/plugin-transform-block-scoped-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" + integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-block-scoping@^7.12.12", "@babel/plugin-transform-block-scoping@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.6.tgz#b5f78318914615397d86a731ef2cc668796a726c" + integrity sha512-pRqwb91C42vs1ahSAWJkxOxU1RHWDn16XAa6ggQ72wjLlWyYeAcLvTtE0aM8ph3KNydy9CQF2nLYcjq1WysgxQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-classes@^7.12.1", "@babel/plugin-transform-classes@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.6.tgz#3501a8f3f4c7d5697c27a3eedbee71d68312669f" + integrity sha512-XTg8XW/mKpzAF3actL554Jl/dOYoJtv3l8fxaEczpgz84IeeVf+T1u2CSvPHuZbt0w3JkIx4rdn/MRQI7mo0HQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.6.tgz#5d15eb90e22e69604f3348344c91165c5395d032" + integrity sha512-9repI4BhNrR0KenoR9vm3/cIc1tSBIo+u1WVjKCAynahj25O8zfbiE6JtAtHPGQSs4yZ+bA8mRasRP+qc+2R5A== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-destructuring@^7.12.1", "@babel/plugin-transform-destructuring@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.6.tgz#a98b0e42c7ffbf5eefcbcf33280430f230895c6f" + integrity sha512-tgy3u6lRp17ilY8r1kP4i2+HDUwxlVqq3RTc943eAWSzGgpU1qhiKpqZ5CMyHReIYPHdo3Kg8v8edKtDqSVEyQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" + integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-duplicate-keys@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.6.tgz#e6c94e8cd3c9dd8a88144f7b78ae22975a7ff473" + integrity sha512-NJU26U/208+sxYszf82nmGYqVF9QN8py2HFTblPT9hbawi8+1C5a9JubODLTGFuT0qlkqVinmkwOD13s0sZktg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-exponentiation-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" + integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-flow-strip-types@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.18.6.tgz#6d3dd9f9c0fe13349428569fef00b31310bb3f9f" + integrity sha512-wE0xtA7csz+hw4fKPwxmu5jnzAsXPIO57XnRwzXP3T19jWh1BODnPGoG9xKYwvAwusP7iUktHayRFbMPGtODaQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-flow" "^7.18.6" + +"@babel/plugin-transform-for-of@^7.12.1", "@babel/plugin-transform-for-of@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.6.tgz#e0fdb813be908e91ccc9ec87b30cc2eabf046f7c" + integrity sha512-WAjoMf4wIiSsy88KmG7tgj2nFdEK7E46tArVtcgED7Bkj6Fg/tG5SbvNIOKxbFS2VFgNh6+iaPswBeQZm4ox8w== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-function-name@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.6.tgz#6a7e4ae2893d336fd1b8f64c9f92276391d0f1b4" + integrity sha512-kJha/Gbs5RjzIu0CxZwf5e3aTTSlhZnHMT8zPWnJMjNpLOUgqevg+PN5oMH68nMCXnfiMo4Bhgxqj59KHTlAnA== + dependencies: + "@babel/helper-compilation-targets" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.6.tgz#9d6af353b5209df72960baf4492722d56f39a205" + integrity sha512-x3HEw0cJZVDoENXOp20HlypIHfl0zMIhMVZEBVTfmqbObIpsMxMbmU5nOEO8R7LYT+z5RORKPlTI5Hj4OsO9/Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-member-expression-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" + integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-modules-amd@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz#8c91f8c5115d2202f277549848874027d7172d21" + integrity sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg== + dependencies: + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-commonjs@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz#afd243afba166cca69892e24a8fd8c9f2ca87883" + integrity sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q== + dependencies: + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-simple-access" "^7.18.6" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-systemjs@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.6.tgz#026511b7657d63bf5d4cf2fd4aeb963139914a54" + integrity sha512-UbPYpXxLjTw6w6yXX2BYNxF3p6QY225wcTkfQCy3OMnSlS/C3xGtwUjEzGkldb/sy6PWLiCQ3NbYfjWUTI3t4g== + dependencies: + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-identifier" "^7.18.6" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-umd@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" + integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== + dependencies: + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz#c89bfbc7cc6805d692f3a49bc5fc1b630007246d" + integrity sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-new-target@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" + integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-object-super@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" + integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + +"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.6.tgz#cbe03d5a4c6385dd756034ac1baa63c04beab8dc" + integrity sha512-FjdqgMv37yVl/gwvzkcB+wfjRI8HQmc5EgOG9iGNvUY1ok+TjsoaMP7IqCDZBhkFcM5f3OPVMs6Dmp03C5k4/A== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-property-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" + integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-display-name@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" + integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-react-jsx-development@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" + integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.18.6" + +"@babel/plugin-transform-react-jsx@^7.12.12", "@babel/plugin-transform-react-jsx@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.6.tgz#2721e96d31df96e3b7ad48ff446995d26bc028ff" + integrity sha512-Mz7xMPxoy9kPS/JScj6fJs03TZ/fZ1dJPlMjRAgTaxaS0fUBk8FV/A2rRgfPsVCZqALNwMexD+0Uaf5zlcKPpw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-jsx" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/plugin-transform-react-pure-annotations@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844" + integrity sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-regenerator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73" + integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + regenerator-transform "^0.15.0" + +"@babel/plugin-transform-reserved-words@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" + integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-shorthand-properties@^7.12.1", "@babel/plugin-transform-shorthand-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" + integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-spread@^7.12.1", "@babel/plugin-transform-spread@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.6.tgz#82b080241965f1689f0a60ecc6f1f6575dbdb9d6" + integrity sha512-ayT53rT/ENF8WWexIRg9AiV9h0aIteyWn5ptfZTZQrjk/+f3WdrJGCY4c9wcgl2+MKkKPhzbYp97FTsquZpDCw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.6" + +"@babel/plugin-transform-sticky-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" + integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-template-literals@^7.12.1", "@babel/plugin-transform-template-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.6.tgz#b763f4dc9d11a7cce58cf9a490d82e80547db9c2" + integrity sha512-UuqlRrQmT2SWRvahW46cGSany0uTlcj8NYOS5sRGYi8FxPYPoLd5DDmMd32ZXEj2Jq+06uGVQKHxa/hJx2EzKw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-typeof-symbol@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.6.tgz#486bb39d5a18047358e0d04dc0d2f322f0b92e92" + integrity sha512-7m71iS/QhsPk85xSjFPovHPcH3H9qeyzsujhTc+vcdnsXavoWYJ74zx0lP5RhpC5+iDnVLO+PPMHzC11qels1g== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-typescript@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.6.tgz#8f4ade1a9cf253e5cf7c7c20173082c2c08a50a7" + integrity sha512-ijHNhzIrLj5lQCnI6aaNVRtGVuUZhOXFLRVFs7lLrkXTHip4FKty5oAuQdk4tywG0/WjXmjTfQCWmuzrvFer1w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-typescript" "^7.18.6" + +"@babel/plugin-transform-unicode-escapes@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz#0d01fb7fb2243ae1c033f65f6e3b4be78db75f27" + integrity sha512-XNRwQUXYMP7VLuy54cr/KS/WeL3AZeORhrmeZ7iewgu+X2eBqmpaLI/hzqr9ZxCeUoq0ASK4GUzSM0BDhZkLFw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-unicode-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" + integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/preset-env@^7.12.11", "@babel/preset-env@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.18.6.tgz#953422e98a5f66bc56cd0b9074eaea127ec86ace" + integrity sha512-WrthhuIIYKrEFAwttYzgRNQ5hULGmwTj+D6l7Zdfsv5M7IWV/OZbUfbeL++Qrzx1nVJwWROIFhCHRYQV4xbPNw== + dependencies: + "@babel/compat-data" "^7.18.6" + "@babel/helper-compilation-targets" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.6" + "@babel/plugin-proposal-async-generator-functions" "^7.18.6" + "@babel/plugin-proposal-class-properties" "^7.18.6" + "@babel/plugin-proposal-class-static-block" "^7.18.6" + "@babel/plugin-proposal-dynamic-import" "^7.18.6" + "@babel/plugin-proposal-export-namespace-from" "^7.18.6" + "@babel/plugin-proposal-json-strings" "^7.18.6" + "@babel/plugin-proposal-logical-assignment-operators" "^7.18.6" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" + "@babel/plugin-proposal-numeric-separator" "^7.18.6" + "@babel/plugin-proposal-object-rest-spread" "^7.18.6" + "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" + "@babel/plugin-proposal-optional-chaining" "^7.18.6" + "@babel/plugin-proposal-private-methods" "^7.18.6" + "@babel/plugin-proposal-private-property-in-object" "^7.18.6" + "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.18.6" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-transform-arrow-functions" "^7.18.6" + "@babel/plugin-transform-async-to-generator" "^7.18.6" + "@babel/plugin-transform-block-scoped-functions" "^7.18.6" + "@babel/plugin-transform-block-scoping" "^7.18.6" + "@babel/plugin-transform-classes" "^7.18.6" + "@babel/plugin-transform-computed-properties" "^7.18.6" + "@babel/plugin-transform-destructuring" "^7.18.6" + "@babel/plugin-transform-dotall-regex" "^7.18.6" + "@babel/plugin-transform-duplicate-keys" "^7.18.6" + "@babel/plugin-transform-exponentiation-operator" "^7.18.6" + "@babel/plugin-transform-for-of" "^7.18.6" + "@babel/plugin-transform-function-name" "^7.18.6" + "@babel/plugin-transform-literals" "^7.18.6" + "@babel/plugin-transform-member-expression-literals" "^7.18.6" + "@babel/plugin-transform-modules-amd" "^7.18.6" + "@babel/plugin-transform-modules-commonjs" "^7.18.6" + "@babel/plugin-transform-modules-systemjs" "^7.18.6" + "@babel/plugin-transform-modules-umd" "^7.18.6" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.18.6" + "@babel/plugin-transform-new-target" "^7.18.6" + "@babel/plugin-transform-object-super" "^7.18.6" + "@babel/plugin-transform-parameters" "^7.18.6" + "@babel/plugin-transform-property-literals" "^7.18.6" + "@babel/plugin-transform-regenerator" "^7.18.6" + "@babel/plugin-transform-reserved-words" "^7.18.6" + "@babel/plugin-transform-shorthand-properties" "^7.18.6" + "@babel/plugin-transform-spread" "^7.18.6" + "@babel/plugin-transform-sticky-regex" "^7.18.6" + "@babel/plugin-transform-template-literals" "^7.18.6" + "@babel/plugin-transform-typeof-symbol" "^7.18.6" + "@babel/plugin-transform-unicode-escapes" "^7.18.6" + "@babel/plugin-transform-unicode-regex" "^7.18.6" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.18.6" + babel-plugin-polyfill-corejs2 "^0.3.1" + babel-plugin-polyfill-corejs3 "^0.5.2" + babel-plugin-polyfill-regenerator "^0.3.1" + core-js-compat "^3.22.1" + semver "^6.3.0" + +"@babel/preset-flow@^7.12.1": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.18.6.tgz#83f7602ba566e72a9918beefafef8ef16d2810cb" + integrity sha512-E7BDhL64W6OUqpuyHnSroLnqyRTcG6ZdOBl1OKI/QK/HJfplqK/S3sq1Cckx7oTodJ5yOXyfw7rEADJ6UjoQDQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-flow-strip-types" "^7.18.6" + +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== + 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" + +"@babel/preset-react@^7.12.10", "@babel/preset-react@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" + integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-react-display-name" "^7.18.6" + "@babel/plugin-transform-react-jsx" "^7.18.6" + "@babel/plugin-transform-react-jsx-development" "^7.18.6" + "@babel/plugin-transform-react-pure-annotations" "^7.18.6" + +"@babel/preset-typescript@^7.12.7", "@babel/preset-typescript@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" + integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-typescript" "^7.18.6" + +"@babel/register@^7.12.1": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.18.6.tgz#48a4520f1b2a7d7ac861e8148caeb0cefe6c59db" + integrity sha512-tkYtONzaO8rQubZzpBnvZPFcHgh8D9F55IjOsYton4X2IBoyRn2ZSWQqySTZnUn2guZbxbQiAB27hJEbvXamhQ== + dependencies: + clone-deep "^4.0.1" + find-cache-dir "^2.0.0" + make-dir "^2.1.0" + pirates "^4.0.5" + source-map-support "^0.5.16" + +"@babel/runtime@7.7.2": + version "7.7.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.2.tgz#111a78002a5c25fc8e3361bedc9529c696b85a6a" + integrity sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw== + dependencies: + regenerator-runtime "^0.13.2" + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.17.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580" + integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/runtime@~7.5.4": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132" + integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ== + dependencies: + regenerator-runtime "^0.13.2" + +"@babel/template@^7.12.7", "@babel/template@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31" + integrity sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/traverse@^7.1.6", "@babel/traverse@^7.12.11", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.6.tgz#a228562d2f46e89258efa4ddd0416942e2fd671d" + integrity sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.18.6" + "@babel/types" "^7.18.6" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.12.11", "@babel/types@^7.12.7", "@babel/types@^7.18.6", "@babel/types@^7.18.7", "@babel/types@^7.2.0", "@babel/types@^7.4.4": + version "7.18.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.7.tgz#a4a2c910c15040ea52cdd1ddb1614a65c8041726" + integrity sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + to-fast-properties "^2.0.0" + +"@base2/pretty-print-object@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz#371ba8be66d556812dc7fb169ebc3c08378f69d4" + integrity sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA== + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@cnakazawa/watch@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" + integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ== + dependencies: + exec-sh "^0.3.2" + minimist "^1.2.0" + +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== + +"@design-systems/utils@2.12.0": + version "2.12.0" + resolved "https://registry.yarnpkg.com/@design-systems/utils/-/utils-2.12.0.tgz#955c108be07cb8f01532207cbfea8f848fa760c9" + integrity sha512-Y/d2Zzr+JJfN6u1gbuBUb1ufBuLMJJRZQk+dRmw8GaTpqKx5uf7cGUYGTwN02dIb3I+Tf+cW8jcGBTRiFxdYFg== + dependencies: + "@babel/runtime" "^7.11.2" + clsx "^1.0.4" + focus-lock "^0.8.0" + react-merge-refs "^1.0.0" + +"@devtools-ds/object-inspector@^1.1.2": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@devtools-ds/object-inspector/-/object-inspector-1.2.0.tgz#64a132fbd4159affa5a87c8cf6cf8540c337aed2" + integrity sha512-VztcwqVwScSvYdvJVZBJYsVO/2Pew3JPpFV3T9fuCHQLlHcLYOV3aU/kBS2ScuE2O1JN0ZbobLqFLa3vQF54Fw== + dependencies: + "@babel/runtime" "7.7.2" + "@devtools-ds/object-parser" "^1.2.0" + "@devtools-ds/themes" "^1.2.0" + "@devtools-ds/tree" "^1.2.0" + clsx "1.1.0" + +"@devtools-ds/object-parser@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@devtools-ds/object-parser/-/object-parser-1.2.0.tgz#8da39bf481687afdf113c78dbac5ced6fd8e30d1" + integrity sha512-SjGGyiFFY8dtUpiWXAvRSzRT+hE11EAAysrq2PsC/GVLf2ZLyT2nHlQO5kDStywyTz+fjw7S7pyDRj1HG9YTTA== + dependencies: + "@babel/runtime" "~7.5.4" + +"@devtools-ds/themes@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@devtools-ds/themes/-/themes-1.2.0.tgz#2fda60af9741e97bc09257b512e49a7aecf6f4bc" + integrity sha512-LimEITorE6yWZWWuMc6OiBfLQgPrQqWbyMEmfRUDPa3PHXoAY4SpDxczfg31fgyRDUNWnZhjaJH5bBbu8VEbIw== + dependencies: + "@babel/runtime" "~7.5.4" + "@design-systems/utils" "2.12.0" + clsx "1.1.0" + +"@devtools-ds/tree@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@devtools-ds/tree/-/tree-1.2.0.tgz#e882d10ae13a30f2aa02e75c3eeb6c44a47a80c3" + integrity sha512-hC4g4ocuo2eg7jsnzKdauxH0sDQiPW3KSM2+uK3kRgcmr9PzpBD5Kob+Y/WFSVKswFleftOGKL4BQLuRv0sPxA== + dependencies: + "@babel/runtime" "7.7.2" + "@devtools-ds/themes" "^1.2.0" + clsx "1.1.0" + +"@discoveryjs/json-ext@^0.5.0", "@discoveryjs/json-ext@^0.5.3": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@emotion/babel-plugin@^11.7.1", "@emotion/babel-plugin@^11.9.2": + version "11.9.2" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz#723b6d394c89fb2ef782229d92ba95a740576e95" + integrity sha512-Pr/7HGH6H6yKgnVFNEj2MVlreu3ADqftqjqwUvDy/OJzKFgxKeTQ+eeUf20FOTuHVkDON2iNa25rAXVYtWJCjw== + dependencies: + "@babel/helper-module-imports" "^7.12.13" + "@babel/plugin-syntax-jsx" "^7.12.13" + "@babel/runtime" "^7.13.10" + "@emotion/hash" "^0.8.0" + "@emotion/memoize" "^0.7.5" + "@emotion/serialize" "^1.0.2" + babel-plugin-macros "^2.6.1" + convert-source-map "^1.5.0" + escape-string-regexp "^4.0.0" + find-root "^1.1.0" + source-map "^0.5.7" + stylis "4.0.13" + +"@emotion/cache@^11.9.3": + version "11.9.3" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.9.3.tgz#96638449f6929fd18062cfe04d79b29b44c0d6cb" + integrity sha512-0dgkI/JKlCXa+lEXviaMtGBL0ynpx4osh7rjOXE71q9bIF8G+XhJgvi+wDu0B0IdCVx37BffiwXlN9I3UuzFvg== + dependencies: + "@emotion/memoize" "^0.7.4" + "@emotion/sheet" "^1.1.1" + "@emotion/utils" "^1.0.0" + "@emotion/weak-memoize" "^0.2.5" + stylis "4.0.13" + +"@emotion/hash@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" + integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== + +"@emotion/is-prop-valid@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.1.3.tgz#f0907a416368cf8df9e410117068e20fe87c0a3a" + integrity sha512-RFg04p6C+1uO19uG8N+vqanzKqiM9eeV1LDOG3bmkYmuOj7NbKNlFC/4EZq5gnwAIlcC/jOT24f8Td0iax2SXA== + dependencies: + "@emotion/memoize" "^0.7.4" + +"@emotion/memoize@^0.7.4", "@emotion/memoize@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" + integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ== + +"@emotion/react@^11.9.3": + version "11.9.3" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.9.3.tgz#f4f4f34444f6654a2e550f5dab4f2d360c101df9" + integrity sha512-g9Q1GcTOlzOEjqwuLF/Zd9LC+4FljjPjDfxSM7KmEakm+hsHXk+bYZ2q+/hTJzr0OUNkujo72pXLQvXj6H+GJQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@emotion/babel-plugin" "^11.7.1" + "@emotion/cache" "^11.9.3" + "@emotion/serialize" "^1.0.4" + "@emotion/utils" "^1.1.0" + "@emotion/weak-memoize" "^0.2.5" + hoist-non-react-statics "^3.3.1" + +"@emotion/serialize@^1.0.2", "@emotion/serialize@^1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.4.tgz#ff31fd11bb07999611199c2229e152faadc21a3c" + integrity sha512-1JHamSpH8PIfFwAMryO2bNka+y8+KA5yga5Ocf2d7ZEiJjb7xlLW7aknBGZqJLajuLOvJ+72vN+IBSwPlXD1Pg== + dependencies: + "@emotion/hash" "^0.8.0" + "@emotion/memoize" "^0.7.4" + "@emotion/unitless" "^0.7.5" + "@emotion/utils" "^1.0.0" + csstype "^3.0.2" + +"@emotion/sheet@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.1.1.tgz#015756e2a9a3c7c5f11d8ec22966a8dbfbfac787" + integrity sha512-J3YPccVRMiTZxYAY0IOq3kd+hUP8idY8Kz6B/Cyo+JuXq52Ek+zbPbSQUrVQp95aJ+lsAW7DPL1P2Z+U1jGkKA== + +"@emotion/styled@^11.9.3": + version "11.9.3" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.9.3.tgz#47f0c71137fec7c57035bf3659b52fb536792340" + integrity sha512-o3sBNwbtoVz9v7WB1/Y/AmXl69YHmei2mrVnK7JgyBJ//Rst5yqPZCecEJlMlJrFeWHp+ki/54uN265V2pEcXA== + dependencies: + "@babel/runtime" "^7.13.10" + "@emotion/babel-plugin" "^11.7.1" + "@emotion/is-prop-valid" "^1.1.3" + "@emotion/serialize" "^1.0.4" + "@emotion/utils" "^1.1.0" + +"@emotion/unitless@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" + integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== + +"@emotion/utils@^1.0.0", "@emotion/utils@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.1.0.tgz#86b0b297f3f1a0f2bdb08eeac9a2f49afd40d0cf" + integrity sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ== + +"@emotion/weak-memoize@^0.2.5": + version "0.2.5" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" + integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== + +"@eslint/eslintrc@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f" + integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.3.2" + globals "^13.15.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@gar/promisify@^1.0.1": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" + integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== + +"@humanwhocodes/config-array@^0.9.2": + version "0.9.5" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" + integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/transform@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" + integrity sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^26.6.2" + babel-plugin-istanbul "^6.0.0" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.4" + jest-haste-map "^26.6.2" + jest-regex-util "^26.0.0" + jest-util "^26.6.2" + micromatch "^4.0.2" + pirates "^4.0.1" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + +"@jest/types@^27.5.1": + version "27.5.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80" + integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.0.8" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz#687cc2bbf243f4e9a868ecf2262318e2658873a1" + integrity sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.7", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.14" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" + integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" + integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + +"@mdx-js/mdx@^1.6.22": + version "1.6.22" + resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.22.tgz#8a723157bf90e78f17dc0f27995398e6c731f1ba" + integrity sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA== + dependencies: + "@babel/core" "7.12.9" + "@babel/plugin-syntax-jsx" "7.12.1" + "@babel/plugin-syntax-object-rest-spread" "7.8.3" + "@mdx-js/util" "1.6.22" + babel-plugin-apply-mdx-type-prop "1.6.22" + babel-plugin-extract-import-names "1.6.22" + camelcase-css "2.0.1" + detab "2.0.4" + hast-util-raw "6.0.1" + lodash.uniq "4.5.0" + mdast-util-to-hast "10.0.1" + remark-footnotes "2.0.0" + remark-mdx "1.6.22" + remark-parse "8.0.3" + remark-squeeze-paragraphs "4.0.0" + style-to-object "0.3.0" + unified "9.2.0" + unist-builder "2.0.3" + unist-util-visit "2.0.3" + +"@mdx-js/react@^1.6.22": + version "1.6.22" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.22.tgz#ae09b4744fddc74714ee9f9d6f17a66e77c43573" + integrity sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg== + +"@mdx-js/util@1.6.22": + version "1.6.22" + resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" + integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== + +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" + integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== + dependencies: + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" + integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@npmcli/fs@^1.0.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" + integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== + dependencies: + "@gar/promisify" "^1.0.1" + semver "^7.3.5" + +"@npmcli/move-file@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" + integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== + dependencies: + mkdirp "^1.0.4" + rimraf "^3.0.2" + +"@pmmmwh/react-refresh-webpack-plugin@^0.5.3": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.7.tgz#58f8217ba70069cc6a73f5d7e05e85b458c150e2" + integrity sha512-bcKCAzF0DV2IIROp9ZHkRJa6O4jy7NlnHdWL3GmcUxYWNjLXkK5kfELELwEfSP5hXPfVL/qOGMAROuMQb9GG8Q== + dependencies: + ansi-html-community "^0.0.8" + common-path-prefix "^3.0.0" + core-js-pure "^3.8.1" + error-stack-parser "^2.0.6" + find-up "^5.0.0" + html-entities "^2.1.0" + loader-utils "^2.0.0" + schema-utils "^3.0.0" + source-map "^0.7.3" + +"@storybook/addon-actions@6.5.9", "@storybook/addon-actions@^6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-6.5.9.tgz#d50d65631403e1a5b680961429d9c0d7bd383e68" + integrity sha512-wDYm3M1bN+zcYZV3Q24M03b/P8DDpvj1oSoY6VLlxDAi56h8qZB/voeIS2I6vWXOB79C5tbwljYNQO0GsufS0g== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/theming" "6.5.9" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.21" + polished "^4.2.2" + prop-types "^15.7.2" + react-inspector "^5.1.0" + regenerator-runtime "^0.13.7" + telejson "^6.0.8" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + uuid-browser "^3.1.0" + +"@storybook/addon-backgrounds@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-6.5.9.tgz#a9579fc9d73f783a768c6c6ceb97193c5a1ee708" + integrity sha512-9k+GiY5aiANLOct34ar29jqgdi5ZpCqpZ86zPH0GsEC6ifH6nzP4trLU0vFUe260XDCvB4g8YaI7JZKPhozERg== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/theming" "6.5.9" + core-js "^3.8.2" + global "^4.4.0" + memoizerific "^1.11.3" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + +"@storybook/addon-controls@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-controls/-/addon-controls-6.5.9.tgz#8f6ef939c87b3dbad98f8bda7e124f0b34f668d2" + integrity sha512-VvjkgK32bGURKyWU2No6Q2B0RQZjLZk8D3neVNCnrWxwrl1G82StegxjRPn/UZm9+MZVPvTvI46nj1VdgOktnw== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/core-common" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/node-logger" "6.5.9" + "@storybook/store" "6.5.9" + "@storybook/theming" "6.5.9" + core-js "^3.8.2" + lodash "^4.17.21" + ts-dedent "^2.0.0" + +"@storybook/addon-docs@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-docs/-/addon-docs-6.5.9.tgz#32b27fb298624afd738c1371a764d7ff4831fe6d" + integrity sha512-9lwOZyiOJFUgGd9ADVfcgpels5o0XOXqGMeVLuzT1160nopbZjNjo/3+YLJ0pyHRPpMJ4rmq2+vxRQR6PVRgPg== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.12.12" + "@babel/preset-env" "^7.12.11" + "@jest/transform" "^26.6.2" + "@mdx-js/react" "^1.6.22" + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/core-common" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/docs-tools" "6.5.9" + "@storybook/mdx1-csf" "^0.0.1" + "@storybook/node-logger" "6.5.9" + "@storybook/postinstall" "6.5.9" + "@storybook/preview-web" "6.5.9" + "@storybook/source-loader" "6.5.9" + "@storybook/store" "6.5.9" + "@storybook/theming" "6.5.9" + babel-loader "^8.0.0" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.21" + regenerator-runtime "^0.13.7" + remark-external-links "^8.0.0" + remark-slug "^6.0.0" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + +"@storybook/addon-essentials@^6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-essentials/-/addon-essentials-6.5.9.tgz#32ba63acba4d153f4cf6ac33cbbf14b87d260788" + integrity sha512-V9ThjKQsde4A2Es20pLFBsn0MWx2KCJuoTcTsANP4JDcbvEmj8UjbDWbs8jAU+yzJT5r+CI6NoWmQudv12ZOgw== + dependencies: + "@storybook/addon-actions" "6.5.9" + "@storybook/addon-backgrounds" "6.5.9" + "@storybook/addon-controls" "6.5.9" + "@storybook/addon-docs" "6.5.9" + "@storybook/addon-measure" "6.5.9" + "@storybook/addon-outline" "6.5.9" + "@storybook/addon-toolbars" "6.5.9" + "@storybook/addon-viewport" "6.5.9" + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/core-common" "6.5.9" + "@storybook/node-logger" "6.5.9" + core-js "^3.8.2" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" + +"@storybook/addon-interactions@^6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-interactions/-/addon-interactions-6.5.9.tgz#4356e96beae8f44000955d8870c3acc6c8d1fb3a" + integrity sha512-p3xBbrhmYTHvRO8MqAIr2DucgrXt38nJE71rogLNLsJ01rUN4JsLI8OkQAMQbqfIpwC27irMjQxJTp4HSzkFJA== + dependencies: + "@devtools-ds/object-inspector" "^1.1.2" + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/core-common" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/instrumenter" "6.5.9" + "@storybook/theming" "6.5.9" + core-js "^3.8.2" + global "^4.4.0" + jest-mock "^27.0.6" + polished "^4.2.2" + ts-dedent "^2.2.0" + +"@storybook/addon-links@^6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-6.5.9.tgz#91cbca0c044796badf2498723fdd10dacea5748b" + integrity sha512-4BYC7pkxL3NLRnEgTA9jpIkObQKril+XFj1WtmY/lngF90vvK0Kc/TtvTA2/5tSgrHfxEuPevIdxMIyLJ4ejWQ== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/router" "6.5.9" + "@types/qs" "^6.9.5" + core-js "^3.8.2" + global "^4.4.0" + prop-types "^15.7.2" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" + +"@storybook/addon-measure@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-measure/-/addon-measure-6.5.9.tgz#f949d4f5f4025c839634114365f1399ea04bd0ae" + integrity sha512-0aA22wD0CIEUccsEbWkckCOXOwr4VffofMH1ToVCOeqBoyLOMB0gxFubESeprqM54CWsYh2DN1uujgD6508cwA== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + core-js "^3.8.2" + global "^4.4.0" + +"@storybook/addon-outline@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-outline/-/addon-outline-6.5.9.tgz#6ce9b3fb77e6a1a59607d7657c359c69f26cf6dd" + integrity sha512-oJ1DK3BDJr6aTlZc9axfOxV1oDkZO7hOohgUQDaKO1RZrSpyQsx2ViK2X6p/W7JhFJHKh7rv+nGCaVlLz3YIZA== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + core-js "^3.8.2" + global "^4.4.0" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" + +"@storybook/addon-toolbars@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-toolbars/-/addon-toolbars-6.5.9.tgz#feedfdac08482d43bb1f3cc00840d80322c5eace" + integrity sha512-6JFQNHYVZUwp17p5rppc+iQJ2QOIWPTF+ni1GMMThjc84mzXs2+899Sf1aPFTvrFJTklmT+bPX6x4aUTouVa1w== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/theming" "6.5.9" + core-js "^3.8.2" + regenerator-runtime "^0.13.7" + +"@storybook/addon-viewport@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-viewport/-/addon-viewport-6.5.9.tgz#fc390ccebea56d2e874ed2fda085c09fe04dd240" + integrity sha512-thKS+iw6M7ueDQQ7M66STZ5rgtJKliAcIX6UCopo0Ffh4RaRYmX6MCjqtvBKk8joyXUvm9SpWQemJD9uBQrjgw== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/theming" "6.5.9" + core-js "^3.8.2" + global "^4.4.0" + memoizerific "^1.11.3" + prop-types "^15.7.2" + regenerator-runtime "^0.13.7" + +"@storybook/addons@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.5.9.tgz#5a9d7395c579a9cbc44dfc122362fb3c95dfb9d5" + integrity sha512-adwdiXg+mntfPocLc1KXjZXyLgGk7Aac699Fwe+OUYPEC5tW347Rm/kFatcE556d42o5czcRiq3ZSIGWnm9ieQ== + dependencies: + "@storybook/api" "6.5.9" + "@storybook/channels" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/router" "6.5.9" + "@storybook/theming" "6.5.9" + "@types/webpack-env" "^1.16.0" + core-js "^3.8.2" + global "^4.4.0" + regenerator-runtime "^0.13.7" + +"@storybook/api@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.5.9.tgz#303733214c9de0422d162f7c54ae05d088b89bf9" + integrity sha512-9ylztnty4Y+ALU/ehW3BML9czjCAFsWvrwuCi6UgcwNjswwjSX3VRLhfD1KT3pl16ho//95LgZ0LnSwROCcPOA== + dependencies: + "@storybook/channels" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/router" "6.5.9" + "@storybook/semver" "^7.3.2" + "@storybook/theming" "6.5.9" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + regenerator-runtime "^0.13.7" + store2 "^2.12.0" + telejson "^6.0.8" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + +"@storybook/builder-webpack4@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/builder-webpack4/-/builder-webpack4-6.5.9.tgz#4b37e1fa23a25aa4bfeaba640e5d318fcd511f95" + integrity sha512-YOeA4++9uRZ8Hog1wC60yjaxBOiI1FRQNtax7b9E7g+kP8UlSCPCGcv4gls9hFmzbzTOPfQTWnToA9Oa6jzRVw== + dependencies: + "@babel/core" "^7.12.10" + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/channel-postmessage" "6.5.9" + "@storybook/channels" "6.5.9" + "@storybook/client-api" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/core-common" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/node-logger" "6.5.9" + "@storybook/preview-web" "6.5.9" + "@storybook/router" "6.5.9" + "@storybook/semver" "^7.3.2" + "@storybook/store" "6.5.9" + "@storybook/theming" "6.5.9" + "@storybook/ui" "6.5.9" + "@types/node" "^14.0.10 || ^16.0.0" + "@types/webpack" "^4.41.26" + autoprefixer "^9.8.6" + babel-loader "^8.0.0" + case-sensitive-paths-webpack-plugin "^2.3.0" + core-js "^3.8.2" + css-loader "^3.6.0" + file-loader "^6.2.0" + find-up "^5.0.0" + fork-ts-checker-webpack-plugin "^4.1.6" + glob "^7.1.6" + glob-promise "^3.4.0" + global "^4.4.0" + html-webpack-plugin "^4.0.0" + pnp-webpack-plugin "1.6.4" + postcss "^7.0.36" + postcss-flexbugs-fixes "^4.2.1" + postcss-loader "^4.2.0" + raw-loader "^4.0.2" + stable "^0.1.8" + style-loader "^1.3.0" + terser-webpack-plugin "^4.2.3" + ts-dedent "^2.0.0" + url-loader "^4.1.1" + util-deprecate "^1.0.2" + webpack "4" + webpack-dev-middleware "^3.7.3" + webpack-filter-warnings-plugin "^1.2.1" + webpack-hot-middleware "^2.25.1" + webpack-virtual-modules "^0.2.2" + +"@storybook/builder-webpack5@^6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/builder-webpack5/-/builder-webpack5-6.5.9.tgz#30b4e08622daff104bcccd015d3ee7902f99dd99" + integrity sha512-NUVZ4Qci6HWPuoH8U/zQkdBO5soGgu7QYrGC/LWU0tRfmmZxkjr7IUU14ppDpGPYgx3r7jkaQI1J/E1YEmSCWQ== + dependencies: + "@babel/core" "^7.12.10" + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/channel-postmessage" "6.5.9" + "@storybook/channels" "6.5.9" + "@storybook/client-api" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/core-common" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/node-logger" "6.5.9" + "@storybook/preview-web" "6.5.9" + "@storybook/router" "6.5.9" + "@storybook/semver" "^7.3.2" + "@storybook/store" "6.5.9" + "@storybook/theming" "6.5.9" + "@types/node" "^14.0.10 || ^16.0.0" + babel-loader "^8.0.0" + babel-plugin-named-exports-order "^0.0.2" + browser-assert "^1.2.1" + case-sensitive-paths-webpack-plugin "^2.3.0" + core-js "^3.8.2" + css-loader "^5.0.1" + fork-ts-checker-webpack-plugin "^6.0.4" + glob "^7.1.6" + glob-promise "^3.4.0" + html-webpack-plugin "^5.0.0" + path-browserify "^1.0.1" + process "^0.11.10" + stable "^0.1.8" + style-loader "^2.0.0" + terser-webpack-plugin "^5.0.3" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + webpack "^5.9.0" + webpack-dev-middleware "^4.1.0" + webpack-hot-middleware "^2.25.1" + webpack-virtual-modules "^0.4.1" + +"@storybook/channel-postmessage@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.5.9.tgz#9cf4530f0364cee0d5e58f92d6fb5ce98e10257b" + integrity sha512-pX/0R8UW7ezBhCrafRaL20OvMRcmESYvQQCDgjqSzJyHkcG51GOhsd6Ge93eJ6QvRMm9+w0Zs93N2VKjVtz0Qw== + dependencies: + "@storybook/channels" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/core-events" "6.5.9" + core-js "^3.8.2" + global "^4.4.0" + qs "^6.10.0" + telejson "^6.0.8" + +"@storybook/channel-websocket@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/channel-websocket/-/channel-websocket-6.5.9.tgz#6b7a0127fec58ee5be4f6aebcf460adc564f2f34" + integrity sha512-xtHvSNwuOhkgALwVshKWsoFhDmuvcosdYfxcfFGEiYKXIu46tRS5ZXmpmgEC/0JAVkVoFj5nL8bV7IY5np6oaA== + dependencies: + "@storybook/channels" "6.5.9" + "@storybook/client-logger" "6.5.9" + core-js "^3.8.2" + global "^4.4.0" + telejson "^6.0.8" + +"@storybook/channels@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.5.9.tgz#abfab89a6587a2688e9926d4aafeb11c9d8b2e79" + integrity sha512-FvGA35nV38UPXWOl9ERapFTJaxwSTamQ339s2Ev7E9riyRG+GRkgTWzf5kECJgS1PAYKd/7m/RqKJT9BVv6A5g== + dependencies: + core-js "^3.8.2" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + +"@storybook/client-api@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.5.9.tgz#3e4a8ec1d277fd81325c5d959c553161a85fa182" + integrity sha512-pc7JKJoWLesixUKvG2nV36HukUuYoGRyAgD3PpIV7qSBS4JixqZ3VAHFUtqV1UzfOSQTovLSl4a0rIRnpie6gA== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/channel-postmessage" "6.5.9" + "@storybook/channels" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/store" "6.5.9" + "@types/qs" "^6.9.5" + "@types/webpack-env" "^1.16.0" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + store2 "^2.12.0" + synchronous-promise "^2.0.15" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + +"@storybook/client-logger@6.5.9", "@storybook/client-logger@^6.4.0": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.5.9.tgz#dc1669abe8c45af1cc38f74c6f4b15ff33e63014" + integrity sha512-DOHL6p0uiDd3gV/Sb2FR+Vh6OiPrrf8BrA06uvXWsMRIIvEEvnparxv9EvPg7FlmUX0T3nq7d3juwjx4F8Wbcg== + dependencies: + core-js "^3.8.2" + global "^4.4.0" + +"@storybook/components@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.5.9.tgz#97e07ffe11ab76c01ccee380888991bd161f75b2" + integrity sha512-BhfX980O9zn/1J4FNMeDo8ZvL1m5Ml3T4HRpfYmEBnf8oW5b5BeF6S2K2cwFStZRjWqm1feUcwNpZxCBVMkQnQ== + dependencies: + "@storybook/client-logger" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/theming" "6.5.9" + "@types/react-syntax-highlighter" "11.0.5" + core-js "^3.8.2" + memoizerific "^1.11.3" + qs "^6.10.0" + react-syntax-highlighter "^15.4.5" + regenerator-runtime "^0.13.7" + util-deprecate "^1.0.2" + +"@storybook/core-client@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/core-client/-/core-client-6.5.9.tgz#ea6035d1c90d2c68e860e3cf629979491856cd88" + integrity sha512-LY0QbhShowO+PQx3gao3wdVjpKMH1AaSLmuI95FrcjoMmSXGf96jVLKQp9mJRGeHIsAa93EQBYuCihZycM3Kbg== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/channel-postmessage" "6.5.9" + "@storybook/channel-websocket" "6.5.9" + "@storybook/client-api" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/preview-web" "6.5.9" + "@storybook/store" "6.5.9" + "@storybook/ui" "6.5.9" + airbnb-js-shims "^2.2.1" + ansi-to-html "^0.6.11" + core-js "^3.8.2" + global "^4.4.0" + lodash "^4.17.21" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" + unfetch "^4.2.0" + util-deprecate "^1.0.2" + +"@storybook/core-common@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/core-common/-/core-common-6.5.9.tgz#7ca8258ea2634b1d64695c1e4262f71cc7457989" + integrity sha512-NxOK0mrOCo0TWZ7Npc5HU66EKoRHlrtg18/ZixblLDWQMIqY9XCck8K1kJ8QYpYCHla+aHIsYUArFe2vhlEfZA== + dependencies: + "@babel/core" "^7.12.10" + "@babel/plugin-proposal-class-properties" "^7.12.1" + "@babel/plugin-proposal-decorators" "^7.12.12" + "@babel/plugin-proposal-export-default-from" "^7.12.1" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" + "@babel/plugin-proposal-object-rest-spread" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.7" + "@babel/plugin-proposal-private-methods" "^7.12.1" + "@babel/plugin-proposal-private-property-in-object" "^7.12.1" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.12" + "@babel/plugin-transform-classes" "^7.12.1" + "@babel/plugin-transform-destructuring" "^7.12.1" + "@babel/plugin-transform-for-of" "^7.12.1" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-transform-shorthand-properties" "^7.12.1" + "@babel/plugin-transform-spread" "^7.12.1" + "@babel/preset-env" "^7.12.11" + "@babel/preset-react" "^7.12.10" + "@babel/preset-typescript" "^7.12.7" + "@babel/register" "^7.12.1" + "@storybook/node-logger" "6.5.9" + "@storybook/semver" "^7.3.2" + "@types/node" "^14.0.10 || ^16.0.0" + "@types/pretty-hrtime" "^1.0.0" + babel-loader "^8.0.0" + babel-plugin-macros "^3.0.1" + babel-plugin-polyfill-corejs3 "^0.1.0" + chalk "^4.1.0" + core-js "^3.8.2" + express "^4.17.1" + file-system-cache "^1.0.5" + find-up "^5.0.0" + fork-ts-checker-webpack-plugin "^6.0.4" + fs-extra "^9.0.1" + glob "^7.1.6" + handlebars "^4.7.7" + interpret "^2.2.0" + json5 "^2.1.3" + lazy-universal-dotenv "^3.0.1" + picomatch "^2.3.0" + pkg-dir "^5.0.0" + pretty-hrtime "^1.0.3" + resolve-from "^5.0.0" + slash "^3.0.0" + telejson "^6.0.8" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + webpack "4" + +"@storybook/core-events@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.5.9.tgz#5b0783c7d22a586c0f5e927a61fe1b1223e19637" + integrity sha512-tXt7a3ZvJOCeEKpNa/B5rQM5VI7UJLlOh3IHOImWn4HqoBRrZvbourmac+PRZAtXpos0h3c6554Hjapj/Sny5Q== + dependencies: + core-js "^3.8.2" + +"@storybook/core-server@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-6.5.9.tgz#749a881c1a81d7cf1a69f3782c06a7f0c39a505c" + integrity sha512-YeePGUrd5fQPvGzMhowh124KrcZURFpFXg1VB0Op3ESqCIsInoMZeObci4Gc+binMXC7vcv7aw3EwSLU37qJzQ== + dependencies: + "@discoveryjs/json-ext" "^0.5.3" + "@storybook/builder-webpack4" "6.5.9" + "@storybook/core-client" "6.5.9" + "@storybook/core-common" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/csf-tools" "6.5.9" + "@storybook/manager-webpack4" "6.5.9" + "@storybook/node-logger" "6.5.9" + "@storybook/semver" "^7.3.2" + "@storybook/store" "6.5.9" + "@storybook/telemetry" "6.5.9" + "@types/node" "^14.0.10 || ^16.0.0" + "@types/node-fetch" "^2.5.7" + "@types/pretty-hrtime" "^1.0.0" + "@types/webpack" "^4.41.26" + better-opn "^2.1.1" + boxen "^5.1.2" + chalk "^4.1.0" + cli-table3 "^0.6.1" + commander "^6.2.1" + compression "^1.7.4" + core-js "^3.8.2" + cpy "^8.1.2" + detect-port "^1.3.0" + express "^4.17.1" + fs-extra "^9.0.1" + global "^4.4.0" + globby "^11.0.2" + ip "^2.0.0" + lodash "^4.17.21" + node-fetch "^2.6.7" + open "^8.4.0" + pretty-hrtime "^1.0.3" + prompts "^2.4.0" + regenerator-runtime "^0.13.7" + serve-favicon "^2.5.0" + slash "^3.0.0" + telejson "^6.0.8" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + watchpack "^2.2.0" + webpack "4" + ws "^8.2.3" + x-default-browser "^0.4.0" + +"@storybook/core@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.5.9.tgz#da4f237391d99aed1228323f24b335cafbdf3499" + integrity sha512-Mt3TTQnjQt2/pa60A+bqDsAOrYpohapdtt4DDZEbS8h0V6u11KyYYh3w7FCySlL+sPEyogj63l5Ec76Jah3l2w== + dependencies: + "@storybook/core-client" "6.5.9" + "@storybook/core-server" "6.5.9" + +"@storybook/csf-tools@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/csf-tools/-/csf-tools-6.5.9.tgz#8e01df2305b53e228229f0b45ada3720e6e42a1c" + integrity sha512-RAdhsO2XmEDyWy0qNQvdKMLeIZAuyfD+tYlUwBHRU6DbByDucvwgMOGy5dF97YNJFmyo93EUYJzXjUrJs3U1LQ== + dependencies: + "@babel/core" "^7.12.10" + "@babel/generator" "^7.12.11" + "@babel/parser" "^7.12.11" + "@babel/plugin-transform-react-jsx" "^7.12.12" + "@babel/preset-env" "^7.12.11" + "@babel/traverse" "^7.12.11" + "@babel/types" "^7.12.11" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/mdx1-csf" "^0.0.1" + core-js "^3.8.2" + fs-extra "^9.0.1" + global "^4.4.0" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" + +"@storybook/csf@0.0.2--canary.4566f4d.1": + version "0.0.2--canary.4566f4d.1" + resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.0.2--canary.4566f4d.1.tgz#dac52a21c40ef198554e71fe4d20d61e17f65327" + integrity sha512-9OVvMVh3t9znYZwb0Svf/YQoxX2gVOeQTGe2bses2yj+a3+OJnCrUF3/hGv6Em7KujtOdL2LL+JnG49oMVGFgQ== + dependencies: + lodash "^4.17.15" + +"@storybook/docs-tools@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/docs-tools/-/docs-tools-6.5.9.tgz#5ff304f881e972ce14923a5ffcfed3f052094889" + integrity sha512-UoTaXLvec8x+q+4oYIk/t8DBju9C3ZTGklqOxDIt+0kS3TFAqEgI3JhKXqQOXgN5zDcvLVSxi8dbVAeSxk2ktA== + dependencies: + "@babel/core" "^7.12.10" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/store" "6.5.9" + core-js "^3.8.2" + doctrine "^3.0.0" + lodash "^4.17.21" + regenerator-runtime "^0.13.7" + +"@storybook/instrumenter@6.5.9", "@storybook/instrumenter@^6.4.0": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/instrumenter/-/instrumenter-6.5.9.tgz#885d9dec31b7b7fa6ea29b446105480450e527b8" + integrity sha512-I2nu/6H0MAy8d+d3LY/G6oYEFyWlc8f2Qs2DhpYh5FiCgIpzvY0DMN05Lf8oaXdKHL3lPF/YLJH17FttekXs1w== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/core-events" "6.5.9" + core-js "^3.8.2" + global "^4.4.0" + +"@storybook/manager-webpack4@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/manager-webpack4/-/manager-webpack4-6.5.9.tgz#c75d2cced4550c8a786f00b0e57b203d613e706c" + integrity sha512-49LZlHqWc7zj9tQfOOANixPYmLxqWTTZceA6DSXnKd9xDiO2Gl23Y+l/CSPXNZGDB8QFAwpimwqyKJj/NLH45A== + dependencies: + "@babel/core" "^7.12.10" + "@babel/plugin-transform-template-literals" "^7.12.1" + "@babel/preset-react" "^7.12.10" + "@storybook/addons" "6.5.9" + "@storybook/core-client" "6.5.9" + "@storybook/core-common" "6.5.9" + "@storybook/node-logger" "6.5.9" + "@storybook/theming" "6.5.9" + "@storybook/ui" "6.5.9" + "@types/node" "^14.0.10 || ^16.0.0" + "@types/webpack" "^4.41.26" + babel-loader "^8.0.0" + case-sensitive-paths-webpack-plugin "^2.3.0" + chalk "^4.1.0" + core-js "^3.8.2" + css-loader "^3.6.0" + express "^4.17.1" + file-loader "^6.2.0" + find-up "^5.0.0" + fs-extra "^9.0.1" + html-webpack-plugin "^4.0.0" + node-fetch "^2.6.7" + pnp-webpack-plugin "1.6.4" + read-pkg-up "^7.0.1" + regenerator-runtime "^0.13.7" + resolve-from "^5.0.0" + style-loader "^1.3.0" + telejson "^6.0.8" + terser-webpack-plugin "^4.2.3" + ts-dedent "^2.0.0" + url-loader "^4.1.1" + util-deprecate "^1.0.2" + webpack "4" + webpack-dev-middleware "^3.7.3" + webpack-virtual-modules "^0.2.2" + +"@storybook/manager-webpack5@^6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/manager-webpack5/-/manager-webpack5-6.5.9.tgz#ce9dd6ea6298ab426b111f170c23deea7085ba08" + integrity sha512-J1GamphSsaZLNBEhn1awgxzOS8KfvzrHtVlAm2VHwW7j1E1DItROFJhGCgduYYuBiN9eqm+KIYrxcr6cRuoolQ== + dependencies: + "@babel/core" "^7.12.10" + "@babel/plugin-transform-template-literals" "^7.12.1" + "@babel/preset-react" "^7.12.10" + "@storybook/addons" "6.5.9" + "@storybook/core-client" "6.5.9" + "@storybook/core-common" "6.5.9" + "@storybook/node-logger" "6.5.9" + "@storybook/theming" "6.5.9" + "@storybook/ui" "6.5.9" + "@types/node" "^14.0.10 || ^16.0.0" + babel-loader "^8.0.0" + case-sensitive-paths-webpack-plugin "^2.3.0" + chalk "^4.1.0" + core-js "^3.8.2" + css-loader "^5.0.1" + express "^4.17.1" + find-up "^5.0.0" + fs-extra "^9.0.1" + html-webpack-plugin "^5.0.0" + node-fetch "^2.6.7" + process "^0.11.10" + read-pkg-up "^7.0.1" + regenerator-runtime "^0.13.7" + resolve-from "^5.0.0" + style-loader "^2.0.0" + telejson "^6.0.8" + terser-webpack-plugin "^5.0.3" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + webpack "^5.9.0" + webpack-dev-middleware "^4.1.0" + webpack-virtual-modules "^0.4.1" + +"@storybook/mdx1-csf@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@storybook/mdx1-csf/-/mdx1-csf-0.0.1.tgz#d4184e3f6486fade9f7a6bfaf934d9bc07718d5b" + integrity sha512-4biZIWWzoWlCarMZmTpqcJNgo/RBesYZwGFbQeXiGYsswuvfWARZnW9RE9aUEMZ4XPn7B1N3EKkWcdcWe/K2tg== + dependencies: + "@babel/generator" "^7.12.11" + "@babel/parser" "^7.12.11" + "@babel/preset-env" "^7.12.11" + "@babel/types" "^7.12.11" + "@mdx-js/mdx" "^1.6.22" + "@types/lodash" "^4.14.167" + js-string-escape "^1.0.1" + loader-utils "^2.0.0" + lodash "^4.17.21" + prettier ">=2.2.1 <=2.3.0" + ts-dedent "^2.0.0" + +"@storybook/node-logger@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.5.9.tgz#129cfe0d0f79cab4f6a2ba194d39516680b1626f" + integrity sha512-nZZNZG2Wtwv6Trxi3FrnIqUmB55xO+X/WQGPT5iKlqNjdRIu/T72mE7addcp4rbuWCQfZUhcDDGpBOwKtBxaGg== + dependencies: + "@types/npmlog" "^4.1.2" + chalk "^4.1.0" + core-js "^3.8.2" + npmlog "^5.0.1" + pretty-hrtime "^1.0.3" + +"@storybook/postinstall@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/postinstall/-/postinstall-6.5.9.tgz#a5a2565808e9d7bc310e78c279b09ce337fe3457" + integrity sha512-KQBupK+FMRrtSt8IL0MzCZ/w9qbd25Yxxp/+ajfWgZTRgsWgVFOqcDyMhS16eNbBp5qKIBCBDXfEF+/mK8HwQQ== + dependencies: + core-js "^3.8.2" + +"@storybook/preview-web@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/preview-web/-/preview-web-6.5.9.tgz#557d919e6df50d66259521aa36ebf4055bbd236e" + integrity sha512-4eMrO2HJyZUYyL/j+gUaDvry6iGedshwT5MQqe7J9FaA+Q2pNARQRB1X53f410w7S4sObRmYIAIluWPYdWym9w== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/channel-postmessage" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/store" "6.5.9" + ansi-to-html "^0.6.11" + core-js "^3.8.2" + global "^4.4.0" + lodash "^4.17.21" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + synchronous-promise "^2.0.15" + ts-dedent "^2.0.0" + unfetch "^4.2.0" + util-deprecate "^1.0.2" + +"@storybook/react-docgen-typescript-plugin@1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0": + version "1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0" + resolved "https://registry.yarnpkg.com/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0.tgz#3103532ff494fb7dc3cf835f10740ecf6a26c0f9" + integrity sha512-eVg3BxlOm2P+chijHBTByr90IZVUtgRW56qEOLX7xlww2NBuKrcavBlcmn+HH7GIUktquWkMPtvy6e0W0NgA5w== + dependencies: + debug "^4.1.1" + endent "^2.0.1" + find-cache-dir "^3.3.1" + flat-cache "^3.0.4" + micromatch "^4.0.2" + react-docgen-typescript "^2.1.1" + tslib "^2.0.0" + +"@storybook/react@^6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-6.5.9.tgz#687ec1f6b785822a392b7ac115b61800f69fb7cd" + integrity sha512-Rp+QaTQAzxJhwuzJXVd49mnIBLQRlF8llTxPT2YoGHdrGkku/zl/HblQ6H2yzEf15367VyzaAv/BpLsO9Jlfxg== + dependencies: + "@babel/preset-flow" "^7.12.1" + "@babel/preset-react" "^7.12.10" + "@pmmmwh/react-refresh-webpack-plugin" "^0.5.3" + "@storybook/addons" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/core" "6.5.9" + "@storybook/core-common" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + "@storybook/docs-tools" "6.5.9" + "@storybook/node-logger" "6.5.9" + "@storybook/react-docgen-typescript-plugin" "1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0" + "@storybook/semver" "^7.3.2" + "@storybook/store" "6.5.9" + "@types/estree" "^0.0.51" + "@types/node" "^14.14.20 || ^16.0.0" + "@types/webpack-env" "^1.16.0" + acorn "^7.4.1" + acorn-jsx "^5.3.1" + acorn-walk "^7.2.0" + babel-plugin-add-react-displayname "^0.0.5" + babel-plugin-react-docgen "^4.2.1" + core-js "^3.8.2" + escodegen "^2.0.0" + fs-extra "^9.0.1" + global "^4.4.0" + html-tags "^3.1.0" + lodash "^4.17.21" + prop-types "^15.7.2" + react-element-to-jsx-string "^14.3.4" + react-refresh "^0.11.0" + read-pkg-up "^7.0.1" + regenerator-runtime "^0.13.7" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + webpack ">=4.43.0 <6.0.0" + +"@storybook/router@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.5.9.tgz#4740248f8517425b2056273fb366ace8a17c65e8" + integrity sha512-G2Xp/2r8vU2O34eelE+G5VbEEVFDeHcCURrVJEROh6dq2asFJAPbzslVXSeCqgOTNLSpRDJ2NcN5BckkNqmqJg== + dependencies: + "@storybook/client-logger" "6.5.9" + core-js "^3.8.2" + memoizerific "^1.11.3" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + +"@storybook/semver@^7.3.2": + version "7.3.2" + resolved "https://registry.yarnpkg.com/@storybook/semver/-/semver-7.3.2.tgz#f3b9c44a1c9a0b933c04e66d0048fcf2fa10dac0" + integrity sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg== + dependencies: + core-js "^3.6.5" + find-up "^4.1.0" + +"@storybook/source-loader@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/source-loader/-/source-loader-6.5.9.tgz#7b6f065c6a6108c4b4ca7e45bfd78707373d84ac" + integrity sha512-H03nFKaP6borfWMTTa9igBA+Jm2ph+FoVJImWC/X+LAmLSJYYSXuqSgmiZ/DZvbjxS4k8vccE2HXogne1IvaRA== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + core-js "^3.8.2" + estraverse "^5.2.0" + global "^4.4.0" + loader-utils "^2.0.0" + lodash "^4.17.21" + prettier ">=2.2.1 <=2.3.0" + regenerator-runtime "^0.13.7" + +"@storybook/store@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/store/-/store-6.5.9.tgz#dc9963fc013636569082bd8f7200804866373735" + integrity sha512-80pcDTcCwK6wUA63aWOp13urI77jfipIVee9mpVvbNyfrNN8kGv1BS0z/JHDxuV6rC4g7LG1fb+BurR0yki7BA== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/csf" "0.0.2--canary.4566f4d.1" + core-js "^3.8.2" + fast-deep-equal "^3.1.3" + global "^4.4.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + regenerator-runtime "^0.13.7" + slash "^3.0.0" + stable "^0.1.8" + synchronous-promise "^2.0.15" + ts-dedent "^2.0.0" + util-deprecate "^1.0.2" + +"@storybook/telemetry@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/telemetry/-/telemetry-6.5.9.tgz#8e1e0d4a89fc2387620045e5ea96c109d16a7247" + integrity sha512-JluoHCRhHAr4X0eUNVBSBi1JIBA92404Tu1TPdbN7x6gCZxHXXPTSUTAnspXp/21cTdMhY2x+kfZQ8fmlGK4MQ== + dependencies: + "@storybook/client-logger" "6.5.9" + "@storybook/core-common" "6.5.9" + chalk "^4.1.0" + core-js "^3.8.2" + detect-package-manager "^2.0.1" + fetch-retry "^5.0.2" + fs-extra "^9.0.1" + global "^4.4.0" + isomorphic-unfetch "^3.1.0" + nanoid "^3.3.1" + read-pkg-up "^7.0.1" + regenerator-runtime "^0.13.7" + +"@storybook/testing-library@^0.0.13": + version "0.0.13" + resolved "https://registry.yarnpkg.com/@storybook/testing-library/-/testing-library-0.0.13.tgz#417c87d4ea62895092ec5fdf67027ae201254f45" + integrity sha512-vRMeIGer4EjJkTgI8sQyK9W431ekPWYCWL//OmSDJ64IT3h7FnW7Xg6p+eqM3oII98/O5pcya5049GxnjaPtxw== + dependencies: + "@storybook/client-logger" "^6.4.0" + "@storybook/instrumenter" "^6.4.0" + "@testing-library/dom" "^8.3.0" + "@testing-library/user-event" "^13.2.1" + ts-dedent "^2.2.0" + +"@storybook/theming@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.5.9.tgz#13f60a3a3cd73ceb5caf9f188e1627e79f1891aa" + integrity sha512-KM0AMP5jMQPAdaO8tlbFCYqx9uYM/hZXGSVUhznhLYu7bhNAIK7ZVmXxyE/z/khM++8eUHzRoZGiO/cwCkg9Xw== + dependencies: + "@storybook/client-logger" "6.5.9" + core-js "^3.8.2" + memoizerific "^1.11.3" + regenerator-runtime "^0.13.7" + +"@storybook/ui@6.5.9": + version "6.5.9" + resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.5.9.tgz#41e59279323cccc0d613974ec9782d797220c8a7" + integrity sha512-ryuPxJgtbb0gPXKGgGAUC+Z185xGAd1IvQ0jM5fJ0SisHXI8jteG3RaWhntOehi9qCg+64Vv6eH/cj9QYNHt1Q== + dependencies: + "@storybook/addons" "6.5.9" + "@storybook/api" "6.5.9" + "@storybook/channels" "6.5.9" + "@storybook/client-logger" "6.5.9" + "@storybook/components" "6.5.9" + "@storybook/core-events" "6.5.9" + "@storybook/router" "6.5.9" + "@storybook/semver" "^7.3.2" + "@storybook/theming" "6.5.9" + core-js "^3.8.2" + memoizerific "^1.11.3" + qs "^6.10.0" + regenerator-runtime "^0.13.7" + resolve-from "^5.0.0" + +"@testing-library/dom@^8.3.0": + version "8.14.0" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.14.0.tgz#c9830a21006d87b9ef6e1aae306cf49b0283e28e" + integrity sha512-m8FOdUo77iMTwVRCyzWcqxlEIk+GnopbrRI15a0EaLbpZSCinIVI4kSQzWhkShK83GogvEFJSsHF3Ws0z1vrqA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^4.2.0" + aria-query "^5.0.0" + chalk "^4.1.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.4.4" + pretty-format "^27.0.2" + +"@testing-library/user-event@^13.2.1": + version "13.5.0" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-13.5.0.tgz#69d77007f1e124d55314a2b73fd204b333b13295" + integrity sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg== + dependencies: + "@babel/runtime" "^7.12.5" + +"@types/aria-query@^4.2.0": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc" + integrity sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig== + +"@types/body-parser@*", "@types/body-parser@^1.19.2": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bonjour@^3.5.9": + version "3.5.10" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" + integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + dependencies: + "@types/node" "*" + +"@types/connect-history-api-fallback@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" + integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + +"@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.4.5" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.5.tgz#acdfb7dd36b91cc5d812d7c093811a8f3d9b31e4" + integrity sha512-dhsC09y1gpJWnK+Ff4SGvCuSnk9DaU0BJZSzOwa6GVSg65XtTugLBITDAAzRU5duGBoXBHpdR/9jHGxJjNflJQ== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "0.0.52" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.52.tgz#7f1f57ad5b741f3d5b210d3b1f145640d89bf8fe" + integrity sha512-BZWrtCU0bMVAIliIV+HJO1f1PR41M7NKjfxrFJwwhKI1KwhwOxYw1SXg9ao+CIMt774nFuGiG6eU+udtbEI9oQ== + +"@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": + version "4.17.29" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz#2a1795ea8e9e9c91b4a4bbe475034b20c1ec711c" + integrity sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@*", "@types/express@^4.17.13": + version "4.17.13" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" + integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.18" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/glob@*", "@types/glob@^7.1.1": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + +"@types/graceful-fs@^4.1.2", "@types/graceful-fs@^4.1.5": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + dependencies: + "@types/node" "*" + +"@types/hast@^2.0.0": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" + integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + dependencies: + "@types/unist" "*" + +"@types/html-minifier-terser@^5.0.0": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz#693b316ad323ea97eed6b38ed1a3cc02b1672b57" + integrity sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w== + +"@types/html-minifier-terser@^6.0.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" + integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== + +"@types/http-proxy@^1.17.8": + version "1.17.9" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a" + integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw== + dependencies: + "@types/node" "*" + +"@types/is-function@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/is-function/-/is-function-1.0.1.tgz#2d024eace950c836d9e3335a66b97960ae41d022" + integrity sha512-A79HEEiwXTFtfY+Bcbo58M2GRYzCr9itHWzbzHVFNEYCcoU/MMGwYYf721gBrnhpj1s6RGVVha/IgNFnR0Iw/Q== + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + +"@types/lodash@^4.14.167": + version "4.14.182" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" + integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== + +"@types/mdast@^3.0.0": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" + integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + dependencies: + "@types/unist" "*" + +"@types/mime@^1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" + integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== + +"@types/minimatch@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" + integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== + +"@types/node-fetch@^2.5.7": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" + integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*", "@types/node@^18.0.1": + version "18.0.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.1.tgz#e91bd73239b338557a84d1f67f7b9e0f25643870" + integrity sha512-CmR8+Tsy95hhwtZBKJBs0/FFq4XX7sDZHlGGf+0q+BRZfMbOTkzkj0AFAuTyXbObDIoanaBBW0+KEW+m3N16Wg== + +"@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0": + version "16.11.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.43.tgz#555e5a743f76b6b897d47f945305b618525ddbe6" + integrity sha512-GqWykok+3uocgfAJM8imbozrqLnPyTrpFlrryURQlw1EesPUCx5XxTiucWDSFF9/NUEXDuD4bnvHm8xfVGWTpQ== + +"@types/normalize-package-data@^2.4.0": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" + integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== + +"@types/npmlog@^4.1.2": + version "4.1.4" + resolved "https://registry.yarnpkg.com/@types/npmlog/-/npmlog-4.1.4.tgz#30eb872153c7ead3e8688c476054ddca004115f6" + integrity sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ== + +"@types/parse-json@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" + integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== + +"@types/parse5@^5.0.0": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" + integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== + +"@types/pretty-hrtime@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@types/pretty-hrtime/-/pretty-hrtime-1.0.1.tgz#72a26101dc567b0d68fd956cf42314556e42d601" + integrity sha512-VjID5MJb1eGKthz2qUerWT8+R4b9N+CHvGCzg9fn4kWZgaF9AhdYikQio3R7wV8YY1NsQKPaCwKz1Yff+aHNUQ== + +"@types/prop-types@*": + version "15.7.5" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" + integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + +"@types/qs@*", "@types/qs@^6.9.5": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/react-dom@^18.0.5": + version "18.0.5" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.5.tgz#330b2d472c22f796e5531446939eacef8378444a" + integrity sha512-OWPWTUrY/NIrjsAPkAk1wW9LZeIjSvkXRhclsFO8CZcZGCOg2G0YZy4ft+rOyYxy8B7ui5iZzi9OkDebZ7/QSA== + dependencies: + "@types/react" "*" + +"@types/react-syntax-highlighter@11.0.5": + version "11.0.5" + resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-11.0.5.tgz#0d546261b4021e1f9d85b50401c0a42acb106087" + integrity sha512-VIOi9i2Oj5XsmWWoB72p3KlZoEbdRAcechJa8Ztebw7bDl2YmR+odxIqhtJGp1q2EozHs02US+gzxJ9nuf56qg== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^18.0.14": + version "18.0.14" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.14.tgz#e016616ffff51dba01b04945610fe3671fdbe06d" + integrity sha512-x4gGuASSiWmo0xjDLpm5mPb52syZHJx02VKbqUKdLmKtAwIh63XClGsiTI1K6DO5q7ox4xAsQrU+Gl3+gGXF9Q== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/retry@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" + integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== + +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + +"@types/serve-index@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" + integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + dependencies: + "@types/express" "*" + +"@types/serve-static@*", "@types/serve-static@^1.13.10": + version "1.13.10" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" + integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/sockjs@^0.3.33": + version "0.3.33" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" + integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + dependencies: + "@types/node" "*" + +"@types/source-list-map@*": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" + integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== + +"@types/tapable@^1", "@types/tapable@^1.0.5": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.8.tgz#b94a4391c85666c7b73299fd3ad79d4faa435310" + integrity sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ== + +"@types/uglify-js@*": + version "3.16.0" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.16.0.tgz#2cf74a0e6ebb6cd54c0d48e509d5bd91160a9602" + integrity sha512-0yeUr92L3r0GLRnBOvtYK1v2SjqMIqQDHMl7GLb+l2L8+6LSFWEEWEIgVsPdMn5ImLM8qzWT8xFPtQYpp8co0g== + dependencies: + source-map "^0.6.1" + +"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" + integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + +"@types/webpack-env@^1.16.0": + version "1.17.0" + resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.17.0.tgz#f99ce359f1bfd87da90cc4a57cab0a18f34a48d0" + integrity sha512-eHSaNYEyxRA5IAG0Ym/yCyf86niZUIF/TpWKofQI/CVfh5HsMEUyfE2kwFxha4ow0s5g0LfISQxpDKjbRDrizw== + +"@types/webpack-sources@*": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-3.2.0.tgz#16d759ba096c289034b26553d2df1bf45248d38b" + integrity sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg== + dependencies: + "@types/node" "*" + "@types/source-list-map" "*" + source-map "^0.7.3" + +"@types/webpack@^4.41.26", "@types/webpack@^4.41.8": + version "4.41.32" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.32.tgz#a7bab03b72904070162b2f169415492209e94212" + integrity sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg== + dependencies: + "@types/node" "*" + "@types/tapable" "^1" + "@types/uglify-js" "*" + "@types/webpack-sources" "*" + anymatch "^3.0.0" + source-map "^0.6.0" + +"@types/ws@^8.5.1": + version "8.5.3" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" + integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== + dependencies: + "@types/node" "*" + +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^15.0.0": + version "15.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" + integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== + dependencies: + "@types/yargs-parser" "*" + +"@types/yargs@^16.0.0": + version "16.0.4" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" + integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@^5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.4.tgz#a46c8c0ab755a936cb63786a6222876ce51675e4" + integrity sha512-xjujQISAIa4HAaos8fcMZXmqkuZqMx6icdxkI88jMM/eNe4J8AuTLYnLK+zdm0mBYLyctdFf//UE4/xFCcQzYQ== + dependencies: + "@typescript-eslint/scope-manager" "5.30.4" + "@typescript-eslint/type-utils" "5.30.4" + "@typescript-eslint/utils" "5.30.4" + debug "^4.3.4" + functional-red-black-tree "^1.0.1" + ignore "^5.2.0" + regexpp "^3.2.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.30.4.tgz#659411e8700b22c8d5400798ef24838425bf4567" + integrity sha512-/ge1HtU63wVoED4VnlU2o+FPFmi017bPYpeSrCmd8Ycsti4VSxXrmcpXXm7JpI4GT0Aa7qviabv1PEp6L5bboQ== + dependencies: + "@typescript-eslint/scope-manager" "5.30.4" + "@typescript-eslint/types" "5.30.4" + "@typescript-eslint/typescript-estree" "5.30.4" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.30.4.tgz#8140efd2bc12d41d74e8af23872a89f3edbe552e" + integrity sha512-DNzlQwGSiGefz71JwaHrpcaAX3zYkEcy8uVuan3YMKOa6qeW/y+7SaD8KIsIAruASwq6P+U4BjWBWtM2O+mwBQ== + dependencies: + "@typescript-eslint/types" "5.30.4" + "@typescript-eslint/visitor-keys" "5.30.4" + +"@typescript-eslint/type-utils@5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.30.4.tgz#00ff19073cd01f7d27e9af49ce08d6a69f1e4f01" + integrity sha512-55cf1dZviwwv+unDB+mF8vZkfta5muTK6bppPvenWWCD7slZZ0DEsXUjZerqy7Rq8s3J4SXdg4rMIY8ngCtTmA== + dependencies: + "@typescript-eslint/utils" "5.30.4" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.30.4.tgz#3bc99eca8ba3fcfd6a21480e216b09dab81c3999" + integrity sha512-NTEvqc+Vvu8Q6JeAKryHk2eqLKqsr2St3xhIjhOjQv5wQUBhaTuix4WOSacqj0ONWfKVU12Eug3LEAB95GBkMA== + +"@typescript-eslint/typescript-estree@5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.4.tgz#ac4be8a2f8fb1f1c3b346d5992a36163121ddb3f" + integrity sha512-V4VnEs6/J9/nNizaA12IeU4SAeEYaiKr7XndLNfV5+3zZSB4hIu6EhHJixTKhvIqA+EEHgBl6re8pivBMLLO1w== + dependencies: + "@typescript-eslint/types" "5.30.4" + "@typescript-eslint/visitor-keys" "5.30.4" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.30.4.tgz#07a2b7ce80b2527ea506829f190591b76c70ba9f" + integrity sha512-a+GQrJzOUhn4WT1mUumXDyam+22Oo4c5K/jnZ+6r/4WTQF3q8e4CsC9PLHb4SnOClzOqo/5GLZWvkE1aa5UGKQ== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.30.4" + "@typescript-eslint/types" "5.30.4" + "@typescript-eslint/typescript-estree" "5.30.4" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/visitor-keys@5.30.4": + version "5.30.4" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.4.tgz#b4969df1a440cc999d4bb7f7b7932dce05537089" + integrity sha512-ulKGse3mruSc8x6l8ORSc6+1ORyJzKmZeIaRTu/WpaF/jx3vHvEn5XZUKF9XaVg2710mFmTAUlLcLYLPp/Zf/Q== + dependencies: + "@typescript-eslint/types" "5.30.4" + eslint-visitor-keys "^3.3.0" + +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== + dependencies: + "@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@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== + +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== + +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== + +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== + dependencies: + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== + +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== + dependencies: + "@webassemblyjs/ast" "1.9.0" + +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== + +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== + 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" + +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== + +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== + 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" + +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== + 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" + +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== + dependencies: + "@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@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== + 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" + +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== + 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" + +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" + integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== + +"@webpack-cli/info@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" + integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" + integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + +acorn-jsx@^5.3.1, acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + +acorn@^6.4.1: + version "6.4.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== + +acorn@^7.4.1: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1: + version "8.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" + integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== + +address@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/address/-/address-1.2.0.tgz#d352a62c92fee90f89a693eccd2a8b2139ab02d9" + integrity sha512-tNEZYz5G/zYunxFm7sfhAxkXEuLj3K6BKwv6ZURlsF6yiUQ65z0Q2wZW9L5cPUl9ocofGvXOdFYbFHp0+6MOig== + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +airbnb-js-shims@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/airbnb-js-shims/-/airbnb-js-shims-2.2.1.tgz#db481102d682b98ed1daa4c5baa697a05ce5c040" + integrity sha512-wJNXPH66U2xjgo1Zwyjf9EydvJ2Si94+vSdk6EERcBfB2VZkeltpqIats0cqIZMLCXP3zcyaUKGYQeIBT6XjsQ== + dependencies: + array-includes "^3.0.3" + array.prototype.flat "^1.2.1" + array.prototype.flatmap "^1.2.1" + es5-shim "^4.5.13" + es6-shim "^0.35.5" + function.prototype.name "^1.1.0" + globalthis "^1.0.0" + object.entries "^1.1.0" + object.fromentries "^2.0.0 || ^1.0.0" + object.getownpropertydescriptors "^2.0.3" + object.values "^1.1.0" + promise.allsettled "^1.0.0" + promise.prototype.finally "^3.1.0" + string.prototype.matchall "^4.0.0 || ^3.0.1" + string.prototype.padend "^3.0.0" + string.prototype.padstart "^3.0.0" + symbol.prototype.description "^1.0.0" + +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + 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" + +ajv@^8.0.0, ajv@^8.8.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" + integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + +ansi-colors@^3.0.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" + integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== + +ansi-html-community@0.0.8, ansi-html-community@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" + integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw== + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +ansi-to-html@^0.6.11: + version "0.6.15" + resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.15.tgz#ac6ad4798a00f6aa045535d7f6a9cb9294eebea7" + integrity sha512-28ijx2aHJGdzbs+O5SNQF65r6rrKYnkuwTYm8lZlChuoJ9P1vVzIpWO20sQTqTPDXYp6NFwk326vApTtLVFXpQ== + dependencies: + entities "^2.0.0" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@^3.0.0, anymatch@^3.0.3, anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +app-root-dir@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/app-root-dir/-/app-root-dir-1.0.2.tgz#38187ec2dea7577fff033ffcb12172692ff6e118" + integrity sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g== + +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +aria-query@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.0.0.tgz#210c21aaf469613ee8c9a62c7f86525e058db52c" + integrity sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg== + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array-flatten@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + +array-includes@^3.0.3, array-includes@^3.1.4, array-includes@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb" + integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" + get-intrinsic "^1.1.1" + is-string "^1.0.7" + +array-union@^1.0.1, array-union@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng== + dependencies: + array-uniq "^1.0.1" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q== + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== + +array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.5: + version "1.3.0" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz#0b0c1567bf57b38b56b4c97b8aa72ab45e4adc7b" + integrity sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.2" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz#a7e8ed4225f4788a70cd910abcf0791e76a5534f" + integrity sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.2" + es-shim-unscopables "^1.0.0" + +array.prototype.map@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/array.prototype.map/-/array.prototype.map-1.0.4.tgz#0d97b640cfdd036c1b41cfe706a5e699aa0711f2" + integrity sha512-Qds9QnX7A0qISY7JT5WuJO0NJPE9CMlC6JzHQfhpqAAQQzufVRoeH7EzUY5GcPTx72voG8LV/5eo+b8Qi8hmhA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + +array.prototype.reduce@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.4.tgz#8167e80089f78bff70a99e20bd4201d4663b0a6f" + integrity sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.2" + es-array-method-boxes-properly "^1.0.0" + is-string "^1.0.7" + +arrify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + +assert@^1.1.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + dependencies: + object-assign "^4.1.1" + util "0.10.3" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== + +ast-types@^0.14.2: + version "0.14.2" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.14.2.tgz#600b882df8583e3cd4f2df5fa20fa83759d4bdfd" + integrity sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA== + dependencies: + tslib "^2.0.1" + +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +autoprefixer@^9.8.6: + version "9.8.8" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.8.tgz#fd4bd4595385fa6f06599de749a4d5f7a474957a" + integrity sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA== + dependencies: + browserslist "^4.12.0" + caniuse-lite "^1.0.30001109" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + picocolors "^0.2.1" + postcss "^7.0.32" + postcss-value-parser "^4.1.0" + +babel-loader@^8.0.0, babel-loader@^8.2.5: + version "8.2.5" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e" + integrity sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ== + dependencies: + find-cache-dir "^3.3.1" + loader-utils "^2.0.0" + make-dir "^3.1.0" + schema-utils "^2.6.5" + +babel-plugin-add-react-displayname@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/babel-plugin-add-react-displayname/-/babel-plugin-add-react-displayname-0.0.5.tgz#339d4cddb7b65fd62d1df9db9fe04de134122bd5" + integrity sha512-LY3+Y0XVDYcShHHorshrDbt4KFWL4bSeniCtl4SYZbask+Syngk1uMPCeN9+nSiZo6zX5s0RTq/J9Pnaaf/KHw== + +babel-plugin-apply-mdx-type-prop@1.6.22: + version "1.6.22" + resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz#d216e8fd0de91de3f1478ef3231e05446bc8705b" + integrity sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ== + dependencies: + "@babel/helper-plugin-utils" "7.10.4" + "@mdx-js/util" "1.6.22" + +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + +babel-plugin-extract-import-names@1.6.22: + version "1.6.22" + resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz#de5f9a28eb12f3eb2578bf74472204e66d1a13dc" + integrity sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ== + dependencies: + "@babel/helper-plugin-utils" "7.10.4" + +babel-plugin-istanbul@^6.0.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-macros@^2.6.1: + version "2.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" + integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== + dependencies: + "@babel/runtime" "^7.7.2" + cosmiconfig "^6.0.0" + resolve "^1.12.0" + +babel-plugin-macros@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" + integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg== + dependencies: + "@babel/runtime" "^7.12.5" + cosmiconfig "^7.0.0" + resolve "^1.19.0" + +babel-plugin-named-exports-order@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-named-exports-order/-/babel-plugin-named-exports-order-0.0.2.tgz#ae14909521cf9606094a2048239d69847540cb09" + integrity sha512-OgOYHOLoRK+/mvXU9imKHlG6GkPLYrUCvFXG/CM93R/aNNO8pOOF4aS+S8CCHMDQoNSeiOYEZb/G6RwL95Jktw== + +babel-plugin-polyfill-corejs2@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" + integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== + dependencies: + "@babel/compat-data" "^7.13.11" + "@babel/helper-define-polyfill-provider" "^0.3.1" + semver "^6.1.1" + +babel-plugin-polyfill-corejs3@^0.1.0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz#80449d9d6f2274912e05d9e182b54816904befd0" + integrity sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.1.5" + core-js-compat "^3.8.1" + +babel-plugin-polyfill-corejs3@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72" + integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.1" + core-js-compat "^3.21.0" + +babel-plugin-polyfill-regenerator@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" + integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.3.1" + +babel-plugin-react-docgen@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/babel-plugin-react-docgen/-/babel-plugin-react-docgen-4.2.1.tgz#7cc8e2f94e8dc057a06e953162f0810e4e72257b" + integrity sha512-UQ0NmGHj/HAqi5Bew8WvNfCk8wSsmdgNd8ZdMjBCICtyCJCq9LiqgqvjCYe570/Wg7AQArSq1VQ60Dd/CHN7mQ== + dependencies: + ast-types "^0.14.2" + lodash "^4.17.15" + react-docgen "^5.0.0" + +bail@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" + integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.0.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + 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" + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== + +better-opn@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/better-opn/-/better-opn-2.1.1.tgz#94a55b4695dc79288f31d7d0e5f658320759f7c6" + integrity sha512-kIPXZS5qwyKiX/HcRvDYfmBQUa8XP17I0mYZZ0y4UhpYOSvtsLHDYqmomS+Mj20aDvD3knEiQ0ecQy2nhio3yA== + dependencies: + open "^7.0.3" + +big-integer@^1.6.7: + version "1.6.51" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" + integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bluebird@^3.5.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +body-parser@1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" + integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.10.3" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +bonjour-service@^1.0.11: + version "1.0.13" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.0.13.tgz#4ac003dc1626023252d58adf2946f57e5da450c1" + integrity sha512-LWKRU/7EqDUC9CTAQtuZl5HzBALoCYwtLhffW3et7vZMwv3bWLpJf8bRYlMD5OCcDpTfnPgNCV4yo9ZIaJGMiA== + dependencies: + array-flatten "^2.1.2" + dns-equal "^1.0.0" + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.5" + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +boxen@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + +bplist-parser@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.1.1.tgz#d60d5dcc20cba6dc7e1f299b35d3e1f95dafbae6" + integrity sha512-2AEM0FXy8ZxVLBuqX0hqt1gDwcnz2zygEkQ6zaD5Wko/sB9paUNwlpawrFtKeHUAQUOzjVy9AO4oeonqIHKA9Q== + dependencies: + big-integer "^1.6.7" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + 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" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browser-assert@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/browser-assert/-/browser-assert-1.2.1.tgz#9aaa5a2a8c74685c2ae05bfe46efd606f068c200" + integrity sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ== + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + 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" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + 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" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.20.2, browserslist@^4.21.0: + version "4.21.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.1.tgz#c9b9b0a54c7607e8dc3e01a0d311727188011a00" + integrity sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ== + dependencies: + caniuse-lite "^1.0.30001359" + electron-to-chromium "^1.4.172" + node-releases "^2.0.5" + update-browserslist-db "^1.0.4" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + +buffer@^4.3.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +c8@^7.6.0: + version "7.11.3" + resolved "https://registry.yarnpkg.com/c8/-/c8-7.11.3.tgz#88c8459c1952ed4f701b619493c9ae732b057163" + integrity sha512-6YBmsaNmqRm9OS3ZbIiL2EZgi1+Xc4O24jL3vMYGE6idixYuGdy76rIfIdltSKDj9DpLNrcXSonUTR1miBD0wA== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@istanbuljs/schema" "^0.1.3" + find-up "^5.0.0" + foreground-child "^2.0.0" + istanbul-lib-coverage "^3.2.0" + istanbul-lib-report "^3.0.0" + istanbul-reports "^3.1.4" + rimraf "^3.0.2" + test-exclude "^6.0.0" + v8-to-istanbul "^9.0.0" + yargs "^16.2.0" + yargs-parser "^20.2.9" + +cacache@^12.0.2: + version "12.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" + integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== + 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" + +cacache@^15.0.5: + version "15.3.0" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" + integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== + dependencies: + "@npmcli/fs" "^1.0.0" + "@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.1" + tar "^6.0.2" + unique-filename "^1.1.1" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + 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" + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +call-me-maybe@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + integrity sha512-wCyFsDQkKPwwF8BDwOiWNx/9K45L/hvggQiDbve+viMNMQnWhrlYIuBk09offfwCRtCO9P6XwUttufzU11WCVw== + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camel-case@^4.1.1, camel-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + +camelcase-css@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + integrity sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ== + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + integrity sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001359: + version "1.0.30001363" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001363.tgz#26bec2d606924ba318235944e1193304ea7c4f15" + integrity sha512-HpQhpzTGGPVMnCjIomjt+jvyUu8vNFo3TaDiZ/RcoTrlOq/5+tC8zHdsbgFB6MxmaY+jCpsH09aD80Bb4Ow3Sg== + +capture-exit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" + integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== + dependencies: + rsvp "^4.8.4" + +case-sensitive-paths-webpack-plugin@^2.3.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4" + integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw== + +ccount@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" + integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== + +chalk@^2.0.0, chalk@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + +chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== + 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" + +chokidar@^3.4.1, chokidar@^3.4.2, chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + 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" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +chrome-trace-event@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +clean-css@^4.2.3: + version "4.2.4" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.4.tgz#733bf46eba4e607c6891ea57c24a989356831178" + integrity sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A== + dependencies: + source-map "~0.6.0" + +clean-css@^5.2.2: + version "5.3.0" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.0.tgz#ad3d8238d5f3549e83d5f87205189494bc7cbb59" + integrity sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ== + dependencies: + source-map "~0.6.0" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +clean-webpack-plugin@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/clean-webpack-plugin/-/clean-webpack-plugin-4.0.0.tgz#72947d4403d452f38ed61a9ff0ada8122aacd729" + integrity sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w== + dependencies: + del "^4.1.1" + +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + +cli-table3@^0.6.1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.2.tgz#aaf5df9d8b5bf12634dc8b3040806a0c07120d2a" + integrity sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clsx@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702" + integrity sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA== + +clsx@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.0.tgz#b0e415ea7537dbac01b169c5cec1caeb11d86566" + integrity sha512-EPRP7XJsM1y0iCU3Z7C7jFKdQboXSeHgEfzQUTlz7m5NP3hDrlz48aUsmNGp4pC+JOW9WA3vIRqlYuo/bl4Drw== + +collapse-white-space@^1.0.2: + version "1.0.6" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" + integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +colorette@^1.2.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" + integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== + +colorette@^2.0.10, colorette@^2.0.14: + version "2.0.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +comma-separated-tokens@^1.0.0: + version "1.0.8" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" + integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== + +commander@^2.19.0, commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +commander@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== + +commander@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + +commander@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" + integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== + +common-path-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" + integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + 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" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-stream@^1.5.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== + +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + +console-control-strings@^1.0.0, console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== + dependencies: + safe-buffer "~5.1.1" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== + 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" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== + +core-js-compat@^3.21.0, core-js-compat@^3.22.1, core-js-compat@^3.8.1: + version "3.23.3" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.23.3.tgz#7d8503185be76bb6d8d592c291a4457a8e440aa9" + integrity sha512-WSzUs2h2vvmKsacLHNTdpyOC9k43AEhcGoFlVgCY4L7aw98oSBKtPL6vD0/TqZjRWRQYdDSLkzZIni4Crbbiqw== + dependencies: + browserslist "^4.21.0" + semver "7.0.0" + +core-js-pure@^3.8.1: + version "3.23.3" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.23.3.tgz#bcd02d3d8ec68ad871ef50d5ccbb248ddb54f401" + integrity sha512-XpoouuqIj4P+GWtdyV8ZO3/u4KftkeDVMfvp+308eGMhCrA3lVDSmAxO0c6GGOcmgVlaKDrgWVMo49h2ab/TDA== + +core-js@^3.0.4, core-js@^3.6.5, core-js@^3.8.2: + version "3.23.3" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.23.3.tgz#3b977612b15da6da0c9cc4aec487e8d24f371112" + integrity sha512-oAKwkj9xcWNBAvGbT//WiCdOMpb9XQG92/Fe3ABFM/R16BsHgePG00mFOgKf7IsCtfj8tA1kHtf/VwErhriz5Q== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cosmiconfig@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" + integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.7.2" + +cosmiconfig@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" + integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== + 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" + +cp-file@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-7.0.0.tgz#b9454cfd07fe3b974ab9ea0e5f29655791a9b8cd" + integrity sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw== + dependencies: + graceful-fs "^4.1.2" + make-dir "^3.0.0" + nested-error-stacks "^2.0.0" + p-event "^4.1.0" + +cpy@^8.1.2: + version "8.1.2" + resolved "https://registry.yarnpkg.com/cpy/-/cpy-8.1.2.tgz#e339ea54797ad23f8e3919a5cffd37bfc3f25935" + integrity sha512-dmC4mUesv0OYH2kNFEidtf/skUwv4zePmGeepjyyJ0qTo5+8KhA1o99oIAwVVLzQMAeDJml74d6wPPKb6EZUTg== + dependencies: + arrify "^2.0.1" + cp-file "^7.0.0" + globby "^9.2.0" + has-glob "^1.0.0" + junk "^3.1.0" + nested-error-stacks "^2.1.0" + p-all "^2.1.0" + p-filter "^2.1.0" + p-map "^3.0.0" + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + 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@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + 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" + +cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + 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" + +css-loader@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" + integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== + dependencies: + camelcase "^5.3.1" + cssesc "^3.0.0" + icss-utils "^4.1.1" + loader-utils "^1.2.3" + normalize-path "^3.0.0" + postcss "^7.0.32" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^3.0.2" + postcss-modules-scope "^2.2.0" + postcss-modules-values "^3.0.0" + postcss-value-parser "^4.1.0" + schema-utils "^2.7.0" + semver "^6.3.0" + +css-loader@^5.0.1: + version "5.2.7" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.2.7.tgz#9b9f111edf6fb2be5dc62525644cbc9c232064ae" + integrity sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg== + dependencies: + icss-utils "^5.1.0" + loader-utils "^2.0.0" + postcss "^8.2.15" + 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.5" + +css-loader@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.1.tgz#e98106f154f6e1baf3fc3bc455cb9981c1d5fd2e" + integrity sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw== + dependencies: + icss-utils "^5.1.0" + postcss "^8.4.7" + 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.2.0" + semver "^7.3.5" + +css-select@^4.1.3: + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" + integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== + dependencies: + boolbase "^1.0.0" + css-what "^6.0.1" + domhandler "^4.3.1" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-what@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +csstype@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2" + integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA== + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + integrity sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng== + dependencies: + array-find-index "^1.0.1" + +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + integrity sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A== + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.0.0, debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decamelize@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== + +deep-is@^0.1.3, deep-is@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + +default-browser-id@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-1.0.4.tgz#e59d09a5d157b828b876c26816e61c3d2a2c203a" + integrity sha512-qPy925qewwul9Hifs+3sx1ZYn14obHxpkX+mPD369w4Rzg+YkJBgi3SOvwUq81nWSjqGUegIgEPwD8u+HUnxlw== + dependencies: + bplist-parser "^0.1.0" + meow "^3.1.0" + untildify "^2.0.0" + +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== + dependencies: + execa "^5.0.0" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +del@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" + integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== + 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" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detab@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.4.tgz#b927892069aff405fbb9a186fe97a44a92a94b43" + integrity sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g== + dependencies: + repeat-string "^1.5.4" + +detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + +detect-package-manager@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/detect-package-manager/-/detect-package-manager-2.0.1.tgz#6b182e3ae5e1826752bfef1de9a7b828cffa50d8" + integrity sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A== + dependencies: + execa "^5.1.1" + +detect-port@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" + integrity sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ== + dependencies: + address "^1.0.1" + debug "^2.6.0" + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dir-glob@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" + integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== + dependencies: + path-type "^3.0.0" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== + +dns-packet@^5.2.2: + version "5.4.0" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b" + integrity sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g== + dependencies: + "@leichtgewicht/ip-codec" "^2.0.1" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-accessibility-api@^0.5.9: + version "0.5.14" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz#56082f71b1dc7aac69d83c4285eef39c15d93f56" + integrity sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg== + +dom-converter@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" + integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== + dependencies: + utila "~0.4" + +dom-serializer@^1.0.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +dom-walk@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" + integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +domelementtype@^2.0.1, domelementtype@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== + dependencies: + domelementtype "^2.2.0" + +domutils@^2.5.2, domutils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +dotenv-expand@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" + integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== + +dotenv@^8.0.0: + version "8.6.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" + integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.172: + version "1.4.177" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.177.tgz#b6a4436eb788ca732556cd69f384b8a3c82118c5" + integrity sha512-FYPir3NSBEGexSZUEeht81oVhHfLFl6mhUKSkjHN/iB/TwEIt/WHQrqVGfTLN5gQxwJCQkIJBe05eOXjI7omgg== + +elliptic@^6.5.3: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +endent@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/endent/-/endent-2.1.0.tgz#5aaba698fb569e5e18e69e1ff7a28ff35373cd88" + integrity sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w== + dependencies: + dedent "^0.7.0" + fast-json-parse "^1.0.3" + objectorarray "^1.0.5" + +enhanced-resolve@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" + integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" + +enhanced-resolve@^5.0.0, enhanced-resolve@^5.9.3: + version "5.10.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" + integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + +errno@^0.1.3, errno@~0.1.7: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +error-stack-parser@^2.0.6: + version "2.1.4" + resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286" + integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ== + dependencies: + stackframe "^1.3.4" + +es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" + integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-weakref "^1.0.2" + object-inspect "^1.12.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + regexp.prototype.flags "^1.4.3" + string.prototype.trimend "^1.0.5" + string.prototype.trimstart "^1.0.5" + unbox-primitive "^1.0.2" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-get-iterator@^1.0.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7" + integrity sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.0" + has-symbols "^1.0.1" + is-arguments "^1.1.0" + is-map "^2.0.2" + is-set "^2.0.2" + is-string "^1.0.5" + isarray "^2.0.5" + +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es5-shim@^4.5.13: + version "4.6.7" + resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.6.7.tgz#bc67ae0fc3dd520636e0a1601cc73b450ad3e955" + integrity sha512-jg21/dmlrNQI7JyyA2w7n+yifSxBng0ZralnSfVZjoCawgNTCnS+yBCyVM9DL5itm7SUnDGgv7hcq2XCZX4iRQ== + +es6-shim@^0.35.5: + version "0.35.6" + resolved "https://registry.yarnpkg.com/es6-shim/-/es6-shim-0.35.6.tgz#d10578301a83af2de58b9eadb7c2c9945f7388a0" + integrity sha512-EmTr31wppcaIAgblChZiuN/l9Y7DPyw8Xtbg7fIVngn6zMW+IEBJDJngeKC3x6wr0V/vcA2wqeFnaw1bFJbDdA== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +eslint-config-prettier@^8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" + integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== + +eslint-import-resolver-node@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd" + integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== + dependencies: + debug "^3.2.7" + resolve "^1.20.0" + +eslint-module-utils@^2.7.3: + version "2.7.3" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee" + integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ== + dependencies: + debug "^3.2.7" + find-up "^2.1.0" + +eslint-plugin-import@^2.26.0: + version "2.26.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b" + integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== + dependencies: + array-includes "^3.1.4" + array.prototype.flat "^1.2.5" + debug "^2.6.9" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.6" + eslint-module-utils "^2.7.3" + has "^1.0.3" + is-core-module "^2.8.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.values "^1.1.5" + resolve "^1.22.0" + tsconfig-paths "^3.14.1" + +eslint-plugin-prettier@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-react@^7.30.1: + version "7.30.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz#2be4ab23ce09b5949c6631413ba64b2810fd3e22" + integrity sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg== + dependencies: + array-includes "^3.1.5" + array.prototype.flatmap "^1.3.0" + doctrine "^2.1.0" + estraverse "^5.3.0" + jsx-ast-utils "^2.4.1 || ^3.0.0" + minimatch "^3.1.2" + object.entries "^1.1.5" + object.fromentries "^2.0.5" + object.hasown "^1.1.1" + object.values "^1.1.5" + prop-types "^15.8.1" + resolve "^2.0.0-next.3" + semver "^6.3.0" + string.prototype.matchall "^4.0.7" + +eslint-scope@5.1.1, eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-scope@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" + integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== + +eslint@^8.19.0: + version "8.19.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.19.0.tgz#7342a3cbc4fbc5c106a1eefe0fd0b50b6b1a7d28" + integrity sha512-SXOPj3x9VKvPe81TjjUJCYlV4oJjQw68Uek+AM0X4p+33dj2HY5bpTZOgnQHcG2eAm1mtCU9uNMnJi7exU/kYw== + dependencies: + "@eslint/eslintrc" "^1.3.0" + "@humanwhocodes/config-array" "^0.9.2" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.3.2" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^6.0.1" + globals "^13.15.0" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^9.3.2: + version "9.3.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.2.tgz#f58f77bd334731182801ced3380a8cc859091596" + integrity sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA== + dependencies: + acorn "^8.7.1" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.3.0" + +esprima@^4.0.0, esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.1.0, esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-to-babel@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/estree-to-babel/-/estree-to-babel-3.2.1.tgz#82e78315275c3ca74475fdc8ac1a5103c8a75bf5" + integrity sha512-YNF+mZ/Wu2FU/gvmzuWtYc8rloubL7wfXCTgouFrnjGVXPA/EeYYA7pupXWrb3Iv1cTBeSSxxJIbK23l4MRNqg== + dependencies: + "@babel/traverse" "^7.1.6" + "@babel/types" "^7.2.0" + c8 "^7.6.0" + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +events@^3.0.0, events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +exec-sh@^0.3.2: + version "0.3.6" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" + integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w== + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + 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" + +execa@^5.0.0, execa@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== + 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" + +express@^4.17.1, express@^4.17.3: + version "4.18.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf" + integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.0" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.10.3" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + 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" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-glob@^2.2.6: + version "2.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" + integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.1.2" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.3" + micromatch "^3.1.10" + +fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + 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" + +fast-json-parse@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" + integrity sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastest-levenshtein@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" + integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +fault@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" + integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== + dependencies: + format "^0.2.0" + +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + dependencies: + bser "2.1.1" + +fetch-retry@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/fetch-retry/-/fetch-retry-5.0.3.tgz#edfa3641892995f9afee94f25b168827aa97fe3d" + integrity sha512-uJQyMrX5IJZkhoEUBQ3EjxkeiZkppBd5jS/fMTJmfZxLSiaQjv2zD0kTvuvkSH89uFvgSlB6ueGpjD3HWN7Bxw== + +figgy-pudding@^3.5.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +file-loader@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +file-system-cache@^1.0.5: + version "1.1.0" + resolved "https://registry.yarnpkg.com/file-system-cache/-/file-system-cache-1.1.0.tgz#984de17b976b75a77a27e08d6828137c1aa80fa1" + integrity sha512-IzF5MBq+5CR0jXx5RxPe4BICl/oEhBSXKaL9fLhAXrIfIUS77Hr4vzrYyqYMHN6uTt+BOqi3fDCTjjEBCjERKw== + dependencies: + fs-extra "^10.1.0" + ramda "^0.28.0" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-cache-dir@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-root@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== + dependencies: + locate-path "^2.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.6.tgz#022e9218c637f9f3fc9c35ab9c9193f05add60b2" + integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ== + +flush-write-stream@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +focus-lock@^0.8.0: + version "0.8.1" + resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.8.1.tgz#bb36968abf77a2063fa173cb6c47b12ac8599d33" + integrity sha512-/LFZOIo82WDsyyv7h7oc0MJF9ACOvDRdx9rWPZ2pgMfNWu/z8hQDBtOchuB/0BVLmuFOZjV02YwUVzNsWx/EzA== + dependencies: + tslib "^1.9.3" + +follow-redirects@^1.0.0: + version "1.15.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" + integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== + +foreground-child@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^3.0.2" + +fork-ts-checker-webpack-plugin@^4.1.6: + version "4.1.6" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.6.tgz#5055c703febcf37fa06405d400c122b905167fc5" + integrity sha512-DUxuQaKoqfNne8iikd14SAkh5uw4+8vNifp6gmA73yYNS6ywLIWSLD/n/mBzHQRpW3J7rbATEakmiA8JvkTyZw== + dependencies: + "@babel/code-frame" "^7.5.5" + chalk "^2.4.1" + micromatch "^3.1.10" + minimatch "^3.0.4" + semver "^5.6.0" + tapable "^1.0.0" + worker-rpc "^0.1.0" + +fork-ts-checker-webpack-plugin@^6.0.4: + version "6.5.2" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz#4f67183f2f9eb8ba7df7177ce3cf3e75cdafb340" + integrity sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA== + dependencies: + "@babel/code-frame" "^7.8.3" + "@types/json-schema" "^7.0.5" + chalk "^4.1.0" + chokidar "^3.4.2" + cosmiconfig "^6.0.0" + deepmerge "^4.2.2" + fs-extra "^9.0.0" + glob "^7.1.6" + memfs "^3.1.2" + minimatch "^3.0.4" + schema-utils "2.7.0" + semver "^7.3.2" + tapable "^1.0.0" + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +format@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-extra@^9.0.0, fs-extra@^9.0.1: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs-monkey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" + integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== + +fs-write-stream-atomic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + integrity sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA== + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@^1.2.7: + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== + dependencies: + bindings "^1.5.0" + nan "^2.12.1" + +fsevents@^2.1.2, fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +function.prototype.name@^1.1.0, function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + +gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" + integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + integrity sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw== + +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + +github-slugger@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" + integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA== + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob-promise@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/glob-promise/-/glob-promise-3.4.0.tgz#b6b8f084504216f702dc2ce8c9bc9ac8866fdb20" + integrity sha512-q08RJ6O+eJn+dVanerAndJwIcumgbDdYiUT7zFQl3Wm1xD6fBKtah7H8ZJChj4wP+8C+QfeVy8xautR7rdmKEw== + dependencies: + "@types/glob" "*" + +glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + integrity sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig== + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +glob@^7.0.3, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + 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" + +global@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== + dependencies: + min-document "^2.19.0" + process "^0.11.10" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.15.0: + version "13.15.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac" + integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog== + dependencies: + type-fest "^0.20.2" + +globalthis@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +globby@^11.0.2, globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +globby@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" + integrity sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw== + dependencies: + array-union "^1.0.1" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +globby@^9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" + integrity sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^1.0.2" + dir-glob "^2.2.2" + fast-glob "^2.2.6" + glob "^7.1.3" + ignore "^4.0.3" + pify "^4.0.1" + slash "^2.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + +handlebars@^4.7.7: + version "4.7.7" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" + integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.0" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-glob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-glob/-/has-glob-1.0.0.tgz#9aaa9eedbffb1ba3990a7b0010fb678ee0081207" + integrity sha512-D+8A457fBShSEI3tFCj65PAbT++5sKiFtdCdOam0gnfBgw9D277OERk+HM9qYJXmdVLZ/znez10SqHN0BBQ50g== + dependencies: + is-glob "^3.0.0" + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hast-to-hyperscript@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz#9b67fd188e4c81e8ad66f803855334173920218d" + integrity sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA== + dependencies: + "@types/unist" "^2.0.3" + comma-separated-tokens "^1.0.0" + property-information "^5.3.0" + space-separated-tokens "^1.0.0" + style-to-object "^0.3.0" + unist-util-is "^4.0.0" + web-namespaces "^1.0.0" + +hast-util-from-parse5@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz#554e34abdeea25ac76f5bd950a1f0180e0b3bc2a" + integrity sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA== + dependencies: + "@types/parse5" "^5.0.0" + hastscript "^6.0.0" + property-information "^5.0.0" + vfile "^4.0.0" + vfile-location "^3.2.0" + web-namespaces "^1.0.0" + +hast-util-parse-selector@^2.0.0: + version "2.2.5" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a" + integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== + +hast-util-raw@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-6.0.1.tgz#973b15930b7529a7b66984c98148b46526885977" + integrity sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig== + dependencies: + "@types/hast" "^2.0.0" + hast-util-from-parse5 "^6.0.0" + hast-util-to-parse5 "^6.0.0" + html-void-elements "^1.0.0" + parse5 "^6.0.0" + unist-util-position "^3.0.0" + vfile "^4.0.0" + web-namespaces "^1.0.0" + xtend "^4.0.0" + zwitch "^1.0.0" + +hast-util-to-parse5@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479" + integrity sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ== + dependencies: + hast-to-hyperscript "^9.0.0" + property-information "^5.0.0" + web-namespaces "^1.0.0" + xtend "^4.0.0" + zwitch "^1.0.0" + +hastscript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" + integrity sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w== + dependencies: + "@types/hast" "^2.0.0" + comma-separated-tokens "^1.0.0" + hast-util-parse-selector "^2.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +highlight.js@^10.4.1, highlight.js@~10.7.0: + version "10.7.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hoist-non-react-statics@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +html-entities@^2.1.0, html-entities@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" + integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +html-minifier-terser@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#922e96f1f3bb60832c2634b79884096389b1f054" + integrity sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg== + dependencies: + camel-case "^4.1.1" + clean-css "^4.2.3" + commander "^4.1.1" + he "^1.2.0" + param-case "^3.0.3" + relateurl "^0.2.7" + terser "^4.6.3" + +html-minifier-terser@^6.0.2: + version "6.1.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" + integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== + dependencies: + camel-case "^4.1.2" + clean-css "^5.2.2" + commander "^8.3.0" + he "^1.2.0" + param-case "^3.0.4" + relateurl "^0.2.7" + terser "^5.10.0" + +html-tags@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" + integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg== + +html-void-elements@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" + integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== + +html-webpack-plugin@^4.0.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz#76fc83fa1a0f12dd5f7da0404a54e2699666bc12" + integrity sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A== + dependencies: + "@types/html-minifier-terser" "^5.0.0" + "@types/tapable" "^1.0.5" + "@types/webpack" "^4.41.8" + html-minifier-terser "^5.0.1" + loader-utils "^1.2.3" + lodash "^4.17.20" + pretty-error "^2.1.1" + tapable "^1.1.3" + util.promisify "1.0.0" + +html-webpack-plugin@^5.0.0, html-webpack-plugin@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" + integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== + dependencies: + "@types/html-minifier-terser" "^6.0.0" + html-minifier-terser "^6.0.2" + lodash "^4.17.21" + pretty-error "^4.0.0" + tapable "^2.0.0" + +htmlparser2@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" + integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + domutils "^2.5.2" + entities "^2.0.0" + +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.5.1: + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + +http-proxy-middleware@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== + dependencies: + "@types/http-proxy" "^1.17.8" + http-proxy "^1.18.1" + is-glob "^4.0.1" + is-plain-obj "^3.0.0" + micromatch "^4.0.2" + +http-proxy@^1.18.1: + version "1.18.1" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" + integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +icss-utils@^4.0.0, icss-utils@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== + dependencies: + postcss "^7.0.14" + +icss-utils@^5.0.0, icss-utils@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" + integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== + +ieee754@^1.1.4: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + integrity sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA== + +ignore@^4.0.3: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + +import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + integrity sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg== + dependencies: + repeating "^2.0.0" + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +infer-owner@^1.0.3, infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA== + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== + +inline-style-parser@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" + integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== + +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +interpret@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" + integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== + +ip@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" + integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" + integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + +is-absolute-url@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-alphabetical@1.0.4, is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + +is-arguments@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q== + dependencies: + binary-extensions "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-buffer@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-callable@^1.1.4, is-callable@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.8.1, is-core-module@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" + integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== + dependencies: + has "^1.0.3" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-dom@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-dom/-/is-dom-1.1.0.tgz#af1fced292742443bb59ca3f76ab5e80907b4e8a" + integrity sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ== + dependencies: + is-object "^1.0.1" + is-window "^1.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-function@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" + integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== + +is-glob@^3.0.0, is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw== + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + +is-map@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" + integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" + integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== + +is-path-cwd@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + +is-path-in-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" + integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== + dependencies: + is-path-inside "^2.1.0" + +is-path-inside@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" + integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== + dependencies: + path-is-inside "^1.0.2" + +is-plain-obj@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + +is-plain-object@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-regex@^1.1.2, is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-set@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" + integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-whitespace-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" + integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== + +is-window@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-window/-/is-window-1.0.2.tgz#2c896ca53db97de45d3c33133a65d8c9f563480d" + integrity sha512-uj00kdXyZb9t9RcAUAwMZAnkBUwdYGhYlt7djMXhfyhUCzwNba50tIiBKR7q0l7tdoBtFVw/3JmLY6fI3rmZmg== + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-word-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" + integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw== + +is-wsl@^2.1.1, is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +isobject@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" + integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== + +isomorphic-unfetch@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz#87341d5f4f7b63843d468438128cb087b7c3e98f" + integrity sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q== + dependencies: + node-fetch "^2.6.1" + unfetch "^4.2.0" + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-instrument@^5.0.4: + version "5.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz#31d18bdd127f825dd02ea7bfdfd906f8ab840e9f" + integrity sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-reports@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" + integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +iterate-iterator@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/iterate-iterator/-/iterate-iterator-1.0.2.tgz#551b804c9eaa15b847ea6a7cdc2f5bf1ec150f91" + integrity sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw== + +iterate-value@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/iterate-value/-/iterate-value-1.0.2.tgz#935115bd37d006a52046535ebc8d07e9c9337f57" + integrity sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ== + dependencies: + es-get-iterator "^1.0.2" + iterate-iterator "^1.0.1" + +jest-haste-map@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" + integrity sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w== + dependencies: + "@jest/types" "^26.6.2" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + jest-regex-util "^26.0.0" + jest-serializer "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" + micromatch "^4.0.2" + sane "^4.0.3" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.1.2" + +jest-mock@^27.0.6: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6" + integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og== + dependencies: + "@jest/types" "^27.5.1" + "@types/node" "*" + +jest-regex-util@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" + integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== + +jest-serializer@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" + integrity sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.4" + +jest-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" + integrity sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q== + dependencies: + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + graceful-fs "^4.2.4" + is-ci "^2.0.0" + micromatch "^4.0.2" + +jest-worker@^26.5.0, jest-worker@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +js-string-escape@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + integrity sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== + +json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.2, json5@^2.1.3, json5@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" + integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +"jsx-ast-utils@^2.4.1 || ^3.0.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.1.tgz#a3e0f1cb7e230954eab4dcbce9f6288a78f8ba44" + integrity sha512-pxrjmNpeRw5wwVeWyEAk7QJu2GnBO3uzPFmHCKJJFPKK2Cy0cWL23krGtLdnMmbIi6/FjlrQpPyfQI19ByPOhQ== + dependencies: + array-includes "^3.1.5" + object.assign "^4.1.2" + +junk@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" + integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +klona@^2.0.4: + version "2.0.5" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" + integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== + +lazy-universal-dotenv@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz#a6c8938414bca426ab8c9463940da451a911db38" + integrity sha512-prXSYk799h3GY3iOWnC6ZigYzMPjxN2svgjJ9shk7oMadSNX3wXy0B6F32PMJv7qtMnrIbUxoEHzbutvxR2LBQ== + dependencies: + "@babel/runtime" "^7.5.0" + app-root-dir "^1.0.2" + core-js "^3.0.4" + dotenv "^8.0.0" + dotenv-expand "^5.1.0" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A== + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +loader-runner@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +loader-utils@^1.2.3: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + +loader-utils@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" + integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.uniq@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== + +lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +loose-envify@^1.1.0, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + integrity sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ== + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + +lowlight@^1.17.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.20.0.tgz#ddb197d33462ad0d93bf19d17b6c301aa3941888" + integrity sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw== + dependencies: + fault "^1.0.0" + highlight.js "~10.7.0" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lz-string@^1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" + integrity sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ== + +make-dir@^2.0.0, make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +map-age-cleaner@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== + +map-or-similar@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/map-or-similar/-/map-or-similar-1.5.0.tgz#6de2653174adfb5d9edc33c69d3e92a1b76faf08" + integrity sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg== + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== + dependencies: + object-visit "^1.0.0" + +markdown-escapes@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" + integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +mdast-squeeze-paragraphs@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz#7c4c114679c3bee27ef10b58e2e015be79f1ef97" + integrity sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ== + dependencies: + unist-util-remove "^2.0.0" + +mdast-util-definitions@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz#c5c1a84db799173b4dcf7643cda999e440c24db2" + integrity sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ== + dependencies: + unist-util-visit "^2.0.0" + +mdast-util-to-hast@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz#0cfc82089494c52d46eb0e3edb7a4eb2aea021eb" + integrity sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + mdast-util-definitions "^4.0.0" + mdurl "^1.0.0" + unist-builder "^2.0.0" + unist-util-generated "^1.0.0" + unist-util-position "^3.0.0" + unist-util-visit "^2.0.0" + +mdast-util-to-string@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz#27055500103f51637bd07d01da01eb1967a43527" + integrity sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A== + +mdurl@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +mem@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/mem/-/mem-8.1.1.tgz#cf118b357c65ab7b7e0817bdf00c8062297c0122" + integrity sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA== + dependencies: + map-age-cleaner "^0.1.3" + mimic-fn "^3.1.0" + +memfs@^3.1.2, memfs@^3.2.2, memfs@^3.4.3: + version "3.4.7" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.7.tgz#e5252ad2242a724f938cb937e3c4f7ceb1f70e5a" + integrity sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw== + dependencies: + fs-monkey "^1.0.3" + +memoizerific@^1.11.3: + version "1.11.3" + resolved "https://registry.yarnpkg.com/memoizerific/-/memoizerific-1.11.3.tgz#7c87a4646444c32d75438570905f2dbd1b1a805a" + integrity sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog== + dependencies: + map-or-similar "^1.5.0" + +memory-fs@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +meow@^3.1.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + integrity sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA== + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +microevent.ts@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/microevent.ts/-/microevent.ts-0.1.1.tgz#70b09b83f43df5172d0205a63025bce0f7357fa0" + integrity sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g== + +micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + 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" + +micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.30, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mime@^2.4.4: + version "2.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-fn@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" + integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ== + dependencies: + dom-walk "^0.1.0" + +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + +minipass-collect@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== + dependencies: + minipass "^3.0.0" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.2: + version "1.2.4" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" + integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== + dependencies: + minipass "^3.0.0" + +minipass@^3.0.0, minipass@^3.1.1: + version "3.3.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.4.tgz#ca99f95dd77c43c7a76bf51e6d200025eee0ffae" + integrity sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw== + dependencies: + yallist "^4.0.0" + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== + 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" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@^0.5.1, mkdirp@^0.5.3: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mkdirp@^1.0.3, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + integrity sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ== + 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" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multicast-dns@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== + dependencies: + dns-packet "^5.2.2" + thunky "^1.0.2" + +nan@^2.12.1: + version "2.16.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.16.0.tgz#664f43e45460fb98faf00edca0bb0d7b8dce7916" + integrity sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA== + +nanoid@^3.3.1, nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + 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" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1, neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz#26c8a3cee6cc05fbcf1e333cd2fc3e003326c0b5" + integrity sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + +node-dir@^0.1.10: + version "0.1.17" + resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" + integrity sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg== + dependencies: + minimatch "^3.0.2" + +node-fetch@^2.6.1, node-fetch@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-forge@^1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== + 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-releases@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" + integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q== + +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== + dependencies: + path-key "^2.0.0" + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + integrity sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg== + +object-assign@^4.0.1, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.12.0, object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.0, object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.entries@^1.1.0, object.entries@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" + integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +"object.fromentries@^2.0.0 || ^1.0.0", object.fromentries@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251" + integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.2: + version "2.1.4" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.4.tgz#7965e6437a57278b587383831a9b829455a4bc37" + integrity sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ== + dependencies: + array.prototype.reduce "^1.0.4" + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.1" + +object.hasown@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.1.tgz#ad1eecc60d03f49460600430d97f23882cf592a3" + integrity sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A== + dependencies: + define-properties "^1.1.4" + es-abstract "^1.19.5" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== + dependencies: + isobject "^3.0.1" + +object.values@^1.1.0, object.values@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" + integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +objectorarray@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/objectorarray/-/objectorarray-1.0.5.tgz#2c05248bbefabd8f43ad13b41085951aac5e68a5" + integrity sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg== + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +open@^7.0.3: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +open@^8.0.9, open@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" + integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== + +p-all@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-all/-/p-all-2.1.0.tgz#91419be56b7dee8fe4c5db875d55e0da084244a0" + integrity sha512-HbZxz5FONzz/z2gJfk6bFca0BCiSRF8jU3yCsWOen/vR6lZjfPOu/e7L3uFzTW1i0H8TlC3vqQstEJPQL4/uLA== + dependencies: + p-map "^2.0.0" + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw== + +p-event@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" + integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ== + dependencies: + p-timeout "^3.1.0" + +p-filter@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-filter/-/p-filter-2.1.0.tgz#1b1472562ae7a0f742f0f3d3d3718ea66ff9c09c" + integrity sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw== + dependencies: + p-map "^2.0.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + +p-retry@^4.5.0: + version "4.6.2" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" + integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== + dependencies: + "@types/retry" "0.12.0" + retry "^0.13.1" + +p-timeout@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" + integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== + dependencies: + p-finally "^1.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@~1.0.5: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +parallel-transform@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== + dependencies: + cyclist "^1.0.1" + inherits "^2.0.3" + readable-stream "^2.1.5" + +param-case@^3.0.3, param-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" + integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + 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" + +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== + dependencies: + error-ex "^1.2.0" + +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + 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" + +parse5@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== + +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q== + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ== + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg== + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pbkdf2@^3.0.3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + 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" + +picocolors@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" + integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.0, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== + +pirates@^4.0.1, pirates@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +pkg-dir@^4.1.0, pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-dir@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" + integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== + dependencies: + find-up "^5.0.0" + +pnp-webpack-plugin@1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" + integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg== + dependencies: + ts-pnp "^1.1.6" + +polished@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/polished/-/polished-4.2.2.tgz#2529bb7c3198945373c52e34618c8fe7b1aa84d1" + integrity sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ== + dependencies: + "@babel/runtime" "^7.17.8" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== + +postcss-flexbugs-fixes@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz#9218a65249f30897deab1033aced8578562a6690" + integrity sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ== + dependencies: + postcss "^7.0.26" + +postcss-loader@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-4.3.0.tgz#2c4de9657cd4f07af5ab42bd60a673004da1b8cc" + integrity sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q== + dependencies: + cosmiconfig "^7.0.0" + klona "^2.0.4" + loader-utils "^2.0.0" + schema-utils "^3.0.0" + semver "^7.3.4" + +postcss-modules-extract-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== + dependencies: + postcss "^7.0.5" + +postcss-modules-extract-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" + integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== + +postcss-modules-local-by-default@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" + integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== + dependencies: + icss-utils "^4.1.1" + postcss "^7.0.32" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-local-by-default@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c" + integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" + integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== + dependencies: + postcss "^7.0.6" + postcss-selector-parser "^6.0.0" + +postcss-modules-scope@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06" + integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg== + dependencies: + postcss-selector-parser "^6.0.4" + +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== + dependencies: + icss-utils "^4.0.0" + postcss "^7.0.6" + +postcss-modules-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" + integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== + dependencies: + icss-utils "^5.0.0" + +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: + version "6.0.10" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" + integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^7.0.14, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.36, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.39" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" + integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== + dependencies: + picocolors "^0.2.1" + source-map "^0.6.1" + +postcss@^8.2.15, postcss@^8.4.7: + version "8.4.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" + integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== + dependencies: + nanoid "^3.3.4" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +"prettier@>=2.2.1 <=2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.0.tgz#b6a5bf1284026ae640f17f7ff5658a7567fc0d18" + integrity sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w== + +prettier@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== + +pretty-error@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.2.tgz#be89f82d81b1c86ec8fdfbc385045882727f93b6" + integrity sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw== + dependencies: + lodash "^4.17.20" + renderkid "^2.0.4" + +pretty-error@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" + integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== + dependencies: + lodash "^4.17.20" + renderkid "^3.0.0" + +pretty-format@^27.0.2: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + +pretty-hrtime@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A== + +prismjs@^1.27.0: + version "1.28.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.28.0.tgz#0d8f561fa0f7cf6ebca901747828b149147044b6" + integrity sha512-8aaXdYvl1F7iC7Xm1spqSaY/OJBpYW3v+KJ+F17iYxvdc8sfjW194COK5wVhMZX45tGteiBQgdvD/nhxcRwylw== + +prismjs@~1.27.0: + version "1.27.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" + integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== + +promise.allsettled@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/promise.allsettled/-/promise.allsettled-1.0.5.tgz#2443f3d4b2aa8dfa560f6ac2aa6c4ea999d75f53" + integrity sha512-tVDqeZPoBC0SlzJHzWGZ2NKAguVq2oiYj7gbggbiTvH2itHohijTp7njOUA0aQ/nl+0lr/r6egmhoYu63UZ/pQ== + dependencies: + array.prototype.map "^1.0.4" + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + iterate-value "^1.0.2" + +promise.prototype.finally@^3.1.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/promise.prototype.finally/-/promise.prototype.finally-3.1.3.tgz#d3186e58fcf4df1682a150f934ccc27b7893389c" + integrity sha512-EXRF3fC9/0gz4qkt/f5EP5iW4kj9oFpBICNpCNOb/52+8nlHIX07FPLbi/q4qYBQ1xZqivMzTpNQSnArVASolQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +prompts@^2.4.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + +prop-types@^15.0.0, prop-types@^15.7.2, prop-types@^15.8.1: + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + +property-information@^5.0.0, property-information@^5.3.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" + integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== + dependencies: + xtend "^4.0.0" + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + 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" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== + +punycode@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@6.10.3: + version "6.10.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + dependencies: + side-channel "^1.0.4" + +qs@^6.10.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== + +querystring@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd" + integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +ramda@^0.28.0: + version "0.28.0" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.28.0.tgz#acd785690100337e8b063cab3470019be427cc97" + integrity sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +raw-loader@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6" + integrity sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +react-docgen-typescript@^2.1.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz#4611055e569edc071204aadb20e1c93e1ab1659c" + integrity sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg== + +react-docgen@^5.0.0: + version "5.4.3" + resolved "https://registry.yarnpkg.com/react-docgen/-/react-docgen-5.4.3.tgz#7d297f73b977d0c7611402e5fc2a168acf332b26" + integrity sha512-xlLJyOlnfr8lLEEeaDZ+X2J/KJoe6Nr9AzxnkdQWush5hz2ZSu66w6iLMOScMmxoSHWpWMn+k3v5ZiyCfcWsOA== + dependencies: + "@babel/core" "^7.7.5" + "@babel/generator" "^7.12.11" + "@babel/runtime" "^7.7.6" + ast-types "^0.14.2" + commander "^2.19.0" + doctrine "^3.0.0" + estree-to-babel "^3.1.0" + neo-async "^2.6.1" + node-dir "^0.1.10" + strip-indent "^3.0.0" + +react-dom@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" + integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.0" + +react-element-to-jsx-string@^14.3.4: + version "14.3.4" + resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-14.3.4.tgz#709125bc72f06800b68f9f4db485f2c7d31218a8" + integrity sha512-t4ZwvV6vwNxzujDQ+37bspnLwA4JlgUPWhLjBJWsNIDceAf6ZKUTCjdm08cN6WeZ5pTMKiCJkmAYnpmR4Bm+dg== + dependencies: + "@base2/pretty-print-object" "1.0.1" + is-plain-object "5.0.0" + react-is "17.0.2" + +react-inspector@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-5.1.1.tgz#58476c78fde05d5055646ed8ec02030af42953c8" + integrity sha512-GURDaYzoLbW8pMGXwYPDBIv6nqei4kK7LPRZ9q9HCZF54wqXz/dnylBp/kfE9XmekBhHvLDdcYeyIwSrvtOiWg== + dependencies: + "@babel/runtime" "^7.0.0" + is-dom "^1.0.0" + prop-types "^15.0.0" + +react-is@17.0.2, react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-is@^16.13.1, react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-merge-refs@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/react-merge-refs/-/react-merge-refs-1.1.0.tgz#73d88b892c6c68cbb7a66e0800faa374f4c38b06" + integrity sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ== + +react-refresh@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" + integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A== + +react-syntax-highlighter@^15.4.5: + version "15.5.0" + resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz#4b3eccc2325fa2ec8eff1e2d6c18fa4a9e07ab20" + integrity sha512-+zq2myprEnQmH5yw6Gqc8lD55QHnpKaU8TOcFeC/Lg/MQSs8UknEA0JC4nTZGFAXC2J2Hyj/ijJ7NlabyPi2gg== + dependencies: + "@babel/runtime" "^7.3.1" + highlight.js "^10.4.1" + lowlight "^1.17.0" + prismjs "^1.27.0" + refractor "^3.6.0" + +react@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== + dependencies: + loose-envify "^1.1.0" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A== + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ== + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + 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" + +readable-stream@^3.0.6, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +rechoir@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== + dependencies: + resolve "^1.9.0" + +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + integrity sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g== + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + +refractor@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a" + integrity sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA== + dependencies: + hastscript "^6.0.0" + parse-entities "^2.0.0" + prismjs "~1.27.0" + +regenerate-unicode-properties@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" + integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== + dependencies: + regenerate "^1.4.2" + +regenerate@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + +regenerator-transform@^0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537" + integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg== + dependencies: + "@babel/runtime" "^7.8.4" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + +regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + +regexpu-core@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.1.0.tgz#2f8504c3fd0ebe11215783a41541e21c79942c6d" + integrity sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA== + dependencies: + regenerate "^1.4.2" + regenerate-unicode-properties "^10.0.1" + regjsgen "^0.6.0" + regjsparser "^0.8.2" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.0.0" + +regjsgen@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d" + integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA== + +regjsparser@^0.8.2: + version "0.8.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f" + integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA== + dependencies: + jsesc "~0.5.0" + +relateurl@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== + +remark-external-links@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/remark-external-links/-/remark-external-links-8.0.0.tgz#308de69482958b5d1cd3692bc9b725ce0240f345" + integrity sha512-5vPSX0kHoSsqtdftSHhIYofVINC8qmp0nctkeU9YoJwV3YfiBRiI6cbFRJ0oI/1F9xS+bopXG0m2KS8VFscuKA== + dependencies: + extend "^3.0.0" + is-absolute-url "^3.0.0" + mdast-util-definitions "^4.0.0" + space-separated-tokens "^1.0.0" + unist-util-visit "^2.0.0" + +remark-footnotes@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-2.0.0.tgz#9001c4c2ffebba55695d2dd80ffb8b82f7e6303f" + integrity sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ== + +remark-mdx@1.6.22: + version "1.6.22" + resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.22.tgz#06a8dab07dcfdd57f3373af7f86bd0e992108bbd" + integrity sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ== + dependencies: + "@babel/core" "7.12.9" + "@babel/helper-plugin-utils" "7.10.4" + "@babel/plugin-proposal-object-rest-spread" "7.12.1" + "@babel/plugin-syntax-jsx" "7.12.1" + "@mdx-js/util" "1.6.22" + is-alphabetical "1.0.4" + remark-parse "8.0.3" + unified "9.2.0" + +remark-parse@8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-8.0.3.tgz#9c62aa3b35b79a486454c690472906075f40c7e1" + integrity sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q== + dependencies: + ccount "^1.0.0" + collapse-white-space "^1.0.2" + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + is-word-character "^1.0.0" + markdown-escapes "^1.0.0" + parse-entities "^2.0.0" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + trim "0.0.1" + trim-trailing-lines "^1.0.0" + unherit "^1.0.4" + unist-util-remove-position "^2.0.0" + vfile-location "^3.0.0" + xtend "^4.0.1" + +remark-slug@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/remark-slug/-/remark-slug-6.1.0.tgz#0503268d5f0c4ecb1f33315c00465ccdd97923ce" + integrity sha512-oGCxDF9deA8phWvxFuyr3oSJsdyUAxMFbA0mZ7Y1Sas+emILtO+e5WutF9564gDsEN4IXaQXm5pFo6MLH+YmwQ== + dependencies: + github-slugger "^1.0.0" + mdast-util-to-string "^1.0.0" + unist-util-visit "^2.0.0" + +remark-squeeze-paragraphs@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz#76eb0e085295131c84748c8e43810159c5653ead" + integrity sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw== + dependencies: + mdast-squeeze-paragraphs "^4.0.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== + +renderkid@^2.0.4: + version "2.0.7" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.7.tgz#464f276a6bdcee606f4a15993f9b29fc74ca8609" + integrity sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ== + dependencies: + css-select "^4.1.3" + dom-converter "^0.2.0" + htmlparser2 "^6.1.0" + lodash "^4.17.21" + strip-ansi "^3.0.1" + +renderkid@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" + integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== + dependencies: + css-select "^4.1.3" + dom-converter "^0.2.0" + htmlparser2 "^6.1.0" + lodash "^4.17.21" + strip-ansi "^6.0.1" + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.5.4, repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== + dependencies: + is-finite "^1.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== + +resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.3.2, resolve@^1.9.0: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^2.0.0-next.3: + version "2.0.0-next.4" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" + integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^2.5.4, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rsvp@^4.8.4: + version "4.8.5" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + integrity sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg== + dependencies: + aproba "^1.1.1" + +safe-buffer@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sane@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" + integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== + dependencies: + "@cnakazawa/watch" "^1.0.3" + anymatch "^2.0.0" + capture-exit "^2.0.0" + exec-sh "^0.3.2" + execa "^1.0.0" + fb-watchman "^2.0.0" + micromatch "^3.1.4" + minimist "^1.1.1" + walker "~1.0.5" + +scheduler@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" + integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== + dependencies: + loose-envify "^1.1.0" + +schema-utils@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" + integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== + dependencies: + "@types/json-schema" "^7.0.4" + ajv "^6.12.2" + ajv-keywords "^3.4.1" + +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== + dependencies: + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + +schema-utils@^2.6.5, schema-utils@^2.7.0: + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== + dependencies: + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" + +schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" + integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== + +selfsigned@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.1.tgz#8b2df7fa56bf014d19b6007655fff209c0ef0a56" + integrity sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ== + dependencies: + node-forge "^1" + +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" + +serialize-javascript@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" + integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== + dependencies: + randombytes "^2.1.0" + +serialize-javascript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +serve-favicon@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.5.0.tgz#935d240cdfe0f5805307fdfe967d88942a2cbcf0" + integrity sha512-FMW2RvqNr03x+C0WxTyu6sOv21oOjkq5j8tjquWccwa6ScNyGFOGJVpuS1NmTVGBAHS07xnSKotgf2ehQmf9iA== + dependencies: + etag "~1.8.1" + fresh "0.5.2" + ms "2.1.1" + parseurl "~1.3.2" + safe-buffer "5.1.1" + +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== + 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" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + 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" + +sockjs@^0.3.24: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + 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" + +source-map-support@^0.5.16, source-map-support@~0.5.12, source-map-support@~0.5.20: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +source-map@^0.7.3: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +space-separated-tokens@^1.0.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" + integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.11" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + 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" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + 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" + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +ssri@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" + integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== + dependencies: + figgy-pudding "^3.5.1" + +ssri@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" + integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== + dependencies: + minipass "^3.1.1" + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +stackframe@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310" + integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw== + +state-toggle@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" + integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + +store2@^2.12.0: + version "2.13.2" + resolved "https://registry.yarnpkg.com/store2/-/store2-2.13.2.tgz#01ad8802ca5b445b9c316b55e72645c13a3cd7e3" + integrity sha512-CMtO2Uneg3SAz/d6fZ/6qbqqQHi2ynq6/KzMD/26gTkiEShCcpqFfTHgOxsE0egAq6SX3FmN4CeSqn8BzXQkJg== + +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + 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" + +stream-shift@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz#8e6ecb0d8a1fb1fda470d81acecb2dba057a481d" + integrity sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + get-intrinsic "^1.1.1" + has-symbols "^1.0.3" + internal-slot "^1.0.3" + regexp.prototype.flags "^1.4.1" + side-channel "^1.0.4" + +string.prototype.padend@^3.0.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz#997a6de12c92c7cb34dc8a201a6c53d9bd88a5f1" + integrity sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +string.prototype.padstart@^3.0.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/string.prototype.padstart/-/string.prototype.padstart-3.1.3.tgz#4551d0117d9501692ec6000b15056ac3f816cfa5" + integrity sha512-NZydyOMtYxpTjGqp0VN5PYUF/tsU15yDMZnUdj16qRUIUiMJkHHSDElYyQFrMu+/WloTpA7MQSiADhBicDfaoA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +string.prototype.trimend@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" + integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" + +string.prototype.trimstart@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" + integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.19.5" + +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg== + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + integrity sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA== + dependencies: + get-stdin "^4.0.1" + +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +style-loader@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" + integrity sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q== + dependencies: + loader-utils "^2.0.0" + schema-utils "^2.7.0" + +style-loader@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-2.0.0.tgz#9669602fd4690740eaaec137799a03addbbc393c" + integrity sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +style-loader@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" + integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== + +style-to-object@0.3.0, style-to-object@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" + integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== + dependencies: + inline-style-parser "0.1.1" + +stylis@4.0.13: + version "4.0.13" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91" + integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +symbol.prototype.description@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/symbol.prototype.description/-/symbol.prototype.description-1.0.5.tgz#d30e01263b6020fbbd2d2884a6276ce4d49ab568" + integrity sha512-x738iXRYsrAt9WBhRCVG5BtIC3B7CUkFwbHW2zOvGtwM33s7JjrCDyq8V0zgMYVb5ymsL8+qkzzpANH63CPQaQ== + dependencies: + call-bind "^1.0.2" + get-symbol-description "^1.0.0" + has-symbols "^1.0.2" + object.getownpropertydescriptors "^2.1.2" + +synchronous-promise@^2.0.15: + version "2.0.15" + resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.15.tgz#07ca1822b9de0001f5ff73595f3d08c4f720eb8e" + integrity sha512-k8uzYIkIVwmT+TcglpdN50pS2y1BDcUnBPK9iJeGu0Pl1lOI8pD6wtzgw91Pjpe+RxtTncw32tLxs/R0yNL2Mg== + +tapable@^1.0.0, tapable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +tar@^6.0.2: + version "6.1.11" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" + integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== + 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" + +telejson@^6.0.8: + version "6.0.8" + resolved "https://registry.yarnpkg.com/telejson/-/telejson-6.0.8.tgz#1c432db7e7a9212c1fbd941c3e5174ec385148f7" + integrity sha512-nerNXi+j8NK1QEfBHtZUN/aLdDcyupA//9kAboYLrtzZlPLpUfqbVGWb9zz91f/mIjRbAYhbgtnJHY8I1b5MBg== + dependencies: + "@types/is-function" "^1.0.0" + global "^4.4.0" + is-function "^1.0.2" + is-regex "^1.1.2" + is-symbol "^1.0.3" + isobject "^4.0.0" + lodash "^4.17.21" + memoizerific "^1.11.3" + +terser-webpack-plugin@^1.4.3: + version "1.4.5" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" + integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== + 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" + +terser-webpack-plugin@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz#28daef4a83bd17c1db0297070adc07fc8cfc6a9a" + integrity sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ== + 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" + +terser-webpack-plugin@^5.0.3, terser-webpack-plugin@^5.1.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz#8033db876dd5875487213e87c627bca323e5ed90" + integrity sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ== + dependencies: + "@jridgewell/trace-mapping" "^0.3.7" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.0" + terser "^5.7.2" + +terser@^4.1.2, terser@^4.6.3: + version "4.8.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" + integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +terser@^5.10.0, terser@^5.3.4, terser@^5.7.2: + version "5.14.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.1.tgz#7c95eec36436cb11cf1902cc79ac564741d19eca" + integrity sha512-+ahUAE+iheqBTDxXhTisdA8hgvbEG1hHOQ9xmNjeUJSoi6DU/gMrKNcfZjHkyY6Alnuyc+ikYJaxxfHkT3+WuQ== + dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" + commander "^2.20.0" + source-map-support "~0.5.20" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + +timers-browserify@^2.0.4: + version "2.0.12" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== + dependencies: + setimmediate "^1.0.4" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + integrity sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw== + +trim-trailing-lines@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" + integrity sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ== + +trim@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ== + +trough@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" + integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== + +ts-dedent@^2.0.0, ts-dedent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== + +ts-loader@^9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.3.1.tgz#fe25cca56e3e71c1087fe48dc67f4df8c59b22d4" + integrity sha512-OkyShkcZTsTwyS3Kt7a4rsT/t2qvEVQuKCTg4LJmpj9fhFR7ukGdZwV6Qq3tRUkqcXtfGpPR7+hFKHCG/0d3Lw== + dependencies: + chalk "^4.1.0" + enhanced-resolve "^5.0.0" + micromatch "^4.0.0" + semver "^7.3.4" + +ts-pnp@^1.1.6: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" + integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== + +tsconfig-paths@^3.14.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" + integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^1.8.1, tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== + dependencies: + prelude-ls "~1.1.2" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + +typescript@^4.7.4: + version "4.7.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" + integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== + +uglify-js@^3.1.4: + version "3.16.2" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.16.2.tgz#0481e1dbeed343ad1c2ddf3c6d42e89b7a6d4def" + integrity sha512-AaQNokTNgExWrkEYA24BTNMSjyqEXPSfhqoS0AxmHkCJ4U+Dyy5AvbGV/sqxuxficEfGGoX3zWw9R7QpLFfEsg== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +unfetch@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" + integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA== + +unherit@^1.0.4: + version "1.1.3" + resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" + integrity sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ== + dependencies: + inherits "^2.0.0" + xtend "^4.0.0" + +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== + dependencies: + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" + +unicode-match-property-value-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" + integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== + +unicode-property-aliases-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" + integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== + +unified@9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.0.tgz#67a62c627c40589edebbf60f53edfd4d822027f8" + integrity sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg== + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^2.0.0" + trough "^1.0.0" + vfile "^4.0.0" + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + +unist-builder@2.0.3, unist-builder@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" + integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== + +unist-util-generated@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b" + integrity sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg== + +unist-util-is@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" + integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== + +unist-util-position@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47" + integrity sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA== + +unist-util-remove-position@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz#5d19ca79fdba712301999b2b73553ca8f3b352cc" + integrity sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA== + dependencies: + unist-util-visit "^2.0.0" + +unist-util-remove@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-2.1.0.tgz#b0b4738aa7ee445c402fda9328d604a02d010588" + integrity sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q== + dependencies: + unist-util-is "^4.0.0" + +unist-util-stringify-position@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" + integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== + dependencies: + "@types/unist" "^2.0.2" + +unist-util-visit-parents@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" + integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + +unist-util-visit@2.0.3, unist-util-visit@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" + integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + unist-util-visit-parents "^3.0.0" + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +untildify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/untildify/-/untildify-2.1.0.tgz#17eb2807987f76952e9c0485fc311d06a826a2e0" + integrity sha512-sJjbDp2GodvkB0FZZcn7k6afVisqX5BZD7Yq3xp4nN2O15BBK0cLm3Vwn2vQaF7UDS0UUsrQMkkplmDI5fskig== + dependencies: + os-homedir "^1.0.0" + +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + +update-browserslist-db@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz#dbfc5a789caa26b1db8990796c2c8ebbce304824" + integrity sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== + +url-loader@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.1.tgz#28505e905cae158cf07c92ca622d7f237e70a4e2" + integrity sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA== + dependencies: + loader-utils "^2.0.0" + mime-types "^2.1.27" + schema-utils "^3.0.0" + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ== + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +util.promisify@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ== + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +utila@~0.4: + version "0.4.0" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" + integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +uuid-browser@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/uuid-browser/-/uuid-browser-3.1.0.tgz#0f05a40aef74f9e5951e20efbf44b11871e56410" + integrity sha512-dsNgbLaTrd6l3MMxTtouOCFw4CBFc/3a+GgYA2YyrJvyQ1u6q4pcu3ktLoUZ/VN/Aw9WsauazbgsgdfVWgAKQg== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache@^2.0.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" + integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== + +v8-to-istanbul@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz#b6f994b0b5d4ef255e17a0d17dc444a9f5132fa4" + integrity sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +vfile-location@^3.0.0, vfile-location@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-3.2.0.tgz#d8e41fbcbd406063669ebf6c33d56ae8721d0f3c" + integrity sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA== + +vfile-message@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" + integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^2.0.0" + +vfile@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" + integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + unist-util-stringify-position "^2.0.0" + vfile-message "^2.0.0" + +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + +walker@^1.0.7, walker@~1.0.5: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +watchpack-chokidar2@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" + integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== + dependencies: + chokidar "^2.1.8" + +watchpack@^1.7.4: + version "1.7.5" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" + integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== + dependencies: + graceful-fs "^4.1.2" + neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.1" + watchpack-chokidar2 "^2.0.1" + +watchpack@^2.2.0, watchpack@^2.3.1: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + +web-namespaces@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" + integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webpack-cli@^4.10.0: + version "4.10.0" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" + integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.2.0" + "@webpack-cli/info" "^1.5.0" + "@webpack-cli/serve" "^1.7.0" + colorette "^2.0.14" + commander "^7.0.0" + cross-spawn "^7.0.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + webpack-merge "^5.7.3" + +webpack-dev-middleware@^3.7.3: + version "3.7.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" + integrity sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ== + dependencies: + memory-fs "^0.4.1" + mime "^2.4.4" + mkdirp "^0.5.1" + range-parser "^1.2.1" + webpack-log "^2.0.0" + +webpack-dev-middleware@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz#179cc40795882cae510b1aa7f3710cbe93c9333e" + integrity sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w== + dependencies: + colorette "^1.2.2" + mem "^8.1.1" + memfs "^3.2.2" + mime-types "^2.1.30" + range-parser "^1.2.1" + schema-utils "^3.0.0" + +webpack-dev-middleware@^5.3.1: + version "5.3.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" + integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== + dependencies: + colorette "^2.0.10" + memfs "^3.4.3" + mime-types "^2.1.31" + range-parser "^1.2.1" + schema-utils "^4.0.0" + +webpack-dev-server@^4.9.3: + version "4.9.3" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.9.3.tgz#2360a5d6d532acb5410a668417ad549ee3b8a3c9" + integrity sha512-3qp/eoboZG5/6QgiZ3llN8TUzkSpYg1Ko9khWX1h40MIEUNS2mDoIa8aXsPfskER+GbTvs/IJZ1QTBBhhuetSw== + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" + "@types/serve-index" "^1.9.1" + "@types/serve-static" "^1.13.10" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.5.1" + ansi-html-community "^0.0.8" + bonjour-service "^1.0.11" + chokidar "^3.5.3" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^2.0.0" + default-gateway "^6.0.3" + express "^4.17.3" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.3" + ipaddr.js "^2.0.1" + open "^8.0.9" + p-retry "^4.5.0" + rimraf "^3.0.2" + schema-utils "^4.0.0" + selfsigned "^2.0.1" + serve-index "^1.9.1" + sockjs "^0.3.24" + spdy "^4.0.2" + webpack-dev-middleware "^5.3.1" + ws "^8.4.2" + +webpack-filter-warnings-plugin@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz#dc61521cf4f9b4a336fbc89108a75ae1da951cdb" + integrity sha512-Ez6ytc9IseDMLPo0qCuNNYzgtUl8NovOqjIq4uAU8LTD4uoa1w1KpZyyzFtLTEMZpkkOkLfL9eN+KGYdk1Qtwg== + +webpack-hot-middleware@^2.25.1: + version "2.25.1" + resolved "https://registry.yarnpkg.com/webpack-hot-middleware/-/webpack-hot-middleware-2.25.1.tgz#581f59edf0781743f4ca4c200fd32c9266c6cf7c" + integrity sha512-Koh0KyU/RPYwel/khxbsDz9ibDivmUbrRuKSSQvW42KSDdO4w23WI3SkHpSUKHE76LrFnnM/L7JCrpBwu8AXYw== + dependencies: + ansi-html-community "0.0.8" + html-entities "^2.1.0" + querystring "^0.2.0" + strip-ansi "^6.0.0" + +webpack-log@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" + integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== + dependencies: + ansi-colors "^3.0.0" + uuid "^3.3.2" + +webpack-merge@^5.7.3: + version "5.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + +webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack-virtual-modules@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.2.2.tgz#20863dc3cb6bb2104729fff951fbe14b18bd0299" + integrity sha512-kDUmfm3BZrei0y+1NTHJInejzxfhtU8eDj2M7OKb2IWrPFAeO1SOH2KuQ68MSZu9IGEHcxbkKKR1v18FrUSOmA== + dependencies: + debug "^3.0.0" + +webpack-virtual-modules@^0.4.1: + version "0.4.4" + resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.4.4.tgz#a19fcf371923c59c4712d63d7d194b1e4d8262cc" + integrity sha512-h9atBP/bsZohWpHnr+2sic8Iecb60GxftXsWNLLLSqewgIsGzByd2gcIID4nXcG+3tNe4GQG3dLcff3kXupdRA== + +webpack@4: + version "4.46.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" + integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== + 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.5.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" + +"webpack@>=4.43.0 <6.0.0", webpack@^5.73.0, webpack@^5.9.0: + version "5.73.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.73.0.tgz#bbd17738f8a53ee5760ea2f59dce7f3431d35d38" + integrity sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.4.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.9.3" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.3.1" + webpack-sources "^3.2.3" + +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + +word-wrap@^1.2.3, word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== + +worker-farm@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" + integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== + dependencies: + errno "~0.1.7" + +worker-rpc@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/worker-rpc/-/worker-rpc-0.1.1.tgz#cb565bd6d7071a8f16660686051e969ad32f54d5" + integrity sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg== + dependencies: + microevent.ts "~0.1.1" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@^8.2.3, ws@^8.4.2: + version "8.8.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.0.tgz#8e71c75e2f6348dbf8d78005107297056cb77769" + integrity sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ== + +x-default-browser@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/x-default-browser/-/x-default-browser-0.4.0.tgz#70cf0da85da7c0ab5cb0f15a897f2322a6bdd481" + integrity sha512-7LKo7RtWfoFN/rHx1UELv/2zHGMx8MkZKDq1xENmOCTkfIqZJ0zZ26NEJX8czhnPXVcqS0ARjjfJB+eJ0/5Cvw== + optionalDependencies: + default-browser-id "^1.0.4" + +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yaml@^1.10.0, yaml@^1.7.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" + integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== + +yargs-parser@^20.2.2, yargs-parser@^20.2.9: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zwitch@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" + integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== From 7d43a3bf91fe03287d1b54831316fb97ee4835b4 Mon Sep 17 00:00:00 2001 From: jhy979 <32920566+jhy979@users.noreply.github.com> Date: Mon, 4 Jul 2022 20:45:58 +0900 Subject: [PATCH 0002/1011] =?UTF-8?q?chore:=20EOL=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/.gitignore b/frontend/.gitignore index 76add878..f06235c4 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -1,2 +1,2 @@ node_modules -dist \ No newline at end of file +dist From a856245e114211549ea3b2a61565e066b3409d2e Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 5 Jul 2022 14:43:47 +0900 Subject: [PATCH 0003/1011] =?UTF-8?q?chore:=20=EC=A0=88=EB=8C=80=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/tsconfig.json | 8 +++++++- frontend/webpack.config.js | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index eb62d456..eaf372ba 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -6,7 +6,13 @@ "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true, - "esModuleInterop": true + "esModuleInterop": true, + "jsxImportSource": "@emotion/react", + "moduleResolution": "node", + "baseUrl": ".", + "paths": { + "@/*": ["src/*"] + } }, "exclude": ["node_modules"], "include": ["src"] diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index 512a3bc3..75c96e20 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -10,6 +10,9 @@ module.exports = { devtool: prod ? 'hidden-source-map' : 'eval', entry: './src/index.tsx', resolve: { + alias: { + '@': path.resolve(__dirname, './src/'), + }, extensions: ['.js', '.jsx', '.ts', '.tsx'], }, module: { From 65b298cea935bb1348a9b23b983d7eb179ef1ff1 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 5 Jul 2022 14:44:36 +0900 Subject: [PATCH 0004/1011] =?UTF-8?q?fix:=20prettier=20EOL=20=EC=98=A4?= =?UTF-8?q?=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/.prettierrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json index b5b29cff..c9a045c4 100644 --- a/frontend/.prettierrc.json +++ b/frontend/.prettierrc.json @@ -8,5 +8,5 @@ "bracketSpacing": true, "bracketSameLine": false, "arrowParens": "always", - "endofLine": "auto" + "endOfLine": "auto" } From f6a3d30d4ace868dfddb1be2edb9d4359df3d4f3 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 5 Jul 2022 14:47:52 +0900 Subject: [PATCH 0005/1011] =?UTF-8?q?style:=20global=20style=20=EB=B0=8F?= =?UTF-8?q?=20theme=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/package.json | 1 + frontend/src/index.html | 3 +++ frontend/src/index.tsx | 16 ++++++++++++++-- frontend/src/styles/GlobalStyle.tsx | 25 +++++++++++++++++++++++++ frontend/src/styles/theme.ts | 9 +++++++++ frontend/yarn.lock | 5 +++++ 6 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 frontend/src/styles/GlobalStyle.tsx create mode 100644 frontend/src/styles/theme.ts diff --git a/frontend/package.json b/frontend/package.json index 170eeb1c..c786041e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,6 +14,7 @@ "dependencies": { "@emotion/react": "^11.9.3", "@emotion/styled": "^11.9.3", + "emotion-reset": "^3.0.1", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/frontend/src/index.html b/frontend/src/index.html index 020ed219..2bf44d86 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -3,6 +3,9 @@ + 달록 diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 48b5a1e3..c0973b94 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -1,5 +1,17 @@ import ReactDOM from 'react-dom'; -import App from './App'; +import { ThemeProvider } from '@emotion/react'; + +import theme from '@/styles/theme'; +import GlobalStyle from '@/styles/GlobalStyle'; + +import App from '@/App'; const rootElement = document.getElementById('root'); -ReactDOM.render(, rootElement); + +ReactDOM.render( + + + + , + rootElement +); diff --git a/frontend/src/styles/GlobalStyle.tsx b/frontend/src/styles/GlobalStyle.tsx new file mode 100644 index 00000000..c49a3e7f --- /dev/null +++ b/frontend/src/styles/GlobalStyle.tsx @@ -0,0 +1,25 @@ +import emotionReset from 'emotion-reset'; +import { Global, css } from '@emotion/react'; + +const global = css` + ${emotionReset} + + *, + *::after, + *::before { + margin: 0; + + box-sizing: border-box; + } + + body { + font-family: 'Nanum Gothic', sans-serif; + font-size: 12px; + } +`; + +function GlobalStyle() { + return ; +} + +export default GlobalStyle; diff --git a/frontend/src/styles/theme.ts b/frontend/src/styles/theme.ts new file mode 100644 index 00000000..b73e2ed4 --- /dev/null +++ b/frontend/src/styles/theme.ts @@ -0,0 +1,9 @@ +const colors = { + yellow_500: '#FCC419', +}; + +const theme = { + colors, +}; + +export default theme; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index d7e4d0e1..ee32826d 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -5120,6 +5120,11 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== +emotion-reset@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/emotion-reset/-/emotion-reset-3.0.1.tgz#1445e66bab7e8fd9975ce0d8cd3324589981f0a6" + integrity sha512-v6scW83qSu+wtxg7lX1s0+/2U4EAAGFxDQMkvXE10jhKtyuXCzy3/su5/MU9ZjXeNv6ZjxZH51WktrKosKUy9g== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" From b00c4e067d8ebb957d226d20c056fb6da5860c48 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 5 Jul 2022 20:23:57 +0900 Subject: [PATCH 0006/1011] =?UTF-8?q?feat:=20=EB=82=B4=EB=B9=84=EA=B2=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=EB=B0=94=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/.storybook/main.js | 12 ++++++++++ frontend/.storybook/preview.js | 23 +++++++++++++++++++ frontend/babel.config.js | 7 +++++- frontend/package.json | 1 + frontend/src/@types/emotion.d.ts | 11 +++++++++ .../src/components/NavBar/NavBar.stories.tsx | 13 +++++++++++ .../src/components/NavBar/NavBar.styles.ts | 14 +++++++++++ frontend/src/components/NavBar/NavBar.tsx | 10 ++++++++ frontend/src/styles/theme.ts | 5 +++- frontend/yarn.lock | 23 ++++++++++++++++--- 10 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 frontend/.storybook/main.js create mode 100644 frontend/.storybook/preview.js create mode 100644 frontend/src/@types/emotion.d.ts create mode 100644 frontend/src/components/NavBar/NavBar.stories.tsx create mode 100644 frontend/src/components/NavBar/NavBar.styles.ts create mode 100644 frontend/src/components/NavBar/NavBar.tsx diff --git a/frontend/.storybook/main.js b/frontend/.storybook/main.js new file mode 100644 index 00000000..09b55fd9 --- /dev/null +++ b/frontend/.storybook/main.js @@ -0,0 +1,12 @@ +module.exports = { + stories: ['../src/**/*.stories.@(tsx)'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/addon-interactions', + ], + framework: '@storybook/react', + core: { + builder: '@storybook/builder-webpack5', + }, +}; diff --git a/frontend/.storybook/preview.js b/frontend/.storybook/preview.js new file mode 100644 index 00000000..76ac274f --- /dev/null +++ b/frontend/.storybook/preview.js @@ -0,0 +1,23 @@ +import { ThemeProvider } from '@emotion/react'; + +import GlobalStyle from '../src/styles/GlobalStyle'; +import theme from '../src/styles/theme'; + +export const parameters = { + actions: { argTypesRegex: '^on[A-Z].*' }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, +}; + +export const decorators = [ + (Story) => ( + + + + + ), +]; diff --git a/frontend/babel.config.js b/frontend/babel.config.js index 01db9fa0..32315f68 100644 --- a/frontend/babel.config.js +++ b/frontend/babel.config.js @@ -1,4 +1,9 @@ module.exports = { - presets: ['@babel/preset-react', '@babel/preset-env', '@babel/preset-typescript'], + presets: [ + '@babel/preset-react', + '@babel/preset-env', + '@babel/preset-typescript', + '@emotion/babel-preset-css-prop', + ], plugins: ['@emotion'], }; diff --git a/frontend/package.json b/frontend/package.json index c786041e..b2aaad66 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -24,6 +24,7 @@ "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.18.6", "@emotion/babel-plugin": "^11.9.2", + "@emotion/babel-preset-css-prop": "^11.2.0", "@storybook/addon-actions": "^6.5.9", "@storybook/addon-essentials": "^6.5.9", "@storybook/addon-interactions": "^6.5.9", diff --git a/frontend/src/@types/emotion.d.ts b/frontend/src/@types/emotion.d.ts new file mode 100644 index 00000000..b4f6210a --- /dev/null +++ b/frontend/src/@types/emotion.d.ts @@ -0,0 +1,11 @@ +import '@emotion/react'; + +interface Colors { + [key: string]: string; +} + +declare module '@emotion/react' { + export interface Theme { + colors: Colors; + } +} diff --git a/frontend/src/components/NavBar/NavBar.stories.tsx b/frontend/src/components/NavBar/NavBar.stories.tsx new file mode 100644 index 00000000..d7838b64 --- /dev/null +++ b/frontend/src/components/NavBar/NavBar.stories.tsx @@ -0,0 +1,13 @@ +// eslint-disable-next-line import/named +import { ComponentStory, ComponentMeta } from '@storybook/react'; + +import NavBar from './NavBar'; + +export default { + title: 'Components/NavBar', + component: NavBar, +} as ComponentMeta; + +const Template: ComponentStory = () => ; + +export const Primary = Template.bind({}); diff --git a/frontend/src/components/NavBar/NavBar.styles.ts b/frontend/src/components/NavBar/NavBar.styles.ts new file mode 100644 index 00000000..53285626 --- /dev/null +++ b/frontend/src/components/NavBar/NavBar.styles.ts @@ -0,0 +1,14 @@ +// eslint-disable-next-line import/named +import { css, Theme } from '@emotion/react'; + +const navBar = ({ colors }: Theme) => css` + width: 100%; + height: 64px; + padding: 8px; + + background: ${colors.yellow_500}; + + box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); +`; + +export { navBar }; diff --git a/frontend/src/components/NavBar/NavBar.tsx b/frontend/src/components/NavBar/NavBar.tsx new file mode 100644 index 00000000..22ee7eb2 --- /dev/null +++ b/frontend/src/components/NavBar/NavBar.tsx @@ -0,0 +1,10 @@ +import { navBar } from './NavBar.styles'; +import { useTheme } from '@emotion/react'; + +function NavBar() { + const theme = useTheme(); + + return
; +} + +export default NavBar; diff --git a/frontend/src/styles/theme.ts b/frontend/src/styles/theme.ts index b73e2ed4..5b07e231 100644 --- a/frontend/src/styles/theme.ts +++ b/frontend/src/styles/theme.ts @@ -1,8 +1,11 @@ +// eslint-disable-next-line import/named +import { Theme } from '@emotion/react'; + const colors = { yellow_500: '#FCC419', }; -const theme = { +const theme: Theme = { colors, }; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index ee32826d..c7b54134 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -555,7 +555,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-jsx@^7.12.13", "@babel/plugin-syntax-jsx@^7.18.6": +"@babel/plugin-syntax-jsx@^7.12.13", "@babel/plugin-syntax-jsx@^7.18.6", "@babel/plugin-syntax-jsx@^7.2.0": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== @@ -833,7 +833,7 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.18.6" -"@babel/plugin-transform-react-jsx@^7.12.12", "@babel/plugin-transform-react-jsx@^7.18.6": +"@babel/plugin-transform-react-jsx@^7.12.1", "@babel/plugin-transform-react-jsx@^7.12.12", "@babel/plugin-transform-react-jsx@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.6.tgz#2721e96d31df96e3b7ad48ff446995d26bc028ff" integrity sha512-Mz7xMPxoy9kPS/JScj6fJs03TZ/fZ1dJPlMjRAgTaxaS0fUBk8FV/A2rRgfPsVCZqALNwMexD+0Uaf5zlcKPpw== @@ -1188,7 +1188,14 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@emotion/babel-plugin@^11.7.1", "@emotion/babel-plugin@^11.9.2": +"@emotion/babel-plugin-jsx-pragmatic@^0.1.5": + version "0.1.5" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin-jsx-pragmatic/-/babel-plugin-jsx-pragmatic-0.1.5.tgz#27debfe9c27c4d83574d509787ae553bf8a34d7e" + integrity sha512-y+3AJ0SItMDaAgGPVkQBC/S/BaqaPACkQ6MyCI2CUlrjTxKttTVfD3TMtcs7vLEcLxqzZ1xiG0vzwCXjhopawQ== + dependencies: + "@babel/plugin-syntax-jsx" "^7.2.0" + +"@emotion/babel-plugin@^11.2.0", "@emotion/babel-plugin@^11.7.1", "@emotion/babel-plugin@^11.9.2": version "11.9.2" resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz#723b6d394c89fb2ef782229d92ba95a740576e95" integrity sha512-Pr/7HGH6H6yKgnVFNEj2MVlreu3ADqftqjqwUvDy/OJzKFgxKeTQ+eeUf20FOTuHVkDON2iNa25rAXVYtWJCjw== @@ -1206,6 +1213,16 @@ source-map "^0.5.7" stylis "4.0.13" +"@emotion/babel-preset-css-prop@^11.2.0": + version "11.2.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-preset-css-prop/-/babel-preset-css-prop-11.2.0.tgz#c7e945f56b2610b438f0dc8ae5253fc55488de0e" + integrity sha512-9XLQm2eLPYTho+Cx1LQTDA1rATjoAaB4O+ds55XDvoAa+Z16Hhg8y5Vihj3C8E6+ilDM8SV5A9Z6z+yj0YIRBg== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.12.1" + "@babel/runtime" "^7.7.2" + "@emotion/babel-plugin" "^11.2.0" + "@emotion/babel-plugin-jsx-pragmatic" "^0.1.5" + "@emotion/cache@^11.9.3": version "11.9.3" resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.9.3.tgz#96638449f6929fd18062cfe04d79b29b44c0d6cb" From a0657bbad2def5c81fc1beec16768aba4a2e311b Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 5 Jul 2022 21:08:54 +0900 Subject: [PATCH 0007/1011] =?UTF-8?q?feat:=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../src/components/@common/Button.stories.tsx | 17 +++++++++++++++++ .../src/components/@common/Button.styles.ts | 9 +++++++++ frontend/src/components/@common/Button.tsx | 17 +++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 frontend/src/components/@common/Button.stories.tsx create mode 100644 frontend/src/components/@common/Button.styles.ts create mode 100644 frontend/src/components/@common/Button.tsx diff --git a/frontend/src/components/@common/Button.stories.tsx b/frontend/src/components/@common/Button.stories.tsx new file mode 100644 index 00000000..4d2215b0 --- /dev/null +++ b/frontend/src/components/@common/Button.stories.tsx @@ -0,0 +1,17 @@ +// eslint-disable-next-line import/named +import { ComponentStory, ComponentMeta } from '@storybook/react'; + +import Button from './Button'; + +export default { + title: 'Components/Button', + component: Button, +} as ComponentMeta; + +const Template: ComponentStory = (args) => + ); +} + +export default Button; From 9a3f33e4131cad5ff182801171e492df8b710fcb Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 5 Jul 2022 22:08:27 +0900 Subject: [PATCH 0008/1011] =?UTF-8?q?style:=20=EA=B8=80=EA=BC=B4=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/index.html | 3 --- frontend/src/styles/GlobalStyle.tsx | 4 +++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/frontend/src/index.html b/frontend/src/index.html index 2bf44d86..020ed219 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -3,9 +3,6 @@ - 달록 diff --git a/frontend/src/styles/GlobalStyle.tsx b/frontend/src/styles/GlobalStyle.tsx index c49a3e7f..d4752746 100644 --- a/frontend/src/styles/GlobalStyle.tsx +++ b/frontend/src/styles/GlobalStyle.tsx @@ -2,6 +2,8 @@ import emotionReset from 'emotion-reset'; import { Global, css } from '@emotion/react'; const global = css` + @import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.4/dist/web/static/pretendard.css'); + ${emotionReset} *, @@ -13,7 +15,7 @@ const global = css` } body { - font-family: 'Nanum Gothic', sans-serif; + font-family: 'Pretendard', sans-serif; font-size: 12px; } `; From 2d121b9ee8360e547681675f6b04c82ef4d9b761 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 5 Jul 2022 22:10:16 +0900 Subject: [PATCH 0009/1011] =?UTF-8?q?feat:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B2=84=ED=8A=BC=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../src/components/@common/Button.styles.ts | 3 +++ frontend/src/components/@common/Button.tsx | 10 ++++++--- .../ScheduleAddButton.stories.tsx | 13 +++++++++++ .../ScheduleAddButton.styles.ts | 22 +++++++++++++++++++ .../ScheduleAddButton/ScheduleAddButton.tsx | 14 ++++++++++++ frontend/src/styles/theme.ts | 2 ++ 6 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx create mode 100644 frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts create mode 100644 frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx diff --git a/frontend/src/components/@common/Button.styles.ts b/frontend/src/components/@common/Button.styles.ts index c40dc683..53a58b1c 100644 --- a/frontend/src/components/@common/Button.styles.ts +++ b/frontend/src/components/@common/Button.styles.ts @@ -1,6 +1,9 @@ import { css } from '@emotion/react'; const button = css` + border: none; + + font-family: inherit; text-align: center; cursor: pointer; diff --git a/frontend/src/components/@common/Button.tsx b/frontend/src/components/@common/Button.tsx index 22b92bfa..19d22195 100644 --- a/frontend/src/components/@common/Button.tsx +++ b/frontend/src/components/@common/Button.tsx @@ -1,14 +1,18 @@ +// eslint-disable-next-line import/named +import { SerializedStyles } from '@emotion/react'; + import { button } from './Button.styles'; interface ButtonProps { type?: 'button' | 'submit' | 'reset'; - onClick: () => void; + css?: SerializedStyles; + onClick?: () => void; children?: string | JSX.Element | JSX.Element[]; } -function Button({ type = 'button', onClick, children, ...props }: ButtonProps) { +function Button({ type = 'button', css, onClick, children, ...props }: ButtonProps) { return ( - ); diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx new file mode 100644 index 00000000..c2f0992b --- /dev/null +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx @@ -0,0 +1,13 @@ +// eslint-disable-next-line import/named +import { ComponentStory, ComponentMeta } from '@storybook/react'; + +import ScheduleAddButton from './ScheduleAddButton'; + +export default { + title: 'Components/ScheduleAddButton', + component: ScheduleAddButton, +} as ComponentMeta; + +const Template: ComponentStory = () => ; + +export const Primary = Template.bind({}); diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts new file mode 100644 index 00000000..7bb90551 --- /dev/null +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts @@ -0,0 +1,22 @@ +// eslint-disable-next-line import/named +import { css, Theme } from '@emotion/react'; + +const scheduleAddButton = ({ colors }: Theme) => css` + width: 36px; + height: 36px; + + border-radius: 50%; + + background: ${colors.yellow_500}; + + font-size: 20px; + line-height: 20px; + font-weight: 700; + color: ${colors.white}; + + &:hover { + opacity: 0.7; + } +`; + +export { scheduleAddButton }; diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx new file mode 100644 index 00000000..79152a53 --- /dev/null +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx @@ -0,0 +1,14 @@ +/* eslint-disable import/named */ +import { useTheme } from '@emotion/react'; + +import { scheduleAddButton } from './ScheduleAddButton.styles'; + +import Button from '../@common/Button'; + +function ScheduleAddButton() { + const theme = useTheme(); + + return ; +} + +export default ScheduleAddButton; diff --git a/frontend/src/styles/theme.ts b/frontend/src/styles/theme.ts index 5b07e231..8a595ad5 100644 --- a/frontend/src/styles/theme.ts +++ b/frontend/src/styles/theme.ts @@ -3,6 +3,8 @@ import { Theme } from '@emotion/react'; const colors = { yellow_500: '#FCC419', + white: '#fff', + black: '#000', }; const theme: Theme = { From 1587d112fcb39f5f47816789dcbe7e9b6e9722cf Mon Sep 17 00:00:00 2001 From: jhy979 <32920566+jhy979@users.noreply.github.com> Date: Tue, 5 Jul 2022 22:14:34 +0900 Subject: [PATCH 0010/1011] =?UTF-8?q?refactor:=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EC=8A=A4=ED=86=A0=EB=A6=AC=20title=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/@common/Button.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/@common/Button.stories.tsx b/frontend/src/components/@common/Button.stories.tsx index 4d2215b0..3a43e86a 100644 --- a/frontend/src/components/@common/Button.stories.tsx +++ b/frontend/src/components/@common/Button.stories.tsx @@ -4,7 +4,7 @@ import { ComponentStory, ComponentMeta } from '@storybook/react'; import Button from './Button'; export default { - title: 'Components/Button', + title: 'Components/@Common/Button', component: Button, } as ComponentMeta; From 3c4b8fe33c43f708dfc6f05a27563ad55eccce0c Mon Sep 17 00:00:00 2001 From: koo Date: Mon, 4 Jul 2022 19:20:16 +0900 Subject: [PATCH 0011/1011] =?UTF-8?q?chore:=20RestAssured=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/backend/build.gradle b/backend/build.gradle index fc7408c2..dcbcb02b 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -1,7 +1,7 @@ plugins { - id 'org.springframework.boot' version '2.7.1' - id 'io.spring.dependency-management' version '1.0.11.RELEASE' - id 'java' + id 'org.springframework.boot' version '2.7.1' + id 'io.spring.dependency-management' version '1.0.11.RELEASE' + id 'java' } group = 'com.allog' @@ -9,17 +9,20 @@ version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' repositories { - mavenCentral() + mavenCentral() } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'org.springframework.boot:spring-boot-starter-web' - runtimeOnly 'com.h2database:h2' - testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-web' + + runtimeOnly 'com.h2database:h2' + + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'io.rest-assured:rest-assured:4.4.0' } tasks.named('test') { - useJUnitPlatform() + useJUnitPlatform() } From 64e3e42c59bb14c705278b179ee1247966cb6abb Mon Sep 17 00:00:00 2001 From: koo Date: Mon, 4 Jul 2022 19:24:56 +0900 Subject: [PATCH 0012/1011] =?UTF-8?q?test:=20Acceptance=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=84=A4=EC=A0=95=20=EA=B0=9D=EC=B2=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/acceptance/AcceptanceTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java new file mode 100644 index 00000000..16fa347e --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java @@ -0,0 +1,20 @@ +package com.allog.dallog.acceptance; + +import io.restassured.RestAssured; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.test.annotation.DirtiesContext; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +public class AcceptanceTest { + + @LocalServerPort + int port; + + @BeforeEach + public void setUp() { + RestAssured.port = port; + } +} From 520d0ee9f24b70107b3394123bd857826ee048b5 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Mon, 4 Jul 2022 20:13:08 +0900 Subject: [PATCH 0013/1011] =?UTF-8?q?test:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EC=9D=B8=EC=88=98=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acceptance/SchedulesAcceptanceTest.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java new file mode 100644 index 00000000..377e2b7e --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java @@ -0,0 +1,39 @@ +package com.allog.dallog.acceptance; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +@DisplayName("일정 관련 기능") +public class SchedulesAcceptanceTest extends AcceptanceTest { + + @DisplayName("정상적인 일정정보를 등록하면 상태코드 201을 반환한다.") + @Test + public void 정상적인_일정정보를_등록하면_상태코드_201을_반환한다() { + // given + Map params = new HashMap<>(); + params.put("title", "알록달록 회의"); + params.put("startDateTime", "2022-07-04T13:00"); + params.put("endDateTime", "2022-07-05T07:00"); + params.put("memo", "알록달록 회의가 있어요"); + + // when + ExtractableResponse response = RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(params) + .when().post("/api/schedules") + .then().log().all() + .extract(); + + // then + assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); + } +} From 47407b42f83eeb6c992a04203a8f23117bfebf4f Mon Sep 17 00:00:00 2001 From: devHudi Date: Mon, 4 Jul 2022 20:46:38 +0900 Subject: [PATCH 0014/1011] =?UTF-8?q?feat:=20Period=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=EA=B2=80=EC=A6=9D?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 종료일시가 시작일시 이전이라면 예외를 던진다. --- .../allog/dallog/schedule/domain/Period.java | 22 ++++++++++++++++++ .../dallog/schedule/domain/PeriodTest.java | 23 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/schedule/domain/Period.java create mode 100644 backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java new file mode 100644 index 00000000..71fd96e5 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java @@ -0,0 +1,22 @@ +package com.allog.dallog.schedule.domain; + +import java.time.LocalDateTime; + +public class Period { + + private LocalDateTime startDateTime; + private LocalDateTime endDateTime; + + public Period(final LocalDateTime startDateTime, final LocalDateTime endDateTime) { + validate(startDateTime, endDateTime); + + this.startDateTime = startDateTime; + this.endDateTime = endDateTime; + } + + private void validate(final LocalDateTime startDateTime, final LocalDateTime endDateTime) { + if (startDateTime.isAfter(endDateTime)) { + throw new IllegalArgumentException("종료일시가 시작일시보다 이전일 수 없습니다."); + } + } +} diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java new file mode 100644 index 00000000..e52498b1 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java @@ -0,0 +1,23 @@ +package com.allog.dallog.schedule.domain; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.time.LocalDateTime; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class PeriodTest { + + @DisplayName("종료일시가 시작일시 이전이라면 예외를 던진다.") + @Test + void 종료일시가_시작일시_이전이라면_예외를_던진다() { + // given + LocalDateTime startDateTime = LocalDateTime.of(2022, 1, 2, 0, 0); + LocalDateTime endDateTime = LocalDateTime.of(2022, 1, 1, 0, 0); + + // when & then + assertThatThrownBy(() -> new Period(startDateTime, endDateTime)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("종료일시가 시작일시보다 이전일 수 없습니다."); + } +} From fc78bfaf077e9570c13b83a68a924b0cda20f8e1 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Tue, 5 Jul 2022 14:23:35 +0900 Subject: [PATCH 0015/1011] =?UTF-8?q?feat:=20InvalidPeriodException=20?= =?UTF-8?q?=EC=BB=A4=EC=8A=A4=ED=85=80=20=EC=98=88=EC=99=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/schedule/domain/Period.java | 3 ++- .../schedule/exception/InvalidPeriodException.java | 12 ++++++++++++ .../com/allog/dallog/DallogApplicationTests.java | 13 ------------- .../allog/dallog/schedule/domain/PeriodTest.java | 3 ++- 4 files changed, 16 insertions(+), 15 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/schedule/exception/InvalidPeriodException.java delete mode 100644 backend/src/test/java/com/allog/dallog/DallogApplicationTests.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java index 71fd96e5..647e6c30 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java @@ -1,5 +1,6 @@ package com.allog.dallog.schedule.domain; +import com.allog.dallog.schedule.exception.InvalidPeriodException; import java.time.LocalDateTime; public class Period { @@ -16,7 +17,7 @@ public Period(final LocalDateTime startDateTime, final LocalDateTime endDateTime private void validate(final LocalDateTime startDateTime, final LocalDateTime endDateTime) { if (startDateTime.isAfter(endDateTime)) { - throw new IllegalArgumentException("종료일시가 시작일시보다 이전일 수 없습니다."); + throw new InvalidPeriodException("종료일시가 시작일시보다 이전일 수 없습니다."); } } } diff --git a/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidPeriodException.java b/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidPeriodException.java new file mode 100644 index 00000000..7c9d5c9d --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidPeriodException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.schedule.exception; + +public class InvalidPeriodException extends RuntimeException { + + public InvalidPeriodException() { + super("잘못된 기간입니다."); + } + + public InvalidPeriodException(final String message) { + super(message); + } +} diff --git a/backend/src/test/java/com/allog/dallog/DallogApplicationTests.java b/backend/src/test/java/com/allog/dallog/DallogApplicationTests.java deleted file mode 100644 index 06fb7334..00000000 --- a/backend/src/test/java/com/allog/dallog/DallogApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.allog.dallog; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class DallogApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java index e52498b1..46e6d2bf 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java @@ -2,6 +2,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.allog.dallog.schedule.exception.InvalidPeriodException; import java.time.LocalDateTime; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -17,7 +18,7 @@ class PeriodTest { // when & then assertThatThrownBy(() -> new Period(startDateTime, endDateTime)) - .isInstanceOf(IllegalArgumentException.class) + .isInstanceOf(InvalidPeriodException.class) .hasMessage("종료일시가 시작일시보다 이전일 수 없습니다."); } } From 679ca6ba445c4344b65449a86ae10f63365be8e8 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Tue, 5 Jul 2022 14:55:32 +0900 Subject: [PATCH 0016/1011] =?UTF-8?q?feat:=20Schedule=20Entity=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - JPA 설정 추가 --- .../allog/dallog/schedule/domain/Period.java | 9 +++++ .../dallog/schedule/domain/Schedule.java | 38 +++++++++++++++++++ .../src/main/resources/application.properties | 7 +++- .../dallog/schedule/domain/ScheduleTest.java | 22 +++++++++++ 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java create mode 100644 backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java index 647e6c30..d49dda0e 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java @@ -2,12 +2,21 @@ import com.allog.dallog.schedule.exception.InvalidPeriodException; import java.time.LocalDateTime; +import javax.persistence.Column; +import javax.persistence.Embeddable; +@Embeddable public class Period { + @Column(nullable = false) private LocalDateTime startDateTime; + + @Column(nullable = false) private LocalDateTime endDateTime; + protected Period() { + } + public Period(final LocalDateTime startDateTime, final LocalDateTime endDateTime) { validate(startDateTime, endDateTime); diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java new file mode 100644 index 00000000..495f0821 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java @@ -0,0 +1,38 @@ +package com.allog.dallog.schedule.domain; + +import java.time.LocalDateTime; +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "SCHEDULES") +public class Schedule { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long Id; + + @Column(nullable = false) + private String title; + + @Embedded + private Period period; + + @Column(nullable = false) + private String memo; + + protected Schedule() { + } + + public Schedule(final String title, final LocalDateTime startDateTime, + final LocalDateTime endDateTime, final String memo) { + this.title = title; + this.period = new Period(startDateTime, endDateTime); + this.memo = memo; + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 8b137891..2b920888 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1 +1,6 @@ - +spring.datasource.url=jdbc:h2:~/dallog;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE +spring.datasource.username=sa +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=create +logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java new file mode 100644 index 00000000..63a74f80 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java @@ -0,0 +1,22 @@ +package com.allog.dallog.schedule.domain; + +import java.time.LocalDateTime; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class ScheduleTest { + + @DisplayName("일정을 생성한다.") + @Test + void 일정을_생성한다() { + // given + String title = "알록달록 회의"; + LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); + LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); + String memo = "알록달록 팀회의 - 선릉 큰 강의실"; + + // when & then + Assertions.assertDoesNotThrow(() -> new Schedule(title, startDateTime, endDateTime, memo)); + } +} From 8af131105d4679fb788fa92342c094a7eed2f023 Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 5 Jul 2022 15:15:04 +0900 Subject: [PATCH 0017/1011] =?UTF-8?q?feat:=20ScheduleRepository=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - application.properties MYSQL 방언 추가 --- .../allog/dallog/schedule/domain/ScheduleRepository.java | 7 +++++++ backend/src/main/resources/application.properties | 1 + 2 files changed, 8 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/schedule/domain/ScheduleRepository.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/ScheduleRepository.java b/backend/src/main/java/com/allog/dallog/schedule/domain/ScheduleRepository.java new file mode 100644 index 00000000..21426877 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/ScheduleRepository.java @@ -0,0 +1,7 @@ +package com.allog.dallog.schedule.domain; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ScheduleRepository extends JpaRepository { + +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 2b920888..7a91cde7 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -4,3 +4,4 @@ spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect From 030350144c62103f9df3284e15f06f80694e06bc Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 5 Jul 2022 16:33:28 +0900 Subject: [PATCH 0018/1011] =?UTF-8?q?feat:=20ScheduleService=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 일정 저장 기능 구현 --- .../dallog/schedule/domain/Schedule.java | 4 ++ .../dto/request/ScheduleCreateRequest.java | 40 +++++++++++++++++++ .../schedule/service/ScheduleService.java | 24 +++++++++++ .../schedule/service/ScheduleServiceTest.java | 36 +++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java create mode 100644 backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java create mode 100644 backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java index 495f0821..94890fc9 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java @@ -35,4 +35,8 @@ public Schedule(final String title, final LocalDateTime startDateTime, this.period = new Period(startDateTime, endDateTime); this.memo = memo; } + + public Long getId() { + return Id; + } } diff --git a/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java b/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java new file mode 100644 index 00000000..672d13f9 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java @@ -0,0 +1,40 @@ +package com.allog.dallog.schedule.dto.request; + +import com.allog.dallog.schedule.domain.Schedule; +import java.time.LocalDateTime; + +public class ScheduleCreateRequest { + + private String title; + private LocalDateTime startDateTime; + private LocalDateTime endDateTime; + private String memo; + + public ScheduleCreateRequest(final String title, final LocalDateTime startDateTime, + final LocalDateTime endDateTime, final String memo) { + this.title = title; + this.startDateTime = startDateTime; + this.endDateTime = endDateTime; + this.memo = memo; + } + + public Schedule toEntity() { + return new Schedule(title, startDateTime, endDateTime, memo); + } + + public String getTitle() { + return title; + } + + public LocalDateTime getStartDateTime() { + return startDateTime; + } + + public LocalDateTime getEndDateTime() { + return endDateTime; + } + + public String getMemo() { + return memo; + } +} diff --git a/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java b/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java new file mode 100644 index 00000000..409e7338 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java @@ -0,0 +1,24 @@ +package com.allog.dallog.schedule.service; + +import com.allog.dallog.schedule.domain.Schedule; +import com.allog.dallog.schedule.domain.ScheduleRepository; +import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(readOnly = true) +@Service +public class ScheduleService { + + private final ScheduleRepository scheduleRepository; + + public ScheduleService(final ScheduleRepository scheduleRepository) { + this.scheduleRepository = scheduleRepository; + } + + @Transactional + public Long save(final ScheduleCreateRequest request) { + Schedule schedule = scheduleRepository.save(request.toEntity()); + return schedule.getId(); + } +} diff --git a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java new file mode 100644 index 00000000..aa57ae72 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java @@ -0,0 +1,36 @@ +package com.allog.dallog.schedule.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; +import java.time.LocalDateTime; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ScheduleServiceTest { + + @Autowired + private ScheduleService scheduleService; + + @DisplayName("새로운 일정을 생성한다") + @Test + void 새로운_일정을_생성한다() { + // given + String title = "알록달록 회의"; + LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); + LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); + String memo = "알록달록 팀회의 - 선릉 큰 강의실"; + + ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, + startDateTime, endDateTime, memo); + + // when + Long id = scheduleService.save(scheduleCreateRequest); + + // then + assertThat(id).isNotNull(); + } +} From 522be70b9f2c12144891a7f43b6733b3a46ef50e Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Tue, 5 Jul 2022 16:55:26 +0900 Subject: [PATCH 0019/1011] =?UTF-8?q?feat:=20ScheduleController=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ScheduleCreateRequest에 검증 어노테이션 추가 --- .../controller/ScheduleController.java | 28 +++++++++++++++++++ .../dto/request/ScheduleCreateRequest.java | 12 ++++++++ 2 files changed, 40 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java b/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java new file mode 100644 index 00000000..10112edd --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java @@ -0,0 +1,28 @@ +package com.allog.dallog.schedule.controller; + +import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; +import com.allog.dallog.schedule.service.ScheduleService; +import java.net.URI; +import javax.validation.Valid; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequestMapping("/api/schedules") +@RestController +public class ScheduleController { + + private final ScheduleService scheduleService; + + public ScheduleController(ScheduleService scheduleService) { + this.scheduleService = scheduleService; + } + + @PostMapping + public ResponseEntity save(@Valid @RequestBody ScheduleCreateRequest request) { + Long id = scheduleService.save(request); + return ResponseEntity.created(URI.create("/api/schedules/" + id)).build(); + } +} diff --git a/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java b/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java index 672d13f9..a7535e57 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java +++ b/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java @@ -2,14 +2,26 @@ import com.allog.dallog.schedule.domain.Schedule; import java.time.LocalDateTime; +import javax.validation.constraints.NotNull; +import org.springframework.format.annotation.DateTimeFormat; public class ScheduleCreateRequest { + @NotNull private String title; + + @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm") private LocalDateTime startDateTime; + + @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm") private LocalDateTime endDateTime; + + @NotNull private String memo; + private ScheduleCreateRequest() { + } + public ScheduleCreateRequest(final String title, final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String memo) { this.title = title; From 0808fb2547f731d9323aeeac7b66ac0c5c29e4b4 Mon Sep 17 00:00:00 2001 From: devHudi Date: Wed, 6 Jul 2022 13:51:58 +0900 Subject: [PATCH 0020/1011] =?UTF-8?q?test:=20=EC=9B=94=EB=B3=84=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EC=A1=B0=ED=9A=8C=20=EC=9D=B8=EC=88=98?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/acceptance/AcceptanceTest.java | 4 +- .../acceptance/SchedulesAcceptanceTest.java | 61 ++++++++++++++++--- 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java index 16fa347e..437e537c 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java @@ -8,13 +8,13 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) -public class AcceptanceTest { +class AcceptanceTest { @LocalServerPort int port; @BeforeEach - public void setUp() { + void setUp() { RestAssured.port = port; } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java index 377e2b7e..d6d774da 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java @@ -13,27 +13,70 @@ import org.springframework.http.MediaType; @DisplayName("일정 관련 기능") -public class SchedulesAcceptanceTest extends AcceptanceTest { +class SchedulesAcceptanceTest extends AcceptanceTest { @DisplayName("정상적인 일정정보를 등록하면 상태코드 201을 반환한다.") @Test - public void 정상적인_일정정보를_등록하면_상태코드_201을_반환한다() { + void 정상적인_일정정보를_등록하면_상태코드_201을_반환한다() { // given - Map params = new HashMap<>(); - params.put("title", "알록달록 회의"); - params.put("startDateTime", "2022-07-04T13:00"); - params.put("endDateTime", "2022-07-05T07:00"); - params.put("memo", "알록달록 회의가 있어요"); + String title = "알록달록 회의"; + String startDateTime = "2022-07-04T13:00"; + String endDateTime = "2022-07-05T07:00"; + String memo = "알록달록 회의가 있어요"; + + // given & when + ExtractableResponse response = 새로운_일정을_등록한다(title, startDateTime, endDateTime, + memo); + + // then + 상태코드_201이_반환됨(response); + } + + @DisplayName("월별 일정정보를 조회한다.") + @Test + void 월별_일정정보를_조회한다() { + // given + int year = 2022; + int month = 7; + + 새로운_일정을_등록한다("알록달록 회의 1", "2022-07-04T13:00", "2022-07-05T07:00", "알록달록 회의 1이 있어요"); + 새로운_일정을_등록한다("알록달록 회의 2", "2022-08-04T13:00", "2022-08-05T07:00", "알록달록 회의 2이 있어요"); // when - ExtractableResponse response = RestAssured.given().log().all() + ExtractableResponse response = 월별_일정을_조회한다(year, month); + + // then + 상태코드_200이_반환됨(response); + } + + private ExtractableResponse 새로운_일정을_등록한다(final String title, + final String startDateTime, final String endDateTime, final String memo) { + Map params = new HashMap<>(); + params.put("title", title); + params.put("startDateTime", startDateTime); + params.put("endDateTime", endDateTime); + params.put("memo", memo); + + return RestAssured.given().log().all() .contentType(MediaType.APPLICATION_JSON_VALUE) .body(params) .when().post("/api/schedules") .then().log().all() .extract(); + } - // then + private ExtractableResponse 월별_일정을_조회한다(int year, int month) { + return RestAssured.given().log().all() + .when().get("/api/schedules?year={year}&month={month}", year, month) + .then().log().all() + .extract(); + } + + private void 상태코드_200이_반환됨(ExtractableResponse response) { + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); + } + + private void 상태코드_201이_반환됨(ExtractableResponse response) { assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); } } From c3145517c180d8e15268da155e38d68b38135cb9 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 6 Jul 2022 14:09:05 +0900 Subject: [PATCH 0021/1011] =?UTF-8?q?chore:=20eslint=20import/named=20?= =?UTF-8?q?=EA=B7=9C=EC=B9=99=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/.eslintrc.json | 2 ++ frontend/src/components/NavBar/NavBar.stories.tsx | 1 - frontend/src/components/NavBar/NavBar.styles.ts | 1 - .../components/ScheduleAddButton/ScheduleAddButton.stories.tsx | 1 - .../components/ScheduleAddButton/ScheduleAddButton.styles.ts | 1 - 5 files changed, 2 insertions(+), 4 deletions(-) diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index 39f13408..65c6aa7c 100644 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -5,11 +5,13 @@ "plugin:react/recommended", "plugin:import/errors", "plugin:import/warnings", + "plugin:import/recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended" ], "rules": { "react/react-in-jsx-scope": "off", + "import/named": "off", "import/no-unresolved": "off", "@typescript-eslint/no-var-requires": "off" } diff --git a/frontend/src/components/NavBar/NavBar.stories.tsx b/frontend/src/components/NavBar/NavBar.stories.tsx index d7838b64..009def92 100644 --- a/frontend/src/components/NavBar/NavBar.stories.tsx +++ b/frontend/src/components/NavBar/NavBar.stories.tsx @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/named import { ComponentStory, ComponentMeta } from '@storybook/react'; import NavBar from './NavBar'; diff --git a/frontend/src/components/NavBar/NavBar.styles.ts b/frontend/src/components/NavBar/NavBar.styles.ts index 53285626..f6d07d68 100644 --- a/frontend/src/components/NavBar/NavBar.styles.ts +++ b/frontend/src/components/NavBar/NavBar.styles.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/named import { css, Theme } from '@emotion/react'; const navBar = ({ colors }: Theme) => css` diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx index c2f0992b..3bce0acc 100644 --- a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/named import { ComponentStory, ComponentMeta } from '@storybook/react'; import ScheduleAddButton from './ScheduleAddButton'; diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts index 7bb90551..fa230c69 100644 --- a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/named import { css, Theme } from '@emotion/react'; const scheduleAddButton = ({ colors }: Theme) => css` From ef039607fc2cb860733eccdb52babe0656b56258 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 6 Jul 2022 14:11:35 +0900 Subject: [PATCH 0022/1011] =?UTF-8?q?refactor:=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EB=94=94=EB=A0=89=ED=86=A0=EB=A6=AC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/components/@common/{ => Button}/Button.stories.tsx | 1 - frontend/src/components/@common/{ => Button}/Button.styles.ts | 0 frontend/src/components/@common/{ => Button}/Button.tsx | 1 - 3 files changed, 2 deletions(-) rename frontend/src/components/@common/{ => Button}/Button.stories.tsx (90%) rename frontend/src/components/@common/{ => Button}/Button.styles.ts (100%) rename frontend/src/components/@common/{ => Button}/Button.tsx (92%) diff --git a/frontend/src/components/@common/Button.stories.tsx b/frontend/src/components/@common/Button/Button.stories.tsx similarity index 90% rename from frontend/src/components/@common/Button.stories.tsx rename to frontend/src/components/@common/Button/Button.stories.tsx index 3a43e86a..354e6949 100644 --- a/frontend/src/components/@common/Button.stories.tsx +++ b/frontend/src/components/@common/Button/Button.stories.tsx @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/named import { ComponentStory, ComponentMeta } from '@storybook/react'; import Button from './Button'; diff --git a/frontend/src/components/@common/Button.styles.ts b/frontend/src/components/@common/Button/Button.styles.ts similarity index 100% rename from frontend/src/components/@common/Button.styles.ts rename to frontend/src/components/@common/Button/Button.styles.ts diff --git a/frontend/src/components/@common/Button.tsx b/frontend/src/components/@common/Button/Button.tsx similarity index 92% rename from frontend/src/components/@common/Button.tsx rename to frontend/src/components/@common/Button/Button.tsx index 19d22195..9e775d48 100644 --- a/frontend/src/components/@common/Button.tsx +++ b/frontend/src/components/@common/Button/Button.tsx @@ -1,4 +1,3 @@ -// eslint-disable-next-line import/named import { SerializedStyles } from '@emotion/react'; import { button } from './Button.styles'; From 45c1e5540c98d18b95f98fe1b3c6632795713140 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 6 Jul 2022 14:22:28 +0900 Subject: [PATCH 0023/1011] =?UTF-8?q?style:=20theme=20=EC=83=89=EC=83=81?= =?UTF-8?q?=20=EB=B0=8F=20=EA=B3=B5=ED=86=B5=20=EC=8A=A4=ED=83=80=EC=9D=BC?= =?UTF-8?q?=20flex=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/@types/emotion.d.ts | 7 +++- .../src/components/NavBar/NavBar.styles.ts | 2 +- .../ScheduleAddButton.styles.ts | 4 +-- frontend/src/styles/theme.ts | 35 ++++++++++++++++--- 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/frontend/src/@types/emotion.d.ts b/frontend/src/@types/emotion.d.ts index b4f6210a..98b9b120 100644 --- a/frontend/src/@types/emotion.d.ts +++ b/frontend/src/@types/emotion.d.ts @@ -1,11 +1,16 @@ -import '@emotion/react'; +import { SerializedStyles } from '@emotion/react'; interface Colors { [key: string]: string; } +interface Flex { + [key: string]: SerializedStyles; +} + declare module '@emotion/react' { export interface Theme { colors: Colors; + flex: Flex; } } diff --git a/frontend/src/components/NavBar/NavBar.styles.ts b/frontend/src/components/NavBar/NavBar.styles.ts index f6d07d68..90d20423 100644 --- a/frontend/src/components/NavBar/NavBar.styles.ts +++ b/frontend/src/components/NavBar/NavBar.styles.ts @@ -5,7 +5,7 @@ const navBar = ({ colors }: Theme) => css` height: 64px; padding: 8px; - background: ${colors.yellow_500}; + background: ${colors.YELLOW_500}; box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); `; diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts index fa230c69..1b1fa765 100644 --- a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts @@ -6,12 +6,12 @@ const scheduleAddButton = ({ colors }: Theme) => css` border-radius: 50%; - background: ${colors.yellow_500}; + background: ${colors.YELLOW_500}; font-size: 20px; line-height: 20px; font-weight: 700; - color: ${colors.white}; + color: ${colors.WHITE}; &:hover { opacity: 0.7; diff --git a/frontend/src/styles/theme.ts b/frontend/src/styles/theme.ts index 8a595ad5..21f0235e 100644 --- a/frontend/src/styles/theme.ts +++ b/frontend/src/styles/theme.ts @@ -1,14 +1,39 @@ -// eslint-disable-next-line import/named -import { Theme } from '@emotion/react'; +import { css, Theme } from '@emotion/react'; const colors = { - yellow_500: '#FCC419', - white: '#fff', - black: '#000', + YELLOW_500: '#FCC419', + WHITE: '#fff', + GRAY_000: '#f8f9fa', + GRAY_100: '#f1f3f5', + GRAY_200: '#e9ecef', + GRAY_300: '#dee2e6', + GRAY_400: '#ced4da', + GRAY_500: '#adb5bd', + GRAY_600: '#868e96', + GRAY_700: '#495057', + GRAY_800: '#343a40', + GRAY_900: '#212529', + BLACK: '#000', +}; + +const flex = { + row: css` + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + `, + column: css` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + `, }; const theme: Theme = { colors, + flex, }; export default theme; From 6b93c8dfde23ee370832f54280dea3e338263e9a Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 6 Jul 2022 14:23:39 +0900 Subject: [PATCH 0024/1011] =?UTF-8?q?feat:=20=EC=9D=B8=ED=92=8B=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../@common/FieldSet/FieldSet.stories.tsx | 27 ++++++++++++++++++ .../@common/FieldSet/FieldSet.styles.ts | 28 +++++++++++++++++++ .../components/@common/FieldSet/FieldSet.tsx | 18 ++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 frontend/src/components/@common/FieldSet/FieldSet.stories.tsx create mode 100644 frontend/src/components/@common/FieldSet/FieldSet.styles.ts create mode 100644 frontend/src/components/@common/FieldSet/FieldSet.tsx diff --git a/frontend/src/components/@common/FieldSet/FieldSet.stories.tsx b/frontend/src/components/@common/FieldSet/FieldSet.stories.tsx new file mode 100644 index 00000000..195ae60b --- /dev/null +++ b/frontend/src/components/@common/FieldSet/FieldSet.stories.tsx @@ -0,0 +1,27 @@ +import { ComponentStory, ComponentMeta } from '@storybook/react'; + +import FieldSet from './FieldSet'; + +export default { + title: 'Components/@Common/FieldSet', + component: FieldSet, +} as ComponentMeta; + +const Template: ComponentStory = (args) =>
; + +const Primary = Template.bind({}); +Primary.args = { + id: 'primary', + labelText: 'primary', + placeholder: '입력해주세요.', +}; + +const DatePicker = Template.bind({}); +DatePicker.args = { + type: 'datetime-local', + id: 'date-time-picker', + labelText: '일정 시작', + placeholder: '입력해주세요.', +}; + +export { Primary, DatePicker }; diff --git a/frontend/src/components/@common/FieldSet/FieldSet.styles.ts b/frontend/src/components/@common/FieldSet/FieldSet.styles.ts new file mode 100644 index 00000000..60af3ee2 --- /dev/null +++ b/frontend/src/components/@common/FieldSet/FieldSet.styles.ts @@ -0,0 +1,28 @@ +import { css, Theme } from '@emotion/react'; + +const fieldSet = ({ flex }: Theme) => css` + ${flex.column} + + align-items:flex-start; + gap: 10px; + + font-size: 20px; +`; + +const label = css` + padding: 0 4px; +`; + +const input = ({ colors }: Theme) => css` + width: 500px; + height: 60px; + padding: 12px; + + border-radius: 8px; + border: 1px solid ${colors.GRAY_400}; + + font-family: inherit; + font-size: inherit; +`; + +export { fieldSet, label, input }; diff --git a/frontend/src/components/@common/FieldSet/FieldSet.tsx b/frontend/src/components/@common/FieldSet/FieldSet.tsx new file mode 100644 index 00000000..017bc86a --- /dev/null +++ b/frontend/src/components/@common/FieldSet/FieldSet.tsx @@ -0,0 +1,18 @@ +import { fieldSet, input, label } from './FieldSet.styles'; + +interface FieldSetProps extends HTMLInputElement { + labelText?: string; +} + +function FieldSet({ type = 'text', id, labelText, placeholder }: FieldSetProps) { + return ( +
+ + +
+ ); +} + +export default FieldSet; From f8215acb4ebcbd5bb600c21a4a6175b23721e97b Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 6 Jul 2022 15:03:41 +0900 Subject: [PATCH 0025/1011] =?UTF-8?q?feat:=20=EC=8B=9C=EC=9E=91=EC=9D=BC?= =?UTF-8?q?=EC=8B=9C=EC=99=80=20=EC=A2=85=EB=A3=8C=EC=9D=BC=EC=8B=9C=20?= =?UTF-8?q?=EC=82=AC=EC=9D=B4=EC=97=90=20=ED=95=B4=EB=8B=B9=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=9D=BC=EC=A0=95=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../schedule/domain/ScheduleRepository.java | 7 ++++ .../src/main/resources/application.properties | 1 - .../domain/ScheduleRepositoryTest.java | 39 +++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/ScheduleRepository.java b/backend/src/main/java/com/allog/dallog/schedule/domain/ScheduleRepository.java index 21426877..6bd3472e 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/ScheduleRepository.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/ScheduleRepository.java @@ -1,7 +1,14 @@ package com.allog.dallog.schedule.domain; +import java.time.LocalDateTime; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; public interface ScheduleRepository extends JpaRepository { + @Query("SELECT s " + + "FROM Schedule s " + + "WHERE s.period.startDateTime <= :endDate AND s.period.endDateTime >= :startDate") + List findByBetween(final LocalDateTime startDate, final LocalDateTime endDate); } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 7a91cde7..2b920888 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -4,4 +4,3 @@ spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE -spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java new file mode 100644 index 00000000..e19339f8 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java @@ -0,0 +1,39 @@ +package com.allog.dallog.schedule.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.time.LocalDateTime; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +@DataJpaTest +class ScheduleRepositoryTest { + + @Autowired + private ScheduleRepository scheduleRepository; + + @DisplayName("시작일시와 종료일시를 전달하면 그 사이에 해당하는 일정을 조회한다.") + @Test + void 시작일시와_종료일시를_전달하면_그_사이에_해당하는_일정을_조회한다() { + // given + Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 7, 15, 14, 20), + LocalDateTime.of(2022, 7, 15, 16, 20), "달록"); + Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), + LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + + scheduleRepository.save(schedule1); + scheduleRepository.save(schedule2); + + LocalDateTime startDate = LocalDateTime.of(2022, 7, 1, 0, 0); + LocalDateTime endDate = LocalDateTime.of(2022, 7, 31, 0, 0); + + // when + List schedules = scheduleRepository.findByBetween(startDate, endDate); + + // then + assertThat(schedules).hasSize(1); + } +} From a133d4403fac1df7ecf32302211e34d1d1a4ae30 Mon Sep 17 00:00:00 2001 From: devHudi Date: Wed, 6 Jul 2022 16:05:35 +0900 Subject: [PATCH 0026/1011] =?UTF-8?q?feat:=20=EC=97=B0=EB=8F=84=EC=99=80?= =?UTF-8?q?=20=EC=9B=94=EC=97=90=20=ED=95=B4=EB=8B=B9=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EB=AA=A9=EB=A1=9D=EC=9D=84=20=EA=B0=80?= =?UTF-8?q?=EC=A0=B8=EC=98=A4=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 인수 테스트, 레포지토리 테스트, 서비스 테스트 작성 - Period, Schedule getter 추가 --- .../allog/dallog/schedule/domain/Period.java | 8 ++++ .../dallog/schedule/domain/Schedule.java | 16 +++++++ .../dto/response/ScheduleResponse.java | 47 +++++++++++++++++++ .../schedule/service/ScheduleService.java | 19 ++++++++ .../acceptance/SchedulesAcceptanceTest.java | 10 ++-- .../schedule/service/ScheduleServiceTest.java | 29 +++++++++++- 6 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/schedule/dto/response/ScheduleResponse.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java index d49dda0e..74ff349e 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java @@ -29,4 +29,12 @@ private void validate(final LocalDateTime startDateTime, final LocalDateTime end throw new InvalidPeriodException("종료일시가 시작일시보다 이전일 수 없습니다."); } } + + public LocalDateTime getStartDateTime() { + return startDateTime; + } + + public LocalDateTime getEndDateTime() { + return endDateTime; + } } diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java index 94890fc9..9a5d8131 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java @@ -39,4 +39,20 @@ public Schedule(final String title, final LocalDateTime startDateTime, public Long getId() { return Id; } + + public String getTitle() { + return title; + } + + public LocalDateTime getStartDateTime() { + return period.getStartDateTime(); + } + + public LocalDateTime getEndDateTime() { + return period.getEndDateTime(); + } + + public String getMemo() { + return memo; + } } diff --git a/backend/src/main/java/com/allog/dallog/schedule/dto/response/ScheduleResponse.java b/backend/src/main/java/com/allog/dallog/schedule/dto/response/ScheduleResponse.java new file mode 100644 index 00000000..8410afb1 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/schedule/dto/response/ScheduleResponse.java @@ -0,0 +1,47 @@ +package com.allog.dallog.schedule.dto.response; + +import com.allog.dallog.schedule.domain.Schedule; +import java.time.LocalDateTime; + +public class ScheduleResponse { + + private final Long id; + private final String title; + private final LocalDateTime startDateTime; + private final LocalDateTime endDateTime; + private final String memo; + + public ScheduleResponse(final Schedule schedule) { + this(schedule.getId(), schedule.getTitle(), schedule.getStartDateTime(), + schedule.getEndDateTime(), schedule.getMemo()); + } + + public ScheduleResponse(final Long id, final String title, final LocalDateTime startDateTime, + final LocalDateTime endDateTime, final String memo) { + this.id = id; + this.title = title; + this.startDateTime = startDateTime; + this.endDateTime = endDateTime; + this.memo = memo; + } + + public Long getId() { + return id; + } + + public String getTitle() { + return title; + } + + public LocalDateTime getStartDateTime() { + return startDateTime; + } + + public LocalDateTime getEndDateTime() { + return endDateTime; + } + + public String getMemo() { + return memo; + } +} diff --git a/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java b/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java index 409e7338..cfee72d6 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java +++ b/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java @@ -3,6 +3,12 @@ import com.allog.dallog.schedule.domain.Schedule; import com.allog.dallog.schedule.domain.ScheduleRepository; import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; +import com.allog.dallog.schedule.dto.response.ScheduleResponse; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.List; +import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,4 +27,17 @@ public Long save(final ScheduleCreateRequest request) { Schedule schedule = scheduleRepository.save(request.toEntity()); return schedule.getId(); } + + public List findByYearAndMonth(int year, int month) { + LocalDate startDate = LocalDate.of(year, month, 1); + LocalDate endDate = startDate.plusDays(startDate.lengthOfMonth()); + + List schedules = scheduleRepository.findByBetween( + LocalDateTime.of(startDate, LocalTime.MIN), + LocalDateTime.of(endDate, LocalTime.MIN)); + + return schedules.stream() + .map(ScheduleResponse::new) + .collect(Collectors.toList()); + } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java index d6d774da..3b8aaf1d 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java @@ -29,7 +29,7 @@ class SchedulesAcceptanceTest extends AcceptanceTest { memo); // then - 상태코드_201이_반환됨(response); + 상태코드_201이_반환된다(response); } @DisplayName("월별 일정정보를 조회한다.") @@ -46,7 +46,7 @@ class SchedulesAcceptanceTest extends AcceptanceTest { ExtractableResponse response = 월별_일정을_조회한다(year, month); // then - 상태코드_200이_반환됨(response); + 상태코드_200이_반환된다(response); } private ExtractableResponse 새로운_일정을_등록한다(final String title, @@ -65,18 +65,18 @@ class SchedulesAcceptanceTest extends AcceptanceTest { .extract(); } - private ExtractableResponse 월별_일정을_조회한다(int year, int month) { + private ExtractableResponse 월별_일정을_조회한다(final int year, final int month) { return RestAssured.given().log().all() .when().get("/api/schedules?year={year}&month={month}", year, month) .then().log().all() .extract(); } - private void 상태코드_200이_반환됨(ExtractableResponse response) { + private void 상태코드_200이_반환된다(ExtractableResponse response) { assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); } - private void 상태코드_201이_반환됨(ExtractableResponse response) { + private void 상태코드_201이_반환된다(ExtractableResponse response) { assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); } } diff --git a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java index aa57ae72..999ede41 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java @@ -3,7 +3,9 @@ import static org.assertj.core.api.Assertions.assertThat; import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; +import com.allog.dallog.schedule.dto.response.ScheduleResponse; import java.time.LocalDateTime; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -15,7 +17,7 @@ class ScheduleServiceTest { @Autowired private ScheduleService scheduleService; - @DisplayName("새로운 일정을 생성한다") + @DisplayName("새로운 일정을 생성한다.") @Test void 새로운_일정을_생성한다() { // given @@ -33,4 +35,29 @@ class ScheduleServiceTest { // then assertThat(id).isNotNull(); } + + @DisplayName("연도와 월을 전달받아 해당 월에 해당하는 일정 목록을 가져온다.") + @Test + void 연도와_월을_전달받아_해당_월에_해당하는_일정_목록을_가져온다() { + // given + ScheduleCreateRequest scheduleCreateRequest1 = new ScheduleCreateRequest("알록달록 회의 1", + LocalDateTime.of(2022, 7, 5, 12, 30), LocalDateTime.of(2022, 7, 6, 14, 30), + "알록달록 팀회의 - 선릉 큰 강의실"); + + ScheduleCreateRequest scheduleCreateRequest2 = new ScheduleCreateRequest("알록달록 회의 2", + LocalDateTime.of(2022, 8, 5, 12, 30), LocalDateTime.of(2022, 8, 6, 14, 30), + "알록달록 팀회의 - 잠실 큰 강의실"); + + scheduleService.save(scheduleCreateRequest1); + scheduleService.save(scheduleCreateRequest2); + + int year = 2022; + int month = 7; + + // when + List schedules = scheduleService.findByYearAndMonth(year, month); + + // then + assertThat(schedules).hasSize(1); + } } From dfaab3adfce9d976daa2282b1981c8809f735c84 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 6 Jul 2022 16:40:33 +0900 Subject: [PATCH 0027/1011] =?UTF-8?q?refactor:=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20css?= =?UTF-8?q?=20prop=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B0=8F=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/components/@common/Button/Button.styles.ts | 4 ++++ frontend/src/components/@common/Button/Button.tsx | 6 +++--- .../ScheduleAddButton/ScheduleAddButton.styles.ts | 5 ----- .../src/components/ScheduleAddButton/ScheduleAddButton.tsx | 5 ++--- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/@common/Button/Button.styles.ts b/frontend/src/components/@common/Button/Button.styles.ts index 53a58b1c..89c98654 100644 --- a/frontend/src/components/@common/Button/Button.styles.ts +++ b/frontend/src/components/@common/Button/Button.styles.ts @@ -7,6 +7,10 @@ const button = css` text-align: center; cursor: pointer; + + &:hover { + opacity: 0.7; + } `; export { button }; diff --git a/frontend/src/components/@common/Button/Button.tsx b/frontend/src/components/@common/Button/Button.tsx index 9e775d48..d61a7cdc 100644 --- a/frontend/src/components/@common/Button/Button.tsx +++ b/frontend/src/components/@common/Button/Button.tsx @@ -4,14 +4,14 @@ import { button } from './Button.styles'; interface ButtonProps { type?: 'button' | 'submit' | 'reset'; - css?: SerializedStyles; + cssProp?: SerializedStyles; onClick?: () => void; children?: string | JSX.Element | JSX.Element[]; } -function Button({ type = 'button', css, onClick, children, ...props }: ButtonProps) { +function Button({ type = 'button', cssProp, onClick, children, ...props }: ButtonProps) { return ( - ); diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts index 1b1fa765..069c5c61 100644 --- a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts @@ -3,7 +3,6 @@ import { css, Theme } from '@emotion/react'; const scheduleAddButton = ({ colors }: Theme) => css` width: 36px; height: 36px; - border-radius: 50%; background: ${colors.YELLOW_500}; @@ -12,10 +11,6 @@ const scheduleAddButton = ({ colors }: Theme) => css` line-height: 20px; font-weight: 700; color: ${colors.WHITE}; - - &:hover { - opacity: 0.7; - } `; export { scheduleAddButton }; diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx index 79152a53..4a2f25c9 100644 --- a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx @@ -1,14 +1,13 @@ -/* eslint-disable import/named */ import { useTheme } from '@emotion/react'; import { scheduleAddButton } from './ScheduleAddButton.styles'; -import Button from '../@common/Button'; +import Button from '../@common/Button/Button'; function ScheduleAddButton() { const theme = useTheme(); - return ; + return ; } export default ScheduleAddButton; From 8d2ad5e3d38b6e8916e220548418519bd871f3e1 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 6 Jul 2022 16:42:35 +0900 Subject: [PATCH 0028/1011] =?UTF-8?q?feat:=20=EC=9E=85=EB=A0=A5=EC=B0=BD?= =?UTF-8?q?=20props=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../@common/FieldSet/FieldSet.styles.ts | 9 +++++--- .../components/@common/FieldSet/FieldSet.tsx | 22 +++++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/@common/FieldSet/FieldSet.styles.ts b/frontend/src/components/@common/FieldSet/FieldSet.styles.ts index 60af3ee2..e34317ca 100644 --- a/frontend/src/components/@common/FieldSet/FieldSet.styles.ts +++ b/frontend/src/components/@common/FieldSet/FieldSet.styles.ts @@ -3,7 +3,10 @@ import { css, Theme } from '@emotion/react'; const fieldSet = ({ flex }: Theme) => css` ${flex.column} - align-items:flex-start; + width: 500px; + height: 60px; + + align-items: flex-start; gap: 10px; font-size: 20px; @@ -14,10 +17,10 @@ const label = css` `; const input = ({ colors }: Theme) => css` - width: 500px; - height: 60px; padding: 12px; + width: 100%; + border-radius: 8px; border: 1px solid ${colors.GRAY_400}; diff --git a/frontend/src/components/@common/FieldSet/FieldSet.tsx b/frontend/src/components/@common/FieldSet/FieldSet.tsx index 017bc86a..a520a90b 100644 --- a/frontend/src/components/@common/FieldSet/FieldSet.tsx +++ b/frontend/src/components/@common/FieldSet/FieldSet.tsx @@ -1,16 +1,24 @@ +import { SerializedStyles, useTheme } from '@emotion/react'; + import { fieldSet, input, label } from './FieldSet.styles'; -interface FieldSetProps extends HTMLInputElement { +interface FieldSetProps extends React.HTMLAttributes { + type?: string; + cssProp?: SerializedStyles; labelText?: string; } -function FieldSet({ type = 'text', id, labelText, placeholder }: FieldSetProps) { +function FieldSet({ type = 'text', id, cssProp, labelText, placeholder }: FieldSetProps) { + const theme = useTheme(); + return ( -
- - +
+ {labelText && ( + + )} +
); } From 5d0ea25f66dd4f8deda0f24ee62a634bb66b454c Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 6 Jul 2022 16:45:42 +0900 Subject: [PATCH 0029/1011] =?UTF-8?q?feat:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=AA=A8=EB=8B=AC=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../ScheduleAddModal.stories.tsx | 12 +++ .../ScheduleAddModal.styles.ts | 85 +++++++++++++++++++ .../ScheduleAddModal/ScheduleAddModal.tsx | 42 +++++++++ 3 files changed, 139 insertions(+) create mode 100644 frontend/src/components/ScheduleAddModal/ScheduleAddModal.stories.tsx create mode 100644 frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts create mode 100644 frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.stories.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.stories.tsx new file mode 100644 index 00000000..65f07645 --- /dev/null +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.stories.tsx @@ -0,0 +1,12 @@ +import { ComponentStory, ComponentMeta } from '@storybook/react'; + +import ScheduleAddModal from './ScheduleAddModal'; + +export default { + title: 'Components/ScheduleAddModal', + component: ScheduleAddModal, +} as ComponentMeta; + +const Template: ComponentStory = () => ; + +export const Primary = Template.bind({}); diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts new file mode 100644 index 00000000..52ead346 --- /dev/null +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts @@ -0,0 +1,85 @@ +import { css, Theme } from '@emotion/react'; + +const scheduleAddModal = ({ colors }: Theme) => css` + width: 600px; + height: 600px; + padding: 50px; + border-radius: 12px; + + background: ${colors.WHITE}; +`; + +const form = ({ flex }: Theme) => css` + ${flex.column}; + + height: 100%; + justify-content: space-between; +`; + +const allDayButton = ({ colors }: Theme) => css` + width: 500px; + height: 36px; + border: 1px solid ${colors.GRAY_500}; + border-radius: 8px; + filter: drop-shadow(0px 2px 2px ${colors.GRAY_400}); + + background: ${colors.WHITE}; + + font-size: 20px; + color: ${colors.GRAY_600}; +`; + +const dateTime = ({ flex }: Theme) => css` + ${flex.column} + + gap: 10px; +`; + +const arrow = ({ colors }: Theme) => css` + font-size: 24px; + font-weight: bold; + color: ${colors.GRAY_500}; +`; + +const controlButtons = ({ flex }: Theme) => css` + ${flex.row} + + align-self: flex-end; + gap: 20px; +`; + +const cancelButton = ({ colors }: Theme) => css` + width: 90px; + height: 40px; + border: 2px solid ${colors.GRAY_500}; + border-radius: 8px; + filter: drop-shadow(0px 2px 2px ${colors.GRAY_400}); + + background: ${colors.WHITE}; + + font-size: 20px; + color: ${colors.GRAY_600}; +`; + +const saveButton = ({ colors }: Theme) => css` + width: 90px; + height: 40px; + border-radius: 8px; + filter: drop-shadow(0px 2px 2px ${colors.GRAY_400}); + + background: ${colors.YELLOW_500}; + + font-size: 20px; + color: ${colors.WHITE}; +`; + +export { + allDayButton, + arrow, + cancelButton, + controlButtons, + dateTime, + form, + saveButton, + scheduleAddModal, +}; diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx new file mode 100644 index 00000000..136c53a7 --- /dev/null +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -0,0 +1,42 @@ +import { useTheme } from '@emotion/react'; + +import { + allDayButton, + arrow, + cancelButton, + controlButtons, + dateTime, + form, + saveButton, + scheduleAddModal, +} from './ScheduleAddModal.styles'; + +import Button from '../@common/Button/Button'; +import FieldSet from '../@common/FieldSet/FieldSet'; + +function ScheduleAddModal() { + const theme = useTheme(); + + return ( +
+
+
+ +
+
+

+
+
+
+
+ + +
+ +
+ ); +} + +export default ScheduleAddModal; From 49110c9a7a015d83f090424d6cc00a1071a69de0 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 6 Jul 2022 16:50:45 +0900 Subject: [PATCH 0030/1011] =?UTF-8?q?feat:=20findByYearAndMonth=20controll?= =?UTF-8?q?er=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ListResponse 구현 - 누락된 final 키워드 추가 --- .../allog/dallog/global/dto/ListResponse.java | 19 +++++++++++++++++++ .../controller/ScheduleController.java | 16 ++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/global/dto/ListResponse.java diff --git a/backend/src/main/java/com/allog/dallog/global/dto/ListResponse.java b/backend/src/main/java/com/allog/dallog/global/dto/ListResponse.java new file mode 100644 index 00000000..fb53fe7c --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/global/dto/ListResponse.java @@ -0,0 +1,19 @@ +package com.allog.dallog.global.dto; + +import java.util.List; + +public class ListResponse { + + private List data; + + private ListResponse() { + } + + public ListResponse(List data) { + this.data = data; + } + + public List getData() { + return data; + } +} diff --git a/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java b/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java index 10112edd..fd38c5e2 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java +++ b/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java @@ -1,13 +1,18 @@ package com.allog.dallog.schedule.controller; +import com.allog.dallog.global.dto.ListResponse; import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; +import com.allog.dallog.schedule.dto.response.ScheduleResponse; import com.allog.dallog.schedule.service.ScheduleService; import java.net.URI; +import java.util.List; import javax.validation.Valid; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/api/schedules") @@ -16,13 +21,20 @@ public class ScheduleController { private final ScheduleService scheduleService; - public ScheduleController(ScheduleService scheduleService) { + public ScheduleController(final ScheduleService scheduleService) { this.scheduleService = scheduleService; } @PostMapping - public ResponseEntity save(@Valid @RequestBody ScheduleCreateRequest request) { + public ResponseEntity save(@Valid @RequestBody final ScheduleCreateRequest request) { Long id = scheduleService.save(request); return ResponseEntity.created(URI.create("/api/schedules/" + id)).build(); } + + @GetMapping + public ResponseEntity> findByYearAndMonth( + @RequestParam final int year, @RequestParam final int month) { + List responses = scheduleService.findByYearAndMonth(year, month); + return ResponseEntity.ok(new ListResponse<>(responses)); + } } From 0d48c7b9fc477027c944418924228a8bcdba0d41 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 6 Jul 2022 19:21:26 +0900 Subject: [PATCH 0031/1011] =?UTF-8?q?feat:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B2=84=ED=8A=BC=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=B0=94=EC=9D=B8=EB=94=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/components/@common/Button/Button.tsx | 4 ++-- .../ScheduleAddButton/ScheduleAddButton.stories.tsx | 7 ++++++- .../ScheduleAddButton/ScheduleAddButton.styles.ts | 12 ++++++++---- .../ScheduleAddButton/ScheduleAddButton.tsx | 12 ++++++++++-- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/@common/Button/Button.tsx b/frontend/src/components/@common/Button/Button.tsx index d61a7cdc..82b1de48 100644 --- a/frontend/src/components/@common/Button/Button.tsx +++ b/frontend/src/components/@common/Button/Button.tsx @@ -5,13 +5,13 @@ import { button } from './Button.styles'; interface ButtonProps { type?: 'button' | 'submit' | 'reset'; cssProp?: SerializedStyles; - onClick?: () => void; + onClick?: (e?: React.FormEvent) => void; children?: string | JSX.Element | JSX.Element[]; } function Button({ type = 'button', cssProp, onClick, children, ...props }: ButtonProps) { return ( - ); diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx index 3bce0acc..04be8ab0 100644 --- a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx @@ -7,6 +7,11 @@ export default { component: ScheduleAddButton, } as ComponentMeta; -const Template: ComponentStory = () => ; +const Template: ComponentStory = (args) => ( + +); export const Primary = Template.bind({}); +Primary.args = { + onClick: () => void 0, +}; diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts index 069c5c61..f2a5838c 100644 --- a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts @@ -1,14 +1,18 @@ import { css, Theme } from '@emotion/react'; const scheduleAddButton = ({ colors }: Theme) => css` - width: 36px; - height: 36px; + position: fixed; + right: 52px; + bottom: 52px; + + width: 44px; + height: 44px; border-radius: 50%; background: ${colors.YELLOW_500}; - font-size: 20px; - line-height: 20px; + font-size: 28px; + line-height: 44px; font-weight: 700; color: ${colors.WHITE}; `; diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx index 4a2f25c9..fb1722fe 100644 --- a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx @@ -4,10 +4,18 @@ import { scheduleAddButton } from './ScheduleAddButton.styles'; import Button from '../@common/Button/Button'; -function ScheduleAddButton() { +interface ScheduleAddButtonProps { + onClick: () => void; +} + +function ScheduleAddButton({ onClick }: ScheduleAddButtonProps) { const theme = useTheme(); - return ; + return ( + + ); } export default ScheduleAddButton; From 6b289a661e5077670c1cbc8fbb425ff9190b76cc Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 6 Jul 2022 19:28:41 +0900 Subject: [PATCH 0032/1011] =?UTF-8?q?feat:=20=EB=AA=A8=EB=8B=AC=ED=8F=AC?= =?UTF-8?q?=ED=83=88=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=EC=9D=BC=EC=A0=95?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EB=AA=A8=EB=8B=AC=ED=8F=AC=ED=83=88=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../@common/ModalPortal/ModalPortal.styles.ts | 17 ++++++++++ .../@common/ModalPortal/ModalPortal.tsx | 31 +++++++++++++++++++ .../ScheduleAddModal.stories.tsx | 2 +- .../ScheduleAddModal/ScheduleAddModal.tsx | 18 ++++++++--- frontend/src/hooks/useModal.ts | 17 ++++++++++ frontend/src/index.html | 1 + 6 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 frontend/src/components/@common/ModalPortal/ModalPortal.styles.ts create mode 100644 frontend/src/components/@common/ModalPortal/ModalPortal.tsx create mode 100644 frontend/src/hooks/useModal.ts diff --git a/frontend/src/components/@common/ModalPortal/ModalPortal.styles.ts b/frontend/src/components/@common/ModalPortal/ModalPortal.styles.ts new file mode 100644 index 00000000..ba2765d7 --- /dev/null +++ b/frontend/src/components/@common/ModalPortal/ModalPortal.styles.ts @@ -0,0 +1,17 @@ +import { css, Theme } from '@emotion/react'; + +const dimmer = ({ colors, flex }: Theme, isOpen: boolean) => css` + ${flex.row}; + + position: fixed; + top: 0; + left: 0; + + width: 100%; + height: 100%; + + background: ${isOpen ? colors.GRAY_900 : 'transparent'}; + opacity: 0.9; +`; + +export { dimmer }; diff --git a/frontend/src/components/@common/ModalPortal/ModalPortal.tsx b/frontend/src/components/@common/ModalPortal/ModalPortal.tsx new file mode 100644 index 00000000..171f569f --- /dev/null +++ b/frontend/src/components/@common/ModalPortal/ModalPortal.tsx @@ -0,0 +1,31 @@ +import ReactDOM from 'react-dom'; + +import { useTheme } from '@emotion/react'; + +import { dimmer } from './ModalPortal.styles'; + +interface ModalPortalProps { + isOpen: boolean; + closeModal: () => void; + children: JSX.Element | JSX.Element[]; +} + +function ModalPortal({ isOpen, closeModal, children }: ModalPortalProps) { + const modalElement = document.getElementById('modal'); + + const theme = useTheme(); + + if (!(modalElement instanceof HTMLElement)) { + return <>; + } + + const element = isOpen && ( +
+ {children} +
+ ); + + return ReactDOM.createPortal(element, modalElement); +} + +export default ModalPortal; diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.stories.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.stories.tsx index 65f07645..ae4eca84 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.stories.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.stories.tsx @@ -7,6 +7,6 @@ export default { component: ScheduleAddModal, } as ComponentMeta; -const Template: ComponentStory = () => ; +const Template: ComponentStory = (args) => ; export const Primary = Template.bind({}); diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index 136c53a7..f59625a0 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -14,11 +14,19 @@ import { import Button from '../@common/Button/Button'; import FieldSet from '../@common/FieldSet/FieldSet'; -function ScheduleAddModal() { +interface ScheduleAddModalProps { + closeModal: () => void; +} + +function ScheduleAddModal({ closeModal }: ScheduleAddModalProps) { const theme = useTheme(); + const handleClickScheduleAddModal = (e: React.MouseEvent) => { + e.stopPropagation(); + }; + return ( -
+
@@ -29,8 +37,10 @@ function ScheduleAddModal() {
- - +
diff --git a/frontend/src/hooks/useModal.ts b/frontend/src/hooks/useModal.ts new file mode 100644 index 00000000..bfeb8522 --- /dev/null +++ b/frontend/src/hooks/useModal.ts @@ -0,0 +1,17 @@ +import { useState } from 'react'; + +function useModal(initialState = false) { + const [isOpen, setOpen] = useState(initialState); + + const openModal = () => { + setOpen(true); + }; + + const closeModal = () => { + setOpen(false); + }; + + return { isOpen, openModal, closeModal }; +} + +export default useModal; diff --git a/frontend/src/index.html b/frontend/src/index.html index 020ed219..8d3f0eba 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -7,5 +7,6 @@
+ From 0e17d0a06811a45de77bac38b46d93b2c72fe868 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 6 Jul 2022 19:31:14 +0900 Subject: [PATCH 0033/1011] =?UTF-8?q?chore:=20package.json=20prestart=20sc?= =?UTF-8?q?ripts=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index b2aaad66..050e104a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,7 +6,7 @@ "scripts": { "dev": "webpack serve --mode development --open --hot", "build": "webpack --mode production", - "prestart": "npm build", + "prestart": "npm run build", "start": "webpack --mode development", "storybook": "start-storybook -p 6006", "build-storybook": "build-storybook" From 67b4728b45f29b5fd725bfeb27ec786e1397a749 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Thu, 7 Jul 2022 11:54:07 +0900 Subject: [PATCH 0034/1011] =?UTF-8?q?docs:=20Issue=20=EB=B0=8F=20PR=20?= =?UTF-8?q?=ED=85=9C=ED=94=8C=EB=A6=BF=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/ISSUE_TEMPLATE/bug-template.md | 3 +-- .github/ISSUE_TEMPLATE/feature-template.md | 3 +-- .github/PULL_REQUEST_TEMPLATE.md | 3 ++- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-template.md b/.github/ISSUE_TEMPLATE/bug-template.md index 0c0d4d81..baf919c0 100644 --- a/.github/ISSUE_TEMPLATE/bug-template.md +++ b/.github/ISSUE_TEMPLATE/bug-template.md @@ -1,7 +1,7 @@ --- name: Bug Template about: 버그를 이슈에 등록한다. -title: "" +title: '이슈의 제목을 입력해주세요!' labels: '' assignees: '' --- @@ -16,4 +16,3 @@ assignees: '' ## 📸 스크린샷 ## 👄 참고 사항 - diff --git a/.github/ISSUE_TEMPLATE/feature-template.md b/.github/ISSUE_TEMPLATE/feature-template.md index 752e91d4..b34d74cb 100644 --- a/.github/ISSUE_TEMPLATE/feature-template.md +++ b/.github/ISSUE_TEMPLATE/feature-template.md @@ -1,7 +1,7 @@ --- name: Feature Template about: 구현할 기능을 이슈에 등록한다. -title: "" +title: '이슈의 제목을 입력해주세요!' labels: '' assignees: '' --- @@ -17,4 +17,3 @@ assignees: '' ## 📄 참고 사항 ## ⏰ 예상 소요 기간 - diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3af222a0..e5f724db 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,8 +1,10 @@ +- [ ] 🔀 PR 제목의 형식을 잘 작성했나요? e.g. `[feat] PR을 등록한다.` - [ ] 💯 테스트는 잘 통과했나요? - [ ] 🏗️ 빌드는 성공했나요? - [ ] 🧹 불필요한 코드는 제거했나요? - [ ] 💭 이슈는 등록했나요? - [ ] 🏷️ 라벨은 등록했나요? +- [ ] 💻 git rebase를 사용했나요? - [ ] 🌈 알록달록한가요? ## 작업 내용 @@ -12,4 +14,3 @@ ## 주의사항 Closes #{이슈 번호} - From 414bb8108a47593f61cc042d04f66edc830881a2 Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 7 Jul 2022 11:47:56 +0900 Subject: [PATCH 0035/1011] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=A0=ED=8A=B8?= =?UTF-8?q?=EC=97=94=EB=93=9C=20CI=20Github=20Actions=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A6=BD=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/frontend-ci.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/frontend-ci.yml diff --git a/.github/workflows/frontend-ci.yml b/.github/workflows/frontend-ci.yml new file mode 100644 index 00000000..9df105ff --- /dev/null +++ b/.github/workflows/frontend-ci.yml @@ -0,0 +1,28 @@ +name: CI + +on: + pull_request: + branches: + - main + - develop + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: "14" + + - name: Install node packages + run: npm install + + - name: Check lint + run: npm run check:lint + + - name: Check prettier + run: npm run check:prettier + + - name: Build + run: npm run build From 8371156391138cbf708a2faf1e701c72931f6363 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Thu, 7 Jul 2022 12:16:15 +0900 Subject: [PATCH 0036/1011] =?UTF-8?q?feat:=20backend=20=EB=B0=8F=20fronten?= =?UTF-8?q?d=20=EB=B9=8C=EB=93=9C=20=EC=9E=90=EB=8F=99=ED=99=94=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-ci.yml | 33 +++++++++++++++++++++++++++++++ .github/workflows/frontend-ci.yml | 10 +++++++--- frontend/package.json | 4 +++- 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/backend-ci.yml diff --git a/.github/workflows/backend-ci.yml b/.github/workflows/backend-ci.yml new file mode 100644 index 00000000..ec5a0b03 --- /dev/null +++ b/.github/workflows/backend-ci.yml @@ -0,0 +1,33 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Backend CI + +on: + pull_request: + branches: + - main + - develop + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./backend + + steps: + - uses: actions/checkout@v3 + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'adopt' + - name: Validate Gradle wrapper + uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b + - name: Build with Gradle + uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 + with: + arguments: build diff --git a/.github/workflows/frontend-ci.yml b/.github/workflows/frontend-ci.yml index 9df105ff..4eb12219 100644 --- a/.github/workflows/frontend-ci.yml +++ b/.github/workflows/frontend-ci.yml @@ -1,4 +1,4 @@ -name: CI +name: Frontend CI on: pull_request: @@ -9,6 +9,10 @@ on: jobs: build: runs-on: ubuntu-latest + defaults: + run: + working-directory: ./frontend + steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 @@ -19,10 +23,10 @@ jobs: run: npm install - name: Check lint - run: npm run check:lint + run: npm run check-lint - name: Check prettier - run: npm run check:prettier + run: npm run check-prettier - name: Build run: npm run build diff --git a/frontend/package.json b/frontend/package.json index 050e104a..45d00a3d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,7 +9,9 @@ "prestart": "npm run build", "start": "webpack --mode development", "storybook": "start-storybook -p 6006", - "build-storybook": "build-storybook" + "build-storybook": "build-storybook", + "check-lint": "eslint . --ext .js,.jsx,.ts,.tsx", + "check-prettier": "prettier -c ." }, "dependencies": { "@emotion/react": "^11.9.3", From e3f1806c113ac64e3a4c26ef1b6911d5f144373c Mon Sep 17 00:00:00 2001 From: hyeonic Date: Thu, 7 Jul 2022 12:33:56 +0900 Subject: [PATCH 0037/1011] =?UTF-8?q?feat:=20backend=20ci=20=EC=9D=B4?= =?UTF-8?q?=EB=B2=A4=ED=8A=B8=20=EA=B4=80=EB=A0=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/backend-ci.yml | 33 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/.github/workflows/backend-ci.yml b/.github/workflows/backend-ci.yml index ec5a0b03..6809bd39 100644 --- a/.github/workflows/backend-ci.yml +++ b/.github/workflows/backend-ci.yml @@ -1,8 +1,3 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - name: Backend CI on: @@ -14,20 +9,24 @@ on: jobs: build: runs-on: ubuntu-latest + defaults: run: working-directory: ./backend steps: - - uses: actions/checkout@v3 - - name: Set up JDK 11 - uses: actions/setup-java@v3 - with: - java-version: '11' - distribution: 'adopt' - - name: Validate Gradle wrapper - uses: gradle/wrapper-validation-action@e6e38bacfdf1a337459f332974bb2327a31aaf4b - - name: Build with Gradle - uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1 - with: - arguments: build + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + cache: gradle + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build with Gradle + run: ./gradlew build From 4e7f3b532f0d01152a0770098b20d6a4b37fb1a9 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 6 Jul 2022 22:20:04 +0900 Subject: [PATCH 0038/1011] =?UTF-8?q?feat:=20msw=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EC=9A=94=EC=B2=AD=20=EB=AA=A8=ED=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/package.json | 4 + frontend/public/mockServiceWorker.js | 367 +++++++++++++++++++++++++++ frontend/src/index.tsx | 6 + frontend/src/mocks/browser.ts | 4 + frontend/src/mocks/handlers.ts | 20 ++ frontend/yarn.lock | 353 +++++++++++++++++++++++++- 6 files changed, 744 insertions(+), 10 deletions(-) create mode 100644 frontend/public/mockServiceWorker.js create mode 100644 frontend/src/mocks/browser.ts create mode 100644 frontend/src/mocks/handlers.ts diff --git a/frontend/package.json b/frontend/package.json index 45d00a3d..cc839393 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -51,6 +51,7 @@ "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.30.1", "html-webpack-plugin": "^5.5.0", + "msw": "^0.43.0", "prettier": "^2.7.1", "style-loader": "^3.3.1", "ts-loader": "^9.3.1", @@ -58,5 +59,8 @@ "webpack": "^5.73.0", "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.9.3" + }, + "msw": { + "workerDirectory": "public" } } diff --git a/frontend/public/mockServiceWorker.js b/frontend/public/mockServiceWorker.js new file mode 100644 index 00000000..3dde0a23 --- /dev/null +++ b/frontend/public/mockServiceWorker.js @@ -0,0 +1,367 @@ +/* eslint-disable */ +/* tslint:disable */ + +/** + * Mock Service Worker (0.43.0). + * @see https://github.com/mswjs/msw + * - Please do NOT modify this file. + * - Please do NOT serve this file on production. + */ + +const INTEGRITY_CHECKSUM = 'c9450df6e4dc5e45740c3b0b640727a2' +const activeClientIds = new Set() + +self.addEventListener('install', function () { + self.skipWaiting() +}) + +self.addEventListener('activate', function (event) { + event.waitUntil(self.clients.claim()) +}) + +self.addEventListener('message', async function (event) { + const clientId = event.source.id + + if (!clientId || !self.clients) { + return + } + + const client = await self.clients.get(clientId) + + if (!client) { + return + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }) + + switch (event.data) { + case 'KEEPALIVE_REQUEST': { + sendToClient(client, { + type: 'KEEPALIVE_RESPONSE', + }) + break + } + + case 'INTEGRITY_CHECK_REQUEST': { + sendToClient(client, { + type: 'INTEGRITY_CHECK_RESPONSE', + payload: INTEGRITY_CHECKSUM, + }) + break + } + + case 'MOCK_ACTIVATE': { + activeClientIds.add(clientId) + + sendToClient(client, { + type: 'MOCKING_ENABLED', + payload: true, + }) + break + } + + case 'MOCK_DEACTIVATE': { + activeClientIds.delete(clientId) + break + } + + case 'CLIENT_CLOSED': { + activeClientIds.delete(clientId) + + const remainingClients = allClients.filter((client) => { + return client.id !== clientId + }) + + // Unregister itself when there are no more clients + if (remainingClients.length === 0) { + self.registration.unregister() + } + + break + } + } +}) + +self.addEventListener('fetch', function (event) { + const { request } = event + const accept = request.headers.get('accept') || '' + + // Bypass server-sent events. + if (accept.includes('text/event-stream')) { + return + } + + // Bypass navigation requests. + if (request.mode === 'navigate') { + return + } + + // Opening the DevTools triggers the "only-if-cached" request + // that cannot be handled by the worker. Bypass such requests. + if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { + return + } + + // Bypass all requests when there are no active clients. + // Prevents the self-unregistered worked from handling requests + // after it's been deleted (still remains active until the next reload). + if (activeClientIds.size === 0) { + return + } + + // Generate unique request ID. + const requestId = Math.random().toString(16).slice(2) + + event.respondWith( + handleRequest(event, requestId).catch((error) => { + if (error.name === 'NetworkError') { + console.warn( + '[MSW] Successfully emulated a network error for the "%s %s" request.', + request.method, + request.url, + ) + return + } + + // At this point, any exception indicates an issue with the original request/response. + console.error( + `\ +[MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`, + request.method, + request.url, + `${error.name}: ${error.message}`, + ) + }), + ) +}) + +async function handleRequest(event, requestId) { + const client = await resolveMainClient(event) + const response = await getResponse(event, client, requestId) + + // Send back the response clone for the "response:*" life-cycle events. + // Ensure MSW is active and ready to handle the message, otherwise + // this message will pend indefinitely. + if (client && activeClientIds.has(client.id)) { + ;(async function () { + const clonedResponse = response.clone() + sendToClient(client, { + type: 'RESPONSE', + payload: { + requestId, + type: clonedResponse.type, + ok: clonedResponse.ok, + status: clonedResponse.status, + statusText: clonedResponse.statusText, + body: + clonedResponse.body === null ? null : await clonedResponse.text(), + headers: Object.fromEntries(clonedResponse.headers.entries()), + redirected: clonedResponse.redirected, + }, + }) + })() + } + + return response +} + +// Resolve the main client for the given event. +// Client that issues a request doesn't necessarily equal the client +// that registered the worker. It's with the latter the worker should +// communicate with during the response resolving phase. +async function resolveMainClient(event) { + const client = await self.clients.get(event.clientId) + + if (client.frameType === 'top-level') { + return client + } + + const allClients = await self.clients.matchAll({ + type: 'window', + }) + + return allClients + .filter((client) => { + // Get only those clients that are currently visible. + return client.visibilityState === 'visible' + }) + .find((client) => { + // Find the client ID that's recorded in the + // set of clients that have registered the worker. + return activeClientIds.has(client.id) + }) +} + +async function getResponse(event, client, requestId) { + const { request } = event + const clonedRequest = request.clone() + + function passthrough() { + // Clone the request because it might've been already used + // (i.e. its body has been read and sent to the cilent). + const headers = Object.fromEntries(clonedRequest.headers.entries()) + + // Remove MSW-specific request headers so the bypassed requests + // comply with the server's CORS preflight check. + // Operate with the headers as an object because request "Headers" + // are immutable. + delete headers['x-msw-bypass'] + + return fetch(clonedRequest, { headers }) + } + + // Bypass mocking when the client is not active. + if (!client) { + return passthrough() + } + + // Bypass initial page load requests (i.e. static assets). + // The absence of the immediate/parent client in the map of the active clients + // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet + // and is not ready to handle requests. + if (!activeClientIds.has(client.id)) { + return passthrough() + } + + // Bypass requests with the explicit bypass header. + // Such requests can be issued by "ctx.fetch()". + if (request.headers.get('x-msw-bypass') === 'true') { + return passthrough() + } + + // Create a communication channel scoped to the current request. + // This way events can be exchanged outside of the worker's global + // "message" event listener (i.e. abstracted into functions). + const operationChannel = new BroadcastChannel( + `msw-response-stream-${requestId}`, + ) + + // Notify the client that a request has been intercepted. + const clientMessage = await sendToClient(client, { + type: 'REQUEST', + payload: { + id: requestId, + url: request.url, + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + cache: request.cache, + mode: request.mode, + credentials: request.credentials, + destination: request.destination, + integrity: request.integrity, + redirect: request.redirect, + referrer: request.referrer, + referrerPolicy: request.referrerPolicy, + body: await request.text(), + bodyUsed: request.bodyUsed, + keepalive: request.keepalive, + }, + }) + + switch (clientMessage.type) { + case 'MOCK_RESPONSE': { + return respondWithMock(clientMessage.payload) + } + + case 'MOCK_RESPONSE_START': { + return respondWithMockStream(operationChannel, clientMessage.payload) + } + + case 'MOCK_NOT_FOUND': { + return passthrough() + } + + case 'NETWORK_ERROR': { + const { name, message } = clientMessage.payload + const networkError = new Error(message) + networkError.name = name + + // Rejecting a "respondWith" promise emulates a network error. + throw networkError + } + + case 'INTERNAL_ERROR': { + const parsedBody = JSON.parse(clientMessage.payload.body) + + console.error( + `\ +[MSW] Uncaught exception in the request handler for "%s %s": + +${parsedBody.location} + +This exception has been gracefully handled as a 500 response, however, it's strongly recommended to resolve this error, as it indicates a mistake in your code. If you wish to mock an error response, please see this guide: https://mswjs.io/docs/recipes/mocking-error-responses\ +`, + request.method, + request.url, + ) + + return respondWithMock(clientMessage.payload) + } + } + + return passthrough() +} + +function sendToClient(client, message) { + return new Promise((resolve, reject) => { + const channel = new MessageChannel() + + channel.port1.onmessage = (event) => { + if (event.data && event.data.error) { + return reject(event.data.error) + } + + resolve(event.data) + } + + client.postMessage(JSON.stringify(message), [channel.port2]) + }) +} + +function sleep(timeMs) { + return new Promise((resolve) => { + setTimeout(resolve, timeMs) + }) +} + +async function respondWithMock(response) { + await sleep(response.delay) + return new Response(response.body, response) +} + +function respondWithMockStream(operationChannel, mockResponse) { + let streamCtrl + const stream = new ReadableStream({ + start: (controller) => (streamCtrl = controller), + }) + + return new Promise(async (resolve, reject) => { + operationChannel.onmessageerror = (event) => { + operationChannel.close() + return reject(event.data.error) + } + + operationChannel.onmessage = (event) => { + if (!event.data) { + return + } + + switch (event.data.type) { + case 'MOCK_RESPONSE_CHUNK': { + streamCtrl.enqueue(event.data.payload) + break + } + + case 'MOCK_RESPONSE_END': { + streamCtrl.close() + operationChannel.close() + } + } + } + + await sleep(mockResponse.delay) + return resolve(new Response(stream, mockResponse)) + }) +} diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index c0973b94..fc66f2c0 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -6,6 +6,12 @@ import GlobalStyle from '@/styles/GlobalStyle'; import App from '@/App'; +import { worker } from '@/mocks/browser'; + +if (process.env.NODE_ENV === 'development') { + worker.start(); +} + const rootElement = document.getElementById('root'); ReactDOM.render( diff --git a/frontend/src/mocks/browser.ts b/frontend/src/mocks/browser.ts new file mode 100644 index 00000000..750e031c --- /dev/null +++ b/frontend/src/mocks/browser.ts @@ -0,0 +1,4 @@ +import { setupWorker } from 'msw'; +import { handlers } from './handlers'; + +export const worker = setupWorker(...handlers); diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts new file mode 100644 index 00000000..76382dd3 --- /dev/null +++ b/frontend/src/mocks/handlers.ts @@ -0,0 +1,20 @@ +import { rest } from 'msw'; + +interface PostScheduleReqBody { + title: string; + startDateTime: string; + endDateTime: string; + memo: string; +} + +const scheduleDB = []; + +const handlers = [ + rest.post('/api/schedules', (req, res, ctx) => { + scheduleDB.push(req.body); + + return res(ctx.status(201)); + }), +]; + +export { handlers }; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index c7b54134..80ab8d9c 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -1495,6 +1495,26 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@mswjs/cookies@^0.2.0": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@mswjs/cookies/-/cookies-0.2.1.tgz#66a283b45970ffc5350d22657983a1377ea6bf97" + integrity sha512-0tDfcPw5/s7QsNQqS3knAvAD5w5PF1nNPagRhKO/yECY+sMbJxoC2sLWnH7Lzmh52mTSVLKDhd1r92Q3kfljnQ== + dependencies: + "@types/set-cookie-parser" "^2.4.0" + set-cookie-parser "^2.4.6" + +"@mswjs/interceptors@^0.16.3": + version "0.16.6" + resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.16.6.tgz#c1a777ed3f69b55bbbc725b2deb827f160c0107c" + integrity sha512-7ax1sRx5s4ZWl0KvVhhcPOUoPbCCkVh8M8hYaqOyvoAQOiqLVzy+Z6Mh2ywPhYw4zudr5Mo/E8UT/zJBO/Wxrw== + dependencies: + "@open-draft/until" "^1.0.3" + "@xmldom/xmldom" "^0.7.5" + debug "^4.3.3" + headers-polyfill "^3.0.4" + outvariant "^1.2.1" + strict-event-emitter "^0.2.4" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1537,6 +1557,11 @@ mkdirp "^1.0.4" rimraf "^3.0.2" +"@open-draft/until@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-1.0.3.tgz#db9cc719191a62e7d9200f6e7bab21c5b848adca" + integrity sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q== + "@pmmmwh/react-refresh-webpack-plugin@^0.5.3": version "0.5.7" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.7.tgz#58f8217ba70069cc6a73f5d7e05e85b458c150e2" @@ -2548,6 +2573,11 @@ dependencies: "@types/node" "*" +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + "@types/eslint-scope@^3.7.3": version "3.7.4" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" @@ -2656,6 +2686,11 @@ dependencies: "@types/istanbul-lib-report" "*" +"@types/js-levenshtein@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz#ba05426a43f9e4e30b631941e0aa17bf0c890ed5" + integrity sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g== + "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -2794,6 +2829,13 @@ "@types/mime" "^1" "@types/node" "*" +"@types/set-cookie-parser@^2.4.0": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@types/set-cookie-parser/-/set-cookie-parser-2.4.2.tgz#b6a955219b54151bfebd4521170723df5e13caad" + integrity sha512-fBZgytwhYAUkj/jC/FAV4RQ5EerRup1YQsXQCh8rZfiHkc4UahC192oH0smGwsXol3cL3A5oETuAHeQHmhXM4w== + dependencies: + "@types/node" "*" + "@types/sockjs@^0.3.33": version "0.3.33" resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" @@ -3238,6 +3280,11 @@ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== +"@xmldom/xmldom@^0.7.5": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.5.tgz#09fa51e356d07d0be200642b0e4f91d8e6dd408d" + integrity sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -3378,6 +3425,13 @@ ansi-colors@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-html-community@0.0.8, ansi-html-community@^0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41" @@ -3770,7 +3824,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.0.2: +base64-js@^1.0.2, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -3827,6 +3881,15 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -4034,6 +4097,14 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" @@ -4203,6 +4274,14 @@ ccount@^1.0.0: resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== +chalk@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" + integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^2.0.0, chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -4212,7 +4291,7 @@ chalk@^2.0.0, chalk@^2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -4235,6 +4314,11 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -4338,6 +4422,18 @@ cli-boxes@^2.2.1: resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" + integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== + cli-table3@^0.6.1: version "0.6.2" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.2.tgz#aaf5df9d8b5bf12634dc8b3040806a0c07120d2a" @@ -4347,6 +4443,11 @@ cli-table3@^0.6.1: optionalDependencies: "@colors/colors" "1.5.0" +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -4365,6 +4466,11 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + clsx@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702" @@ -4563,6 +4669,11 @@ cookie@0.5.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +cookie@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -4819,7 +4930,7 @@ debug@^3.0.0, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: +debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -4867,6 +4978,13 @@ default-gateway@^6.0.3: dependencies: execa "^5.0.0" +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA== + dependencies: + clone "^1.0.2" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" @@ -5533,7 +5651,7 @@ eventemitter3@^4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -events@^3.0.0, events@^3.2.0: +events@^3.0.0, events@^3.2.0, events@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -5649,6 +5767,15 @@ extend@^3.0.0: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -5754,6 +5881,13 @@ figgy-pudding@^3.5.1: resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -6268,6 +6402,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +graphql@^16.3.0: + version "16.5.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.5.0.tgz#41b5c1182eaac7f3d47164fb247f61e4dfb69c85" + integrity sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA== + handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -6459,6 +6598,11 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +headers-polyfill@^3.0.4: + version "3.0.7" + resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-3.0.7.tgz#725c4f591e6748f46b036197eae102c92b959ff4" + integrity sha512-JoLCAdCEab58+2/yEmSnOlficyHFpIl0XJqwu3l+Unkm1gXpFUYsThz6Yha3D6tNhocWkCPfyW0YVIGWFqTi7w== + highlight.js@^10.4.1, highlight.js@~10.7.0: version "10.7.3" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" @@ -6638,7 +6782,7 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -iconv-lite@0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -6657,7 +6801,7 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ieee754@^1.1.4: +ieee754@^1.1.13, ieee754@^1.1.4: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -6743,6 +6887,27 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== +inquirer@^8.2.0: + version "8.2.4" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.4.tgz#ddbfe86ca2f67649a67daa6f1051c128f684f0b4" + integrity sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.1" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.21" + mute-stream "0.0.8" + ora "^5.4.1" + run-async "^2.4.0" + rxjs "^7.5.5" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + wrap-ansi "^7.0.0" + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -6983,6 +7148,11 @@ is-hexadecimal@^1.0.0: resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + is-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" @@ -6993,6 +7163,11 @@ is-negative-zero@^2.0.2: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== +is-node-process@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.0.1.tgz#4fc7ac3a91e8aac58175fe0578abbc56f2831b23" + integrity sha512-5IcdXuf++TTNt3oGl9EBdkvndXA8gmc4bz/Y+mdEpWh3Mcn/+kOw6hI7LD5CocqJWMzeb0I0ClndRVNdEPuJXQ== + is-number-object@^1.0.4: version "1.0.7" resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" @@ -7107,6 +7282,11 @@ is-typedarray@^1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" @@ -7309,6 +7489,11 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" +js-levenshtein@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" + integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== + js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" @@ -7558,6 +7743,14 @@ lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -7999,6 +8192,32 @@ ms@2.1.3, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +msw@^0.43.0: + version "0.43.0" + resolved "https://registry.yarnpkg.com/msw/-/msw-0.43.0.tgz#10c6fc3fb1752c0a144179e5ab04c6a512cc9959" + integrity sha512-XJylZP0qW3D5WUGWh9FFefJEl3MGG4y1I+/8a833d0eedm6B+GaPm6wPVZNcnlS2YVTagvEgShVJ7ZtY66tTRQ== + dependencies: + "@mswjs/cookies" "^0.2.0" + "@mswjs/interceptors" "^0.16.3" + "@open-draft/until" "^1.0.3" + "@types/cookie" "^0.4.1" + "@types/js-levenshtein" "^1.1.1" + chalk "4.1.1" + chokidar "^3.4.2" + cookie "^0.4.2" + graphql "^16.3.0" + headers-polyfill "^3.0.4" + inquirer "^8.2.0" + is-node-process "^1.0.1" + js-levenshtein "^1.1.6" + node-fetch "^2.6.7" + outvariant "^1.3.0" + path-to-regexp "^6.2.0" + statuses "^2.0.0" + strict-event-emitter "^0.2.0" + type-fest "^1.2.2" + yargs "^17.3.1" + multicast-dns@^7.2.5: version "7.2.5" resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" @@ -8007,6 +8226,11 @@ multicast-dns@^7.2.5: dns-packet "^5.2.2" thunky "^1.0.2" +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + nan@^2.12.1: version "2.16.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.16.0.tgz#664f43e45460fb98faf00edca0bb0d7b8dce7916" @@ -8310,7 +8534,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.2: +onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== @@ -8358,6 +8582,21 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" @@ -8368,6 +8607,16 @@ os-homedir@^1.0.0: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +outvariant@^1.2.1, outvariant@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.3.0.tgz#c39723b1d2cba729c930b74bf962317a81b9b1c9" + integrity sha512-yeWM9k6UPfG/nzxdaPlJkB2p08hCg4xP6Lx99F+vP8YF7xyZVfTmJjrrNalkmzudD4WFvNLVudQikqUmF8zhVQ== + p-all@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-all/-/p-all-2.1.0.tgz#91419be56b7dee8fe4c5db875d55e0da084244a0" @@ -8646,6 +8895,11 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +path-to-regexp@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5" + integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw== + path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -9277,7 +9531,7 @@ read-pkg@^5.2.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.6.0: +readable-stream@^3.0.6, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -9568,6 +9822,14 @@ resolve@^2.0.0-next.3: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -9610,6 +9872,11 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -9624,6 +9891,13 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" +rxjs@^7.5.5: + version "7.5.5" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f" + integrity sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw== + dependencies: + tslib "^2.1.0" + safe-buffer@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -9832,6 +10106,11 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +set-cookie-parser@^2.4.6: + version "2.5.0" + resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.5.0.tgz#96b59525e1362c94335c3c761100bb6e8f2da4b0" + integrity sha512-cHMAtSXilfyBePduZEBVPTCftTQWz6ehWJD5YNUg4mqvRosrrjKbo4WS8JkB0/RxonMoohHm7cOGH60mDkRQ9w== + set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" @@ -10116,7 +10395,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -statuses@2.0.1: +statuses@2.0.1, statuses@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== @@ -10163,6 +10442,13 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== +strict-event-emitter@^0.2.0, strict-event-emitter@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.2.4.tgz#365714f0c95f059db31064ca745d5b33e5b30f6e" + integrity sha512-xIqTLS5azUH1djSUsLH9DbP6UnM/nI18vu8d43JigCQEoVsnY+mrlE+qv6kYqs6/1OkMnMIiL6ffedQSZStuoQ== + dependencies: + events "^3.3.0" + "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -10483,6 +10769,11 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + thunky@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" @@ -10495,6 +10786,13 @@ timers-browserify@^2.0.4: dependencies: setimmediate "^1.0.4" +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -10607,7 +10905,7 @@ tslib@^1.8.1, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== @@ -10643,6 +10941,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + type-fest@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" @@ -10653,6 +10956,11 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-fest@^1.2.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" + integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -11042,6 +11350,13 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + web-namespaces@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" @@ -11415,6 +11730,11 @@ yargs-parser@^20.2.2, yargs-parser@^20.2.9: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs-parser@^21.0.0: + version "21.0.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35" + integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== + yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" @@ -11428,6 +11748,19 @@ yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yargs@^17.3.1: + version "17.5.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e" + integrity sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" From 6ae8c0033feb72801ad83e518a9dbba09eefd62c Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 6 Jul 2022 22:21:37 +0900 Subject: [PATCH 0039/1011] =?UTF-8?q?feat:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20form=EC=9D=84=20=EB=B9=84=EC=A0=9C?= =?UTF-8?q?=EC=96=B4=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../components/@common/FieldSet/FieldSet.tsx | 8 +-- .../ScheduleAddModal/ScheduleAddModal.tsx | 51 ++++++++++++++++--- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/@common/FieldSet/FieldSet.tsx b/frontend/src/components/@common/FieldSet/FieldSet.tsx index a520a90b..44c57dce 100644 --- a/frontend/src/components/@common/FieldSet/FieldSet.tsx +++ b/frontend/src/components/@common/FieldSet/FieldSet.tsx @@ -1,4 +1,5 @@ import { SerializedStyles, useTheme } from '@emotion/react'; +import React from 'react'; import { fieldSet, input, label } from './FieldSet.styles'; @@ -6,9 +7,10 @@ interface FieldSetProps extends React.HTMLAttributes { type?: string; cssProp?: SerializedStyles; labelText?: string; + refProp?: React.MutableRefObject; } -function FieldSet({ type = 'text', id, cssProp, labelText, placeholder }: FieldSetProps) { +function FieldSet({ type = 'text', id, cssProp, labelText, placeholder, refProp }: FieldSetProps) { const theme = useTheme(); return ( @@ -18,9 +20,9 @@ function FieldSet({ type = 'text', id, cssProp, labelText, placeholder }: FieldS {labelText} )} - +
); } -export default FieldSet; +export default React.forwardRef(FieldSet); diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index f59625a0..8a0ce421 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -1,3 +1,5 @@ +import { useRef } from 'react'; + import { useTheme } from '@emotion/react'; import { @@ -21,26 +23,63 @@ interface ScheduleAddModalProps { function ScheduleAddModal({ closeModal }: ScheduleAddModalProps) { const theme = useTheme(); + const inputRef = { + title: useRef(null), + startDateTime: useRef(null), + endDateTime: useRef(null), + memo: useRef(null), + }; + const handleClickScheduleAddModal = (e: React.MouseEvent) => { e.stopPropagation(); }; + const onSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + + const isValidRef = Object.values(inputRef).every( + (inputRef) => inputRef.current instanceof HTMLInputElement + ); + + if (!isValidRef) { + return; + } + + const [title, startDateTime, endDateTime, memo] = Object.values(inputRef); + + const body = await JSON.stringify({ + title: title.current?.value, + startDateTime: startDateTime.current?.value, + endDateTime: endDateTime.current?.value, + memo: memo.current?.value, + }); + + await fetch('/api/schedules', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + body, + }); + }; + return (
- -
+ +
-
+

-
+
-
+
-
From 747f52f35baf898aebdca96a274bc93983f2344f Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 7 Jul 2022 12:43:43 +0900 Subject: [PATCH 0040/1011] =?UTF-8?q?chore:=20prettier=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/public/mockServiceWorker.js | 205 +++++++++++++-------------- 1 file changed, 101 insertions(+), 104 deletions(-) diff --git a/frontend/public/mockServiceWorker.js b/frontend/public/mockServiceWorker.js index 3dde0a23..a5fbb289 100644 --- a/frontend/public/mockServiceWorker.js +++ b/frontend/public/mockServiceWorker.js @@ -8,111 +8,111 @@ * - Please do NOT serve this file on production. */ -const INTEGRITY_CHECKSUM = 'c9450df6e4dc5e45740c3b0b640727a2' -const activeClientIds = new Set() +const INTEGRITY_CHECKSUM = 'c9450df6e4dc5e45740c3b0b640727a2'; +const activeClientIds = new Set(); self.addEventListener('install', function () { - self.skipWaiting() -}) + self.skipWaiting(); +}); self.addEventListener('activate', function (event) { - event.waitUntil(self.clients.claim()) -}) + event.waitUntil(self.clients.claim()); +}); self.addEventListener('message', async function (event) { - const clientId = event.source.id + const clientId = event.source.id; if (!clientId || !self.clients) { - return + return; } - const client = await self.clients.get(clientId) + const client = await self.clients.get(clientId); if (!client) { - return + return; } const allClients = await self.clients.matchAll({ type: 'window', - }) + }); switch (event.data) { case 'KEEPALIVE_REQUEST': { sendToClient(client, { type: 'KEEPALIVE_RESPONSE', - }) - break + }); + break; } case 'INTEGRITY_CHECK_REQUEST': { sendToClient(client, { type: 'INTEGRITY_CHECK_RESPONSE', payload: INTEGRITY_CHECKSUM, - }) - break + }); + break; } case 'MOCK_ACTIVATE': { - activeClientIds.add(clientId) + activeClientIds.add(clientId); sendToClient(client, { type: 'MOCKING_ENABLED', payload: true, - }) - break + }); + break; } case 'MOCK_DEACTIVATE': { - activeClientIds.delete(clientId) - break + activeClientIds.delete(clientId); + break; } case 'CLIENT_CLOSED': { - activeClientIds.delete(clientId) + activeClientIds.delete(clientId); const remainingClients = allClients.filter((client) => { - return client.id !== clientId - }) + return client.id !== clientId; + }); // Unregister itself when there are no more clients if (remainingClients.length === 0) { - self.registration.unregister() + self.registration.unregister(); } - break + break; } } -}) +}); self.addEventListener('fetch', function (event) { - const { request } = event - const accept = request.headers.get('accept') || '' + const { request } = event; + const accept = request.headers.get('accept') || ''; // Bypass server-sent events. if (accept.includes('text/event-stream')) { - return + return; } // Bypass navigation requests. if (request.mode === 'navigate') { - return + return; } // Opening the DevTools triggers the "only-if-cached" request // that cannot be handled by the worker. Bypass such requests. if (request.cache === 'only-if-cached' && request.mode !== 'same-origin') { - return + return; } // Bypass all requests when there are no active clients. // Prevents the self-unregistered worked from handling requests // after it's been deleted (still remains active until the next reload). if (activeClientIds.size === 0) { - return + return; } // Generate unique request ID. - const requestId = Math.random().toString(16).slice(2) + const requestId = Math.random().toString(16).slice(2); event.respondWith( handleRequest(event, requestId).catch((error) => { @@ -120,9 +120,9 @@ self.addEventListener('fetch', function (event) { console.warn( '[MSW] Successfully emulated a network error for the "%s %s" request.', request.method, - request.url, - ) - return + request.url + ); + return; } // At this point, any exception indicates an issue with the original request/response. @@ -131,22 +131,22 @@ self.addEventListener('fetch', function (event) { [MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`, request.method, request.url, - `${error.name}: ${error.message}`, - ) - }), - ) -}) + `${error.name}: ${error.message}` + ); + }) + ); +}); async function handleRequest(event, requestId) { - const client = await resolveMainClient(event) - const response = await getResponse(event, client, requestId) + const client = await resolveMainClient(event); + const response = await getResponse(event, client, requestId); // Send back the response clone for the "response:*" life-cycle events. // Ensure MSW is active and ready to handle the message, otherwise // this message will pend indefinitely. if (client && activeClientIds.has(client.id)) { - ;(async function () { - const clonedResponse = response.clone() + (async function () { + const clonedResponse = response.clone(); sendToClient(client, { type: 'RESPONSE', payload: { @@ -155,16 +155,15 @@ async function handleRequest(event, requestId) { ok: clonedResponse.ok, status: clonedResponse.status, statusText: clonedResponse.statusText, - body: - clonedResponse.body === null ? null : await clonedResponse.text(), + body: clonedResponse.body === null ? null : await clonedResponse.text(), headers: Object.fromEntries(clonedResponse.headers.entries()), redirected: clonedResponse.redirected, }, - }) - })() + }); + })(); } - return response + return response; } // Resolve the main client for the given event. @@ -172,49 +171,49 @@ async function handleRequest(event, requestId) { // that registered the worker. It's with the latter the worker should // communicate with during the response resolving phase. async function resolveMainClient(event) { - const client = await self.clients.get(event.clientId) + const client = await self.clients.get(event.clientId); if (client.frameType === 'top-level') { - return client + return client; } const allClients = await self.clients.matchAll({ type: 'window', - }) + }); return allClients .filter((client) => { // Get only those clients that are currently visible. - return client.visibilityState === 'visible' + return client.visibilityState === 'visible'; }) .find((client) => { // Find the client ID that's recorded in the // set of clients that have registered the worker. - return activeClientIds.has(client.id) - }) + return activeClientIds.has(client.id); + }); } async function getResponse(event, client, requestId) { - const { request } = event - const clonedRequest = request.clone() + const { request } = event; + const clonedRequest = request.clone(); function passthrough() { // Clone the request because it might've been already used // (i.e. its body has been read and sent to the cilent). - const headers = Object.fromEntries(clonedRequest.headers.entries()) + const headers = Object.fromEntries(clonedRequest.headers.entries()); // Remove MSW-specific request headers so the bypassed requests // comply with the server's CORS preflight check. // Operate with the headers as an object because request "Headers" // are immutable. - delete headers['x-msw-bypass'] + delete headers['x-msw-bypass']; - return fetch(clonedRequest, { headers }) + return fetch(clonedRequest, { headers }); } // Bypass mocking when the client is not active. if (!client) { - return passthrough() + return passthrough(); } // Bypass initial page load requests (i.e. static assets). @@ -222,21 +221,19 @@ async function getResponse(event, client, requestId) { // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet // and is not ready to handle requests. if (!activeClientIds.has(client.id)) { - return passthrough() + return passthrough(); } // Bypass requests with the explicit bypass header. // Such requests can be issued by "ctx.fetch()". if (request.headers.get('x-msw-bypass') === 'true') { - return passthrough() + return passthrough(); } // Create a communication channel scoped to the current request. // This way events can be exchanged outside of the worker's global // "message" event listener (i.e. abstracted into functions). - const operationChannel = new BroadcastChannel( - `msw-response-stream-${requestId}`, - ) + const operationChannel = new BroadcastChannel(`msw-response-stream-${requestId}`); // Notify the client that a request has been intercepted. const clientMessage = await sendToClient(client, { @@ -258,32 +255,32 @@ async function getResponse(event, client, requestId) { bodyUsed: request.bodyUsed, keepalive: request.keepalive, }, - }) + }); switch (clientMessage.type) { case 'MOCK_RESPONSE': { - return respondWithMock(clientMessage.payload) + return respondWithMock(clientMessage.payload); } case 'MOCK_RESPONSE_START': { - return respondWithMockStream(operationChannel, clientMessage.payload) + return respondWithMockStream(operationChannel, clientMessage.payload); } case 'MOCK_NOT_FOUND': { - return passthrough() + return passthrough(); } case 'NETWORK_ERROR': { - const { name, message } = clientMessage.payload - const networkError = new Error(message) - networkError.name = name + const { name, message } = clientMessage.payload; + const networkError = new Error(message); + networkError.name = name; // Rejecting a "respondWith" promise emulates a network error. - throw networkError + throw networkError; } case 'INTERNAL_ERROR': { - const parsedBody = JSON.parse(clientMessage.payload.body) + const parsedBody = JSON.parse(clientMessage.payload.body); console.error( `\ @@ -294,74 +291,74 @@ ${parsedBody.location} This exception has been gracefully handled as a 500 response, however, it's strongly recommended to resolve this error, as it indicates a mistake in your code. If you wish to mock an error response, please see this guide: https://mswjs.io/docs/recipes/mocking-error-responses\ `, request.method, - request.url, - ) + request.url + ); - return respondWithMock(clientMessage.payload) + return respondWithMock(clientMessage.payload); } } - return passthrough() + return passthrough(); } function sendToClient(client, message) { return new Promise((resolve, reject) => { - const channel = new MessageChannel() + const channel = new MessageChannel(); channel.port1.onmessage = (event) => { if (event.data && event.data.error) { - return reject(event.data.error) + return reject(event.data.error); } - resolve(event.data) - } + resolve(event.data); + }; - client.postMessage(JSON.stringify(message), [channel.port2]) - }) + client.postMessage(JSON.stringify(message), [channel.port2]); + }); } function sleep(timeMs) { return new Promise((resolve) => { - setTimeout(resolve, timeMs) - }) + setTimeout(resolve, timeMs); + }); } async function respondWithMock(response) { - await sleep(response.delay) - return new Response(response.body, response) + await sleep(response.delay); + return new Response(response.body, response); } function respondWithMockStream(operationChannel, mockResponse) { - let streamCtrl + let streamCtrl; const stream = new ReadableStream({ start: (controller) => (streamCtrl = controller), - }) + }); return new Promise(async (resolve, reject) => { operationChannel.onmessageerror = (event) => { - operationChannel.close() - return reject(event.data.error) - } + operationChannel.close(); + return reject(event.data.error); + }; operationChannel.onmessage = (event) => { if (!event.data) { - return + return; } switch (event.data.type) { case 'MOCK_RESPONSE_CHUNK': { - streamCtrl.enqueue(event.data.payload) - break + streamCtrl.enqueue(event.data.payload); + break; } case 'MOCK_RESPONSE_END': { - streamCtrl.close() - operationChannel.close() + streamCtrl.close(); + operationChannel.close(); } } - } + }; - await sleep(mockResponse.delay) - return resolve(new Response(stream, mockResponse)) - }) + await sleep(mockResponse.delay); + return resolve(new Response(stream, mockResponse)); + }); } From f5d10371d56dc381fa2ecfbb29aa0f156915a65f Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 7 Jul 2022 13:26:22 +0900 Subject: [PATCH 0041/1011] =?UTF-8?q?chore:=20scripts=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index cc839393..e28fc200 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,7 +11,7 @@ "storybook": "start-storybook -p 6006", "build-storybook": "build-storybook", "check-lint": "eslint . --ext .js,.jsx,.ts,.tsx", - "check-prettier": "prettier -c ." + "check-prettier": "prettier -c ./src" }, "dependencies": { "@emotion/react": "^11.9.3", From 6f7c06e812f4d442deedf26f19aacb243105b32c Mon Sep 17 00:00:00 2001 From: jhy979 <32920566+jhy979@users.noreply.github.com> Date: Thu, 7 Jul 2022 13:30:55 +0900 Subject: [PATCH 0042/1011] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20import=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee --- frontend/src/components/@common/FieldSet/FieldSet.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/components/@common/FieldSet/FieldSet.tsx b/frontend/src/components/@common/FieldSet/FieldSet.tsx index 44c57dce..2fd70259 100644 --- a/frontend/src/components/@common/FieldSet/FieldSet.tsx +++ b/frontend/src/components/@common/FieldSet/FieldSet.tsx @@ -1,5 +1,4 @@ import { SerializedStyles, useTheme } from '@emotion/react'; -import React from 'react'; import { fieldSet, input, label } from './FieldSet.styles'; From 474987d368d592d8cc6c75c7efb3dfab5748c3a4 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 7 Jul 2022 13:57:57 +0900 Subject: [PATCH 0043/1011] =?UTF-8?q?refactor:=20forwardRef=20=EC=A7=81?= =?UTF-8?q?=EC=A0=91=20import=ED=95=98=EC=97=AC=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com --- frontend/src/components/@common/FieldSet/FieldSet.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/@common/FieldSet/FieldSet.tsx b/frontend/src/components/@common/FieldSet/FieldSet.tsx index 2fd70259..b04bbed7 100644 --- a/frontend/src/components/@common/FieldSet/FieldSet.tsx +++ b/frontend/src/components/@common/FieldSet/FieldSet.tsx @@ -1,3 +1,5 @@ +import { forwardRef } from 'react'; + import { SerializedStyles, useTheme } from '@emotion/react'; import { fieldSet, input, label } from './FieldSet.styles'; @@ -24,4 +26,4 @@ function FieldSet({ type = 'text', id, cssProp, labelText, placeholder, refProp ); } -export default React.forwardRef(FieldSet); +export default forwardRef(FieldSet); From 5874c7caac355b339f6464bb63762c27cccf576f Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 7 Jul 2022 13:59:41 +0900 Subject: [PATCH 0044/1011] =?UTF-8?q?refactor:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20onSubmit=20=ED=95=B8=EB=93=A4=EB=9F=AC=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com --- frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index 8a0ce421..7120e388 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -34,7 +34,7 @@ function ScheduleAddModal({ closeModal }: ScheduleAddModalProps) { e.stopPropagation(); }; - const onSubmit = async (e: React.FormEvent) => { + const handleSubmitScheduleAddForm = async (e: React.FormEvent) => { e.preventDefault(); const isValidRef = Object.values(inputRef).every( @@ -66,7 +66,7 @@ function ScheduleAddModal({ closeModal }: ScheduleAddModalProps) { return (
- +
From 4e96d269237217951eff8398e6636d8c7936fe09 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 7 Jul 2022 15:48:30 +0900 Subject: [PATCH 0045/1011] =?UTF-8?q?feat:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../src/components/NavBar/NavBar.styles.ts | 4 ++++ .../components/PageLayout/PageLayout.styles.ts | 8 ++++++++ .../src/components/PageLayout/PageLayout.tsx | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 frontend/src/components/PageLayout/PageLayout.styles.ts create mode 100644 frontend/src/components/PageLayout/PageLayout.tsx diff --git a/frontend/src/components/NavBar/NavBar.styles.ts b/frontend/src/components/NavBar/NavBar.styles.ts index 90d20423..17598762 100644 --- a/frontend/src/components/NavBar/NavBar.styles.ts +++ b/frontend/src/components/NavBar/NavBar.styles.ts @@ -1,6 +1,10 @@ import { css, Theme } from '@emotion/react'; const navBar = ({ colors }: Theme) => css` + position: fixed; + top: 0; + left: 0; + width: 100%; height: 64px; padding: 8px; diff --git a/frontend/src/components/PageLayout/PageLayout.styles.ts b/frontend/src/components/PageLayout/PageLayout.styles.ts new file mode 100644 index 00000000..a1712ed2 --- /dev/null +++ b/frontend/src/components/PageLayout/PageLayout.styles.ts @@ -0,0 +1,8 @@ +import { css } from '@emotion/react'; + +const content = css` + margin-top: 64px; + padding: 8px; +`; + +export { content }; diff --git a/frontend/src/components/PageLayout/PageLayout.tsx b/frontend/src/components/PageLayout/PageLayout.tsx new file mode 100644 index 00000000..da75c9b6 --- /dev/null +++ b/frontend/src/components/PageLayout/PageLayout.tsx @@ -0,0 +1,18 @@ +import NavBar from '@/components/NavBar/NavBar'; + +import { content } from './PageLayout.styles'; + +interface PageLayoutProps { + children: JSX.Element | JSX.Element[]; +} + +function PageLayout({ children }: PageLayoutProps) { + return ( + <> + +
{children}
+ + ); +} + +export default PageLayout; From a4fb796b6e585d8582108a6c1e51e4e650d0222a Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 7 Jul 2022 15:50:12 +0900 Subject: [PATCH 0046/1011] =?UTF-8?q?style:=20=EC=83=89=EC=83=81=20?= =?UTF-8?q?=ED=8C=94=EB=A0=88=ED=8A=B8=20=ED=97=A5=EC=82=AC=EC=BD=94?= =?UTF-8?q?=EB=93=9C=206=EC=9E=90=EB=A6=AC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/styles/theme.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/styles/theme.ts b/frontend/src/styles/theme.ts index 21f0235e..ff561ed4 100644 --- a/frontend/src/styles/theme.ts +++ b/frontend/src/styles/theme.ts @@ -2,7 +2,7 @@ import { css, Theme } from '@emotion/react'; const colors = { YELLOW_500: '#FCC419', - WHITE: '#fff', + WHITE: '#ffffff', GRAY_000: '#f8f9fa', GRAY_100: '#f1f3f5', GRAY_200: '#e9ecef', @@ -13,7 +13,7 @@ const colors = { GRAY_700: '#495057', GRAY_800: '#343a40', GRAY_900: '#212529', - BLACK: '#000', + BLACK: '#000000', }; const flex = { From 37b9ffda2d1bc3eec7539ddd4cf7eadfe8640717 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 7 Jul 2022 15:51:10 +0900 Subject: [PATCH 0047/1011] =?UTF-8?q?style:=20=EC=8A=A4=ED=83=80=EC=9D=BC?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/components/@common/Button/Button.styles.ts | 2 +- .../src/components/@common/FieldSet/FieldSet.styles.ts | 2 +- .../components/@common/ModalPortal/ModalPortal.styles.ts | 3 +-- .../ScheduleAddModal/ScheduleAddModal.styles.ts | 8 +++++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/@common/Button/Button.styles.ts b/frontend/src/components/@common/Button/Button.styles.ts index 89c98654..72b3af71 100644 --- a/frontend/src/components/@common/Button/Button.styles.ts +++ b/frontend/src/components/@common/Button/Button.styles.ts @@ -9,7 +9,7 @@ const button = css` cursor: pointer; &:hover { - opacity: 0.7; + filter: brightness(1.1); } `; diff --git a/frontend/src/components/@common/FieldSet/FieldSet.styles.ts b/frontend/src/components/@common/FieldSet/FieldSet.styles.ts index e34317ca..860b67aa 100644 --- a/frontend/src/components/@common/FieldSet/FieldSet.styles.ts +++ b/frontend/src/components/@common/FieldSet/FieldSet.styles.ts @@ -3,7 +3,7 @@ import { css, Theme } from '@emotion/react'; const fieldSet = ({ flex }: Theme) => css` ${flex.column} - width: 500px; + width:100%; height: 60px; align-items: flex-start; diff --git a/frontend/src/components/@common/ModalPortal/ModalPortal.styles.ts b/frontend/src/components/@common/ModalPortal/ModalPortal.styles.ts index ba2765d7..4e87f407 100644 --- a/frontend/src/components/@common/ModalPortal/ModalPortal.styles.ts +++ b/frontend/src/components/@common/ModalPortal/ModalPortal.styles.ts @@ -10,8 +10,7 @@ const dimmer = ({ colors, flex }: Theme, isOpen: boolean) => css` width: 100%; height: 100%; - background: ${isOpen ? colors.GRAY_900 : 'transparent'}; - opacity: 0.9; + background: ${isOpen ? `${colors.BLACK}bb` : 'transparent'}; `; export { dimmer }; diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts index 52ead346..9b749832 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts @@ -1,8 +1,8 @@ import { css, Theme } from '@emotion/react'; const scheduleAddModal = ({ colors }: Theme) => css` - width: 600px; - height: 600px; + width: 480px; + height: 640px; padding: 50px; border-radius: 12px; @@ -17,7 +17,7 @@ const form = ({ flex }: Theme) => css` `; const allDayButton = ({ colors }: Theme) => css` - width: 500px; + width: 100%; height: 36px; border: 1px solid ${colors.GRAY_500}; border-radius: 8px; @@ -32,6 +32,8 @@ const allDayButton = ({ colors }: Theme) => css` const dateTime = ({ flex }: Theme) => css` ${flex.column} + width:100%; + gap: 10px; `; From 6a4799d03d59634d1586167364d79929633e9620 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 7 Jul 2022 15:52:12 +0900 Subject: [PATCH 0048/1011] =?UTF-8?q?feat:=20=EB=8B=AC=EB=A0=A5=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A0=88=EC=9D=B4=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/App.tsx | 6 ++++- frontend/src/components/Calendar/Calendar.tsx | 9 ++++++++ .../src/pages/CalendarPage/CalendarPage.tsx | 23 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/Calendar/Calendar.tsx create mode 100644 frontend/src/pages/CalendarPage/CalendarPage.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f27a8c76..6ede00c8 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,3 +1,7 @@ -const App = () => <>Dallog; +import CalendarPage from '@/pages/CalendarPage/CalendarPage'; + +function App() { + return ; +} export default App; diff --git a/frontend/src/components/Calendar/Calendar.tsx b/frontend/src/components/Calendar/Calendar.tsx new file mode 100644 index 00000000..12b65661 --- /dev/null +++ b/frontend/src/components/Calendar/Calendar.tsx @@ -0,0 +1,9 @@ +interface CalendarProps { + children?: string; +} + +function Calendar({ children }: CalendarProps) { + return
{children}
; +} + +export default Calendar; diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx new file mode 100644 index 00000000..a085a94b --- /dev/null +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -0,0 +1,23 @@ +import useModal from '@/hooks/useModal'; + +import PageLayout from '@/components/PageLayout/PageLayout'; +import Calendar from '@/components/Calendar/Calendar'; +import ScheduleAddButton from '@/components/ScheduleAddButton/ScheduleAddButton'; +import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; +import ScheduleAddModal from '@/components/ScheduleAddModal/ScheduleAddModal'; + +function CalendarPage() { + const { isOpen, openModal, closeModal } = useModal(); + + return ( + + + + + + + + ); +} + +export default CalendarPage; From d6c82acc3246399e15be6bb4c234b3ca19e80eb7 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 7 Jul 2022 19:02:56 +0900 Subject: [PATCH 0049/1011] =?UTF-8?q?style:=20=EB=8B=AC=EB=A0=A5=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../components/Calendar/Calendar.styles.ts | 20 +++++++++++++ frontend/src/components/Calendar/Calendar.tsx | 28 +++++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 frontend/src/components/Calendar/Calendar.styles.ts diff --git a/frontend/src/components/Calendar/Calendar.styles.ts b/frontend/src/components/Calendar/Calendar.styles.ts new file mode 100644 index 00000000..ccb221b8 --- /dev/null +++ b/frontend/src/components/Calendar/Calendar.styles.ts @@ -0,0 +1,20 @@ +import { css, Theme } from '@emotion/react'; + +const calendar = ({ flex }: Theme) => css` + ${flex.column} + + width: 100%; + height: 100%; + + gap: 20px; +`; + +const schedule = ({ colors }: Theme) => css` + padding: 20px; + border: 1px solid ${colors.BLACK}; + + font-size: 16px; + line-height: 32px; +`; + +export { calendar, schedule }; diff --git a/frontend/src/components/Calendar/Calendar.tsx b/frontend/src/components/Calendar/Calendar.tsx index 12b65661..2e9f81de 100644 --- a/frontend/src/components/Calendar/Calendar.tsx +++ b/frontend/src/components/Calendar/Calendar.tsx @@ -1,9 +1,31 @@ +import { calendar, schedule } from './Calendar.styles'; + +interface Schedule { + id: number; + title: string; + startDateTime: string; + endDateTime: string; + memo: string; +} + interface CalendarProps { - children?: string; + schedules: Schedule[]; } -function Calendar({ children }: CalendarProps) { - return
{children}
; +function Calendar({ schedules }: CalendarProps) { + return ( +
+ {schedules.map(({ id, title, startDateTime, endDateTime, memo }) => { + return ( +
+ 📅 {startDateTime.split('T').join(' ')} ~ {endDateTime.split('T').join(' ')} +

< {title} >

+ {memo} +
+ ); + })} +
+ ); } export default Calendar; From bd685ada20fa4efad32097bea692d3188e35c559 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 7 Jul 2022 19:03:36 +0900 Subject: [PATCH 0050/1011] =?UTF-8?q?feat:=20msw=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=9A=94=EC=B2=AD=20=EB=AA=A8=ED=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/mocks/handlers.ts | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 76382dd3..3cf53731 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -7,14 +7,37 @@ interface PostScheduleReqBody { memo: string; } -const scheduleDB = []; +interface ScheduleResponse extends PostScheduleReqBody { + id: number; +} + +const scheduleDB: ScheduleResponse[] = [ + { + id: 1, + title: '우테코 데모데이', + startDateTime: '2022-07-07T14:00', + endDateTime: '2022-07-07T18:00', + memo: '달록팀 스프린트 1차 발표', + }, + { + id: 2, + title: '테코톡', + startDateTime: '2022-07-09T14:00', + endDateTime: '2022-07-10T20:00', + memo: '레벨3 첫 테코톡', + }, +]; const handlers = [ rest.post('/api/schedules', (req, res, ctx) => { - scheduleDB.push(req.body); + scheduleDB.push({ id: scheduleDB.length + 1, ...req.body }); return res(ctx.status(201)); }), + + rest.get('/api/schedules', (req, res, ctx) => { + return res(ctx.status(200), ctx.json({ data: scheduleDB })); + }), ]; export { handlers }; From e43eee3994edba97c078917c1be1bd3b859cf869 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 7 Jul 2022 19:05:02 +0900 Subject: [PATCH 0051/1011] =?UTF-8?q?feat:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../ScheduleAddModal/ScheduleAddModal.tsx | 22 ++++++++++++- .../src/pages/CalendarPage/CalendarPage.tsx | 33 +++++++++++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index 7120e388..269d51c1 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -16,11 +16,20 @@ import { import Button from '../@common/Button/Button'; import FieldSet from '../@common/FieldSet/FieldSet'; +interface Schedule { + id: number; + title: string; + startDateTime: string; + endDateTime: string; + memo: string; +} + interface ScheduleAddModalProps { closeModal: () => void; + setSchedule: React.Dispatch>; } -function ScheduleAddModal({ closeModal }: ScheduleAddModalProps) { +function ScheduleAddModal({ closeModal, setSchedule }: ScheduleAddModalProps) { const theme = useTheme(); const inputRef = { @@ -62,6 +71,17 @@ function ScheduleAddModal({ closeModal }: ScheduleAddModalProps) { }, body, }); + + setSchedule((prev) => [ + ...prev, + { + id: prev.length, + title: title.current?.value as string, + startDateTime: startDateTime.current?.value as string, + endDateTime: endDateTime.current?.value as string, + memo: memo.current?.value as string, + }, + ]); }; return ( diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index a085a94b..005eb2e0 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -1,3 +1,5 @@ +import { useEffect, useState } from 'react'; + import useModal from '@/hooks/useModal'; import PageLayout from '@/components/PageLayout/PageLayout'; @@ -6,14 +8,41 @@ import ScheduleAddButton from '@/components/ScheduleAddButton/ScheduleAddButton' import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; import ScheduleAddModal from '@/components/ScheduleAddModal/ScheduleAddModal'; +interface Schedule { + id: number; + title: string; + startDateTime: string; + endDateTime: string; + memo: string; +} + function CalendarPage() { + const [schedules, setSchedules] = useState([]); + const { isOpen, openModal, closeModal } = useModal(); + useEffect(() => { + const fetchSchedules = async () => { + const response = await fetch('/api/schedules', { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + }); + const { data } = await response.json(); + + setSchedules(data); + }; + + fetchSchedules(); + }, []); + return ( - + - + From f97658bb466217f04356b81efad80ab9fd244e96 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 12 Jul 2022 17:02:40 +0900 Subject: [PATCH 0052/1011] =?UTF-8?q?style:=20css=20=EB=8B=A8=EC=9C=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/.storybook/preview-body.html | 5 +++ .../@common/FieldSet/FieldSet.styles.ts | 12 +++---- .../components/Calendar/Calendar.styles.ts | 8 ++--- .../src/components/NavBar/NavBar.styles.ts | 6 ++-- .../PageLayout/PageLayout.styles.ts | 4 +-- .../ScheduleAddButton.styles.ts | 12 +++---- .../ScheduleAddModal.styles.ts | 34 +++++++++---------- frontend/src/index.html | 2 +- frontend/src/styles/GlobalStyle.tsx | 2 +- 9 files changed, 45 insertions(+), 40 deletions(-) create mode 100644 frontend/.storybook/preview-body.html diff --git a/frontend/.storybook/preview-body.html b/frontend/.storybook/preview-body.html new file mode 100644 index 00000000..508dda40 --- /dev/null +++ b/frontend/.storybook/preview-body.html @@ -0,0 +1,5 @@ + diff --git a/frontend/src/components/@common/FieldSet/FieldSet.styles.ts b/frontend/src/components/@common/FieldSet/FieldSet.styles.ts index 860b67aa..436d27ca 100644 --- a/frontend/src/components/@common/FieldSet/FieldSet.styles.ts +++ b/frontend/src/components/@common/FieldSet/FieldSet.styles.ts @@ -3,21 +3,21 @@ import { css, Theme } from '@emotion/react'; const fieldSet = ({ flex }: Theme) => css` ${flex.column} - width:100%; - height: 60px; + width: 100%; + height: 15rem; align-items: flex-start; - gap: 10px; + gap: 2.5rem; - font-size: 20px; + font-size: 5rem; `; const label = css` - padding: 0 4px; + padding: 0 1rem; `; const input = ({ colors }: Theme) => css` - padding: 12px; + padding: 3rem; width: 100%; diff --git a/frontend/src/components/Calendar/Calendar.styles.ts b/frontend/src/components/Calendar/Calendar.styles.ts index ccb221b8..de637f33 100644 --- a/frontend/src/components/Calendar/Calendar.styles.ts +++ b/frontend/src/components/Calendar/Calendar.styles.ts @@ -6,15 +6,15 @@ const calendar = ({ flex }: Theme) => css` width: 100%; height: 100%; - gap: 20px; + gap: 5rem; `; const schedule = ({ colors }: Theme) => css` - padding: 20px; + padding: 5rem; border: 1px solid ${colors.BLACK}; - font-size: 16px; - line-height: 32px; + font-size: 4rem; + line-height: 8rem; `; export { calendar, schedule }; diff --git a/frontend/src/components/NavBar/NavBar.styles.ts b/frontend/src/components/NavBar/NavBar.styles.ts index 17598762..4a5ddb6f 100644 --- a/frontend/src/components/NavBar/NavBar.styles.ts +++ b/frontend/src/components/NavBar/NavBar.styles.ts @@ -6,12 +6,12 @@ const navBar = ({ colors }: Theme) => css` left: 0; width: 100%; - height: 64px; - padding: 8px; + height: 16rem; + padding: 2rem; background: ${colors.YELLOW_500}; - box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); + box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25); `; export { navBar }; diff --git a/frontend/src/components/PageLayout/PageLayout.styles.ts b/frontend/src/components/PageLayout/PageLayout.styles.ts index a1712ed2..e4c8334a 100644 --- a/frontend/src/components/PageLayout/PageLayout.styles.ts +++ b/frontend/src/components/PageLayout/PageLayout.styles.ts @@ -1,8 +1,8 @@ import { css } from '@emotion/react'; const content = css` - margin-top: 64px; - padding: 8px; + margin-top: 16rem; + padding: 2rem; `; export { content }; diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts index f2a5838c..fc3526ca 100644 --- a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts @@ -2,17 +2,17 @@ import { css, Theme } from '@emotion/react'; const scheduleAddButton = ({ colors }: Theme) => css` position: fixed; - right: 52px; - bottom: 52px; + right: 13rem; + bottom: 13rem; - width: 44px; - height: 44px; + width: 11rem; + height: 11rem; border-radius: 50%; background: ${colors.YELLOW_500}; - font-size: 28px; - line-height: 44px; + font-size: 7rem; + line-height: 11rem; font-weight: 700; color: ${colors.WHITE}; `; diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts index 9b749832..33c92ffc 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts @@ -1,9 +1,9 @@ import { css, Theme } from '@emotion/react'; const scheduleAddModal = ({ colors }: Theme) => css` - width: 480px; - height: 640px; - padding: 50px; + width: 120rem; + height: 160rem; + padding: 12.5rem; border-radius: 12px; background: ${colors.WHITE}; @@ -18,27 +18,27 @@ const form = ({ flex }: Theme) => css` const allDayButton = ({ colors }: Theme) => css` width: 100%; - height: 36px; + height: 9rem; border: 1px solid ${colors.GRAY_500}; border-radius: 8px; - filter: drop-shadow(0px 2px 2px ${colors.GRAY_400}); + filter: drop-shadow(0 2px 2px ${colors.GRAY_400}); background: ${colors.WHITE}; - font-size: 20px; + font-size: 5rem; color: ${colors.GRAY_600}; `; const dateTime = ({ flex }: Theme) => css` ${flex.column} - width:100%; + width: 100%; - gap: 10px; + gap: 2.5rem; `; const arrow = ({ colors }: Theme) => css` - font-size: 24px; + font-size: 6rem; font-weight: bold; color: ${colors.GRAY_500}; `; @@ -47,31 +47,31 @@ const controlButtons = ({ flex }: Theme) => css` ${flex.row} align-self: flex-end; - gap: 20px; + gap: 5rem; `; const cancelButton = ({ colors }: Theme) => css` - width: 90px; - height: 40px; + width: 22.5rem; + height: 10rem; border: 2px solid ${colors.GRAY_500}; border-radius: 8px; - filter: drop-shadow(0px 2px 2px ${colors.GRAY_400}); + filter: drop-shadow(0 2px 2px ${colors.GRAY_400}); background: ${colors.WHITE}; - font-size: 20px; + font-size: 5rem; color: ${colors.GRAY_600}; `; const saveButton = ({ colors }: Theme) => css` - width: 90px; - height: 40px; + width: 22.5rem; + height: 10rem; border-radius: 8px; filter: drop-shadow(0px 2px 2px ${colors.GRAY_400}); background: ${colors.YELLOW_500}; - font-size: 20px; + font-size: 5rem; color: ${colors.WHITE}; `; diff --git a/frontend/src/index.html b/frontend/src/index.html index 8d3f0eba..43007932 100644 --- a/frontend/src/index.html +++ b/frontend/src/index.html @@ -1,5 +1,5 @@ - + diff --git a/frontend/src/styles/GlobalStyle.tsx b/frontend/src/styles/GlobalStyle.tsx index d4752746..ac659cd8 100644 --- a/frontend/src/styles/GlobalStyle.tsx +++ b/frontend/src/styles/GlobalStyle.tsx @@ -16,7 +16,7 @@ const global = css` body { font-family: 'Pretendard', sans-serif; - font-size: 12px; + font-size: 1rem; } `; From 92720b081a040438b3d73bc68519f8b2c6ab3592 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 12 Jul 2022 17:12:14 +0900 Subject: [PATCH 0053/1011] =?UTF-8?q?refactor:=20=EC=A4=91=EB=B3=B5?= =?UTF-8?q?=EB=90=9C=20=ED=83=80=EC=9E=85=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/@types/index.ts | 9 +++++++++ frontend/src/components/Calendar/Calendar.tsx | 10 ++-------- .../components/ScheduleAddModal/ScheduleAddModal.tsx | 10 ++-------- frontend/src/pages/CalendarPage/CalendarPage.tsx | 10 ++-------- 4 files changed, 15 insertions(+), 24 deletions(-) create mode 100644 frontend/src/@types/index.ts diff --git a/frontend/src/@types/index.ts b/frontend/src/@types/index.ts new file mode 100644 index 00000000..ee73c148 --- /dev/null +++ b/frontend/src/@types/index.ts @@ -0,0 +1,9 @@ +interface Schedule { + id: number; + title: string; + startDateTime: string; + endDateTime: string; + memo: string; +} + +export { Schedule }; diff --git a/frontend/src/components/Calendar/Calendar.tsx b/frontend/src/components/Calendar/Calendar.tsx index 2e9f81de..7a6c9e6e 100644 --- a/frontend/src/components/Calendar/Calendar.tsx +++ b/frontend/src/components/Calendar/Calendar.tsx @@ -1,12 +1,6 @@ -import { calendar, schedule } from './Calendar.styles'; +import { Schedule } from '@/@types'; -interface Schedule { - id: number; - title: string; - startDateTime: string; - endDateTime: string; - memo: string; -} +import { calendar, schedule } from './Calendar.styles'; interface CalendarProps { schedules: Schedule[]; diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index 269d51c1..d9857373 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -2,6 +2,8 @@ import { useRef } from 'react'; import { useTheme } from '@emotion/react'; +import { Schedule } from '@/@types'; + import { allDayButton, arrow, @@ -16,14 +18,6 @@ import { import Button from '../@common/Button/Button'; import FieldSet from '../@common/FieldSet/FieldSet'; -interface Schedule { - id: number; - title: string; - startDateTime: string; - endDateTime: string; - memo: string; -} - interface ScheduleAddModalProps { closeModal: () => void; setSchedule: React.Dispatch>; diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index 005eb2e0..0565f6e5 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -2,20 +2,14 @@ import { useEffect, useState } from 'react'; import useModal from '@/hooks/useModal'; +import { Schedule } from '@/@types'; + import PageLayout from '@/components/PageLayout/PageLayout'; import Calendar from '@/components/Calendar/Calendar'; import ScheduleAddButton from '@/components/ScheduleAddButton/ScheduleAddButton'; import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; import ScheduleAddModal from '@/components/ScheduleAddModal/ScheduleAddModal'; -interface Schedule { - id: number; - title: string; - startDateTime: string; - endDateTime: string; - memo: string; -} - function CalendarPage() { const [schedules, setSchedules] = useState([]); From d14cb1ab5915ae666b5c64eb82071e8c24021455 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 12 Jul 2022 21:53:44 +0900 Subject: [PATCH 0054/1011] =?UTF-8?q?feat:=20react-query=20=EB=B0=8F=20axi?= =?UTF-8?q?os=20=EB=8F=84=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/package.json | 4 +- frontend/src/App.tsx | 10 +- frontend/src/api/schedule.ts | 29 +++++ .../ScheduleAddModal/ScheduleAddModal.tsx | 57 +++++----- frontend/src/constants/index.ts | 5 + frontend/src/mocks/handlers.ts | 19 +--- .../src/pages/CalendarPage/CalendarPage.tsx | 41 ++++--- frontend/yarn.lock | 105 ++++++++++++++++-- 8 files changed, 196 insertions(+), 74 deletions(-) create mode 100644 frontend/src/api/schedule.ts create mode 100644 frontend/src/constants/index.ts diff --git a/frontend/package.json b/frontend/package.json index e28fc200..6be5579c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,9 +16,11 @@ "dependencies": { "@emotion/react": "^11.9.3", "@emotion/styled": "^11.9.3", + "axios": "^0.27.2", "emotion-reset": "^3.0.1", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-query": "^3.39.1" }, "devDependencies": { "@babel/core": "^7.18.6", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 6ede00c8..d6d56ec9 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,7 +1,15 @@ +import { QueryClient, QueryClientProvider } from 'react-query'; + import CalendarPage from '@/pages/CalendarPage/CalendarPage'; +const queryClient = new QueryClient(); + function App() { - return ; + return ( + + + + ); } export default App; diff --git a/frontend/src/api/schedule.ts b/frontend/src/api/schedule.ts new file mode 100644 index 00000000..5915e00a --- /dev/null +++ b/frontend/src/api/schedule.ts @@ -0,0 +1,29 @@ +import axios from 'axios'; + +import { Schedule } from '@/@types'; + +const scheduleApi = { + endpoint: '/api/schedule', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + + get: async () => { + const response = await axios.get<{ schedules: Schedule[] }>(scheduleApi.endpoint, { + headers: scheduleApi.headers, + }); + + return response; + }, + + post: async (body: Omit) => { + const response = axios.post(scheduleApi.endpoint, body, { + headers: scheduleApi.headers, + }); + + return response; + }, +}; + +export default scheduleApi; diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index d9857373..13bee280 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -1,5 +1,6 @@ import { useRef } from 'react'; +import { useMutation } from 'react-query'; import { useTheme } from '@emotion/react'; import { Schedule } from '@/@types'; @@ -18,6 +19,8 @@ import { import Button from '../@common/Button/Button'; import FieldSet from '../@common/FieldSet/FieldSet'; +import scheduleApi from '@/api/schedule'; + interface ScheduleAddModalProps { closeModal: () => void; setSchedule: React.Dispatch>; @@ -26,6 +29,8 @@ interface ScheduleAddModalProps { function ScheduleAddModal({ closeModal, setSchedule }: ScheduleAddModalProps) { const theme = useTheme(); + const { isLoading, error, mutate: postSchedule } = useMutation(scheduleApi.post); + const inputRef = { title: useRef(null), startDateTime: useRef(null), @@ -40,44 +45,34 @@ function ScheduleAddModal({ closeModal, setSchedule }: ScheduleAddModalProps) { const handleSubmitScheduleAddForm = async (e: React.FormEvent) => { e.preventDefault(); - const isValidRef = Object.values(inputRef).every( - (inputRef) => inputRef.current instanceof HTMLInputElement + const [title, startDateTime, endDateTime, memo] = Object.values(inputRef).map( + (el) => el.current ); - if (!isValidRef) { + if ( + !(title instanceof HTMLInputElement) || + !(memo instanceof HTMLInputElement) || + !(startDateTime instanceof HTMLInputElement) || + !(endDateTime instanceof HTMLInputElement) + ) { return; } - const [title, startDateTime, endDateTime, memo] = Object.values(inputRef); - - const body = await JSON.stringify({ - title: title.current?.value, - startDateTime: startDateTime.current?.value, - endDateTime: endDateTime.current?.value, - memo: memo.current?.value, - }); - - await fetch('/api/schedules', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - }, - body, - }); - - setSchedule((prev) => [ - ...prev, - { - id: prev.length, - title: title.current?.value as string, - startDateTime: startDateTime.current?.value as string, - endDateTime: endDateTime.current?.value as string, - memo: memo.current?.value as string, - }, - ]); + const body = { + title: title.value, + startDateTime: startDateTime.value, + endDateTime: endDateTime.value, + memo: memo.value, + }; + + postSchedule(body); + setSchedule((prev) => [...prev, { id: prev.length, ...body }]); }; + if (isLoading) return <>Loading; + + if (error) return <>Error; + return (
diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts new file mode 100644 index 00000000..ef0c3a09 --- /dev/null +++ b/frontend/src/constants/index.ts @@ -0,0 +1,5 @@ +const CACHE_KEY = { + SCHEDULES: 'schedules', +}; + +export { CACHE_KEY }; diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 3cf53731..35b2fc8a 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -1,17 +1,10 @@ import { rest } from 'msw'; -interface PostScheduleReqBody { - title: string; - startDateTime: string; - endDateTime: string; - memo: string; -} +import { Schedule } from '@/@types'; -interface ScheduleResponse extends PostScheduleReqBody { - id: number; -} +import scheduleApi from '@/api/schedule'; -const scheduleDB: ScheduleResponse[] = [ +const scheduleDB: Schedule[] = [ { id: 1, title: '우테코 데모데이', @@ -29,14 +22,14 @@ const scheduleDB: ScheduleResponse[] = [ ]; const handlers = [ - rest.post('/api/schedules', (req, res, ctx) => { + rest.post>(scheduleApi.endpoint, (req, res, ctx) => { scheduleDB.push({ id: scheduleDB.length + 1, ...req.body }); return res(ctx.status(201)); }), - rest.get('/api/schedules', (req, res, ctx) => { - return res(ctx.status(200), ctx.json({ data: scheduleDB })); + rest.get(scheduleApi.endpoint, (req, res, ctx) => { + return res(ctx.status(200), ctx.json({ schedules: scheduleDB })); }), ]; diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index 0565f6e5..79219c54 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -1,4 +1,7 @@ -import { useEffect, useState } from 'react'; +import { useState } from 'react'; + +import { useQuery } from 'react-query'; +import { AxiosError, AxiosResponse } from 'axios'; import useModal from '@/hooks/useModal'; @@ -10,27 +13,31 @@ import ScheduleAddButton from '@/components/ScheduleAddButton/ScheduleAddButton' import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; import ScheduleAddModal from '@/components/ScheduleAddModal/ScheduleAddModal'; +import { CACHE_KEY } from '@/constants'; + +import scheduleApi from '@/api/schedule'; + function CalendarPage() { const [schedules, setSchedules] = useState([]); + const { isLoading, error } = useQuery, AxiosError>( + CACHE_KEY.SCHEDULES, + scheduleApi.get, + { + onSuccess: (data) => onSuccessGetSchedules(data), + } + ); const { isOpen, openModal, closeModal } = useModal(); - useEffect(() => { - const fetchSchedules = async () => { - const response = await fetch('/api/schedules', { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - }, - }); - const { data } = await response.json(); - - setSchedules(data); - }; - - fetchSchedules(); - }, []); + const onSuccessGetSchedules = (data: AxiosResponse<{ schedules: Schedule[] }>) => { + if (typeof data !== 'undefined') { + setSchedules(data.data.schedules); + } + }; + + if (isLoading) return <>Loading; + + if (error) return <>Error; return ( diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 80ab8d9c..bcbd32e5 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -1067,7 +1067,7 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.17.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.17.8", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580" integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ== @@ -3702,6 +3702,14 @@ autoprefixer@^9.8.6: postcss "^7.0.32" postcss-value-parser "^4.1.0" +axios@^0.27.2: + version "0.27.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972" + integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== + dependencies: + follow-redirects "^1.14.9" + form-data "^4.0.0" + babel-loader@^8.0.0, babel-loader@^8.2.5: version "8.2.5" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e" @@ -3854,7 +3862,7 @@ better-opn@^2.1.1: dependencies: open "^7.0.3" -big-integer@^1.6.7: +big-integer@^1.6.16, big-integer@^1.6.7: version "1.6.51" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== @@ -3990,6 +3998,20 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" +broadcast-channel@^3.4.1: + version "3.7.0" + resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-3.7.0.tgz#2dfa5c7b4289547ac3f6705f9c00af8723889937" + integrity sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg== + dependencies: + "@babel/runtime" "^7.7.2" + detect-node "^2.1.0" + js-sha3 "0.8.0" + microseconds "0.2.0" + nano-time "1.0.0" + oblivious-set "1.0.0" + rimraf "3.0.2" + unload "2.2.0" + brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -5073,7 +5095,7 @@ detab@2.0.4: dependencies: repeat-string "^1.5.4" -detect-node@^2.0.4: +detect-node@^2.0.4, detect-node@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== @@ -6035,7 +6057,7 @@ focus-lock@^0.8.0: dependencies: tslib "^1.9.3" -follow-redirects@^1.0.0: +follow-redirects@^1.0.0, follow-redirects@^1.14.9: version "1.15.1" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== @@ -6094,6 +6116,15 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + format@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" @@ -7494,6 +7525,11 @@ js-levenshtein@^1.1.6: resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== +js-sha3@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" @@ -7856,6 +7892,14 @@ markdown-escapes@^1.0.0: resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== +match-sorter@^6.0.2: + version "6.3.1" + resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.1.tgz#98cc37fda756093424ddf3cbc62bfe9c75b92bda" + integrity sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw== + dependencies: + "@babel/runtime" "^7.12.5" + remove-accents "0.4.2" + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -8014,6 +8058,11 @@ micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4: braces "^3.0.2" picomatch "^2.3.1" +microseconds@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39" + integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA== + miller-rabin@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" @@ -8236,6 +8285,13 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.16.0.tgz#664f43e45460fb98faf00edca0bb0d7b8dce7916" integrity sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA== +nano-time@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef" + integrity sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA== + dependencies: + big-integer "^1.6.16" + nanoid@^3.3.1, nanoid@^3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" @@ -8510,6 +8566,11 @@ objectorarray@^1.0.5: resolved "https://registry.yarnpkg.com/objectorarray/-/objectorarray-1.0.5.tgz#2c05248bbefabd8f43ad13b41085951aac5e68a5" integrity sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg== +oblivious-set@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/oblivious-set/-/oblivious-set-1.0.0.tgz#c8316f2c2fb6ff7b11b6158db3234c49f733c566" + integrity sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw== + obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -9459,6 +9520,15 @@ react-merge-refs@^1.0.0: resolved "https://registry.yarnpkg.com/react-merge-refs/-/react-merge-refs-1.1.0.tgz#73d88b892c6c68cbb7a66e0800faa374f4c38b06" integrity sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ== +react-query@^3.39.1: + version "3.39.1" + resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.39.1.tgz#3876c0fdac7a3b5a84e195534e5fa8fbdd628847" + integrity sha512-qYKT1bavdDiQZbngWZyPotlBVzcBjDYEJg5RQLBa++5Ix5jjfbEYJmHSZRZD+USVHUSvl/ey9Hu+QfF1QAK80A== + dependencies: + "@babel/runtime" "^7.5.5" + broadcast-channel "^3.4.1" + match-sorter "^6.0.2" + react-refresh@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" @@ -9723,6 +9793,11 @@ remark-squeeze-paragraphs@4.0.0: dependencies: mdast-squeeze-paragraphs "^4.0.0" +remove-accents@0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5" + integrity sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA== + remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -9845,6 +9920,13 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== +rimraf@3.0.2, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + rimraf@^2.5.4, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" @@ -9852,13 +9934,6 @@ rimraf@^2.5.4, rimraf@^2.6.3: dependencies: glob "^7.1.3" -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -11136,6 +11211,14 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== +unload@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7" + integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA== + dependencies: + "@babel/runtime" "^7.6.2" + detect-node "^2.0.4" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" From 79f4baa98534578c8d187c6b1463e8f8f145d69d Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 13 Jul 2022 15:09:54 +0900 Subject: [PATCH 0055/1011] =?UTF-8?q?chore:=20eslint=20react-hooks=20?= =?UTF-8?q?=EA=B7=9C=EC=B9=99=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/.eslintrc.json | 4 +++- frontend/package.json | 1 + frontend/yarn.lock | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index 65c6aa7c..c1e6f3c9 100644 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -1,6 +1,6 @@ { "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint", "prettier"], + "plugins": ["@typescript-eslint", "react-hooks", "prettier"], "extends": [ "plugin:react/recommended", "plugin:import/errors", @@ -11,6 +11,8 @@ ], "rules": { "react/react-in-jsx-scope": "off", + "react-hooks/rules-of-hooks": "error", + "react-hooks/exhaustive-deps": "warn", "import/named": "off", "import/no-unresolved": "off", "@typescript-eslint/no-var-requires": "off" diff --git a/frontend/package.json b/frontend/package.json index 6be5579c..bc46ff3c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -52,6 +52,7 @@ "eslint-plugin-import": "^2.26.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.30.1", + "eslint-plugin-react-hooks": "^4.6.0", "html-webpack-plugin": "^5.5.0", "msw": "^0.43.0", "prettier": "^2.7.1", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index bcbd32e5..1d5d3b04 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -5509,6 +5509,11 @@ eslint-plugin-prettier@^4.2.1: dependencies: prettier-linter-helpers "^1.0.0" +eslint-plugin-react-hooks@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" + integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== + eslint-plugin-react@^7.30.1: version "7.30.1" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz#2be4ab23ce09b5949c6631413ba64b2810fd3e22" From 7341092c4ea804feab3ca15dc44bd1b3b76d5be2 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 13 Jul 2022 15:18:01 +0900 Subject: [PATCH 0056/1011] =?UTF-8?q?feat:=20post=20request=20body=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=ED=95=A8=EC=88=98=20=EB=B6=84=EB=A6=AC=20?= =?UTF-8?q?=EB=B0=8F=20refetch=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/@types/index.ts | 6 ++- .../ScheduleAddModal/ScheduleAddModal.tsx | 50 +++++++++++-------- .../src/pages/CalendarPage/CalendarPage.tsx | 33 ++++++------ frontend/src/utils/index.ts | 22 ++++++++ 4 files changed, 71 insertions(+), 40 deletions(-) create mode 100644 frontend/src/utils/index.ts diff --git a/frontend/src/@types/index.ts b/frontend/src/@types/index.ts index ee73c148..a8b520df 100644 --- a/frontend/src/@types/index.ts +++ b/frontend/src/@types/index.ts @@ -1,3 +1,7 @@ +interface InputRef { + [index: string]: React.RefObject; +} + interface Schedule { id: number; title: string; @@ -6,4 +10,4 @@ interface Schedule { memo: string; } -export { Schedule }; +export { InputRef, Schedule }; diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index 13bee280..8e3fb786 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -1,7 +1,8 @@ import { useRef } from 'react'; -import { useMutation } from 'react-query'; +import { RefetchOptions, RefetchQueryFilters, useMutation, QueryObserverResult } from 'react-query'; import { useTheme } from '@emotion/react'; +import { AxiosError, AxiosResponse } from 'axios'; import { Schedule } from '@/@types'; @@ -19,17 +20,34 @@ import { import Button from '../@common/Button/Button'; import FieldSet from '../@common/FieldSet/FieldSet'; +import { createPostBody } from '@/utils'; + import scheduleApi from '@/api/schedule'; interface ScheduleAddModalProps { closeModal: () => void; - setSchedule: React.Dispatch>; + refetch: ( + options?: (RefetchOptions & RefetchQueryFilters) | undefined + ) => Promise, AxiosError>>; } -function ScheduleAddModal({ closeModal, setSchedule }: ScheduleAddModalProps) { +function ScheduleAddModal({ closeModal, refetch }: ScheduleAddModalProps) { const theme = useTheme(); - const { isLoading, error, mutate: postSchedule } = useMutation(scheduleApi.post); + const { + isLoading, + error, + mutate: postSchedule, + } = useMutation< + AxiosResponse<{ schedules: Schedule[] }>, + AxiosError, + Omit, + unknown + >(scheduleApi.post, { + onSuccess: () => { + onSuccessPostSchedule(); + }, + }); const inputRef = { title: useRef(null), @@ -45,28 +63,18 @@ function ScheduleAddModal({ closeModal, setSchedule }: ScheduleAddModalProps) { const handleSubmitScheduleAddForm = async (e: React.FormEvent) => { e.preventDefault(); - const [title, startDateTime, endDateTime, memo] = Object.values(inputRef).map( - (el) => el.current - ); + const body = createPostBody(inputRef); - if ( - !(title instanceof HTMLInputElement) || - !(memo instanceof HTMLInputElement) || - !(startDateTime instanceof HTMLInputElement) || - !(endDateTime instanceof HTMLInputElement) - ) { + if (!body) { return; } - const body = { - title: title.value, - startDateTime: startDateTime.value, - endDateTime: endDateTime.value, - memo: memo.value, - }; - postSchedule(body); - setSchedule((prev) => [...prev, { id: prev.length, ...body }]); + }; + + const onSuccessPostSchedule = () => { + refetch(); + closeModal(); }; if (isLoading) return <>Loading; diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index 79219c54..dbfc7526 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -1,5 +1,3 @@ -import { useState } from 'react'; - import { useQuery } from 'react-query'; import { AxiosError, AxiosResponse } from 'axios'; @@ -18,32 +16,31 @@ import { CACHE_KEY } from '@/constants'; import scheduleApi from '@/api/schedule'; function CalendarPage() { - const [schedules, setSchedules] = useState([]); - const { isLoading, error } = useQuery, AxiosError>( + const { + isLoading, + error, + data: schedulesGetResponse, + refetch: refetchSchedules, + } = useQuery, AxiosError>( CACHE_KEY.SCHEDULES, - scheduleApi.get, - { - onSuccess: (data) => onSuccessGetSchedules(data), - } + scheduleApi.get ); const { isOpen, openModal, closeModal } = useModal(); - const onSuccessGetSchedules = (data: AxiosResponse<{ schedules: Schedule[] }>) => { - if (typeof data !== 'undefined') { - setSchedules(data.data.schedules); - } - }; - - if (isLoading) return <>Loading; + if (isLoading || schedulesGetResponse === undefined) { + return <>Loading; + } - if (error) return <>Error; + if (error) { + return <>Error; + } return ( - + - + diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts new file mode 100644 index 00000000..80d7ce1a --- /dev/null +++ b/frontend/src/utils/index.ts @@ -0,0 +1,22 @@ +import { InputRef } from '@/@types'; + +function createPostBody(inputRef: InputRef) { + const inputElements = Object.values(inputRef).map((el) => el.current); + const isValidInputRefs = inputElements.every((el) => el instanceof HTMLInputElement); + + if (!isValidInputRefs) { + return; + } + + const inputRefKeys = Object.keys(inputRef); + + const body = inputRefKeys.reduce((acc: any, cur: number | string) => { + acc[cur] = (inputRef[cur].current as HTMLInputElement).value; + + return acc; + }, {}); + + return body; +} + +export { createPostBody }; From 90f5961b8ae0969b271a477c66055d6a23217b87 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 13 Jul 2022 15:30:07 +0900 Subject: [PATCH 0057/1011] =?UTF-8?q?fix:=20global=20font=20size=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/styles/GlobalStyle.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/styles/GlobalStyle.tsx b/frontend/src/styles/GlobalStyle.tsx index ac659cd8..63ee194e 100644 --- a/frontend/src/styles/GlobalStyle.tsx +++ b/frontend/src/styles/GlobalStyle.tsx @@ -16,7 +16,7 @@ const global = css` body { font-family: 'Pretendard', sans-serif; - font-size: 1rem; + font-size: 3rem; } `; From ec93524f3ea7e35c5251e5f8e5daab8f08d1e098 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Thu, 7 Jul 2022 13:44:42 +0900 Subject: [PATCH 0058/1011] =?UTF-8?q?feat:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=A0=9C=EB=AA=A9=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/schedule/domain/Schedule.java | 10 +++++++- .../exception/InvalidScheduleException.java | 12 ++++++++++ .../dallog/schedule/domain/ScheduleTest.java | 24 +++++++++++++++++-- 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/schedule/exception/InvalidScheduleException.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java index 9a5d8131..6c09e394 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java @@ -1,5 +1,6 @@ package com.allog.dallog.schedule.domain; +import com.allog.dallog.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; import javax.persistence.Column; import javax.persistence.Embedded; @@ -17,7 +18,7 @@ public class Schedule { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long Id; - @Column(nullable = false) + @Column(length = 20, nullable = false) private String title; @Embedded @@ -31,11 +32,18 @@ protected Schedule() { public Schedule(final String title, final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String memo) { + validateTitleLength(title); this.title = title; this.period = new Period(startDateTime, endDateTime); this.memo = memo; } + private void validateTitleLength(String title) { + if (title.length() > 20) { + throw new InvalidScheduleException("일정 제목의 길이는 20을 초과할 수 없습니다."); + } + } + public Long getId() { return Id; } diff --git a/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidScheduleException.java b/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidScheduleException.java new file mode 100644 index 00000000..590c0a43 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidScheduleException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.schedule.exception; + +public class InvalidScheduleException extends RuntimeException { + + public InvalidScheduleException() { + super("잘못된 일정입니다."); + } + + public InvalidScheduleException(final String message) { + super(message); + } +} diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java index 63a74f80..ca410979 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java @@ -1,9 +1,14 @@ package com.allog.dallog.schedule.domain; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import com.allog.dallog.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; public class ScheduleTest { @@ -17,6 +22,21 @@ public class ScheduleTest { String memo = "알록달록 팀회의 - 선릉 큰 강의실"; // when & then - Assertions.assertDoesNotThrow(() -> new Schedule(title, startDateTime, endDateTime, memo)); + assertDoesNotThrow(() -> new Schedule(title, startDateTime, endDateTime, memo)); + } + + @DisplayName("일정 제목의 길이가 20을 초과하는 경우 예외를 던진다.") + @ParameterizedTest + @ValueSource(strings = {"일이삼사오육칠팔구십일이삼사오육칠팔구십일", + "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 회의"}) + void 일정_제목의_길이가_20을_초과하는_경우_예외를_던진다(final String title) { + // given + LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); + LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); + String memo = "알록달록 팀회의 - 선릉 큰 강의실"; + + // when & then + assertThatThrownBy(() -> new Schedule(title, startDateTime, endDateTime, memo)) + .isInstanceOf(InvalidScheduleException.class); } } From 60d0ede4391e2f82c114a7ccb24c0bc9e7f81db0 Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 7 Jul 2022 13:57:07 +0900 Subject: [PATCH 0059/1011] =?UTF-8?q?feat:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EB=A9=94=EB=AA=A8=EC=9D=98=20=EA=B8=B8=EC=9D=B4=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 테스트 코드 추가 --- .../com/allog/dallog/schedule/domain/Schedule.java | 12 +++++++++++- .../allog/dallog/schedule/domain/ScheduleTest.java | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java index 6c09e394..eeaf8f7a 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java @@ -14,6 +14,9 @@ @Table(name = "SCHEDULES") public class Schedule { + private static final int MAX_TITLE_LENGTH = 20; + private static final int MAX_MEMO_LENGTH = 255; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long Id; @@ -33,17 +36,24 @@ protected Schedule() { public Schedule(final String title, final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String memo) { validateTitleLength(title); + validateMemoLength(memo); this.title = title; this.period = new Period(startDateTime, endDateTime); this.memo = memo; } private void validateTitleLength(String title) { - if (title.length() > 20) { + if (title.length() > MAX_TITLE_LENGTH) { throw new InvalidScheduleException("일정 제목의 길이는 20을 초과할 수 없습니다."); } } + private void validateMemoLength(String memo) { + if (memo.length() > MAX_MEMO_LENGTH) { + throw new InvalidScheduleException("일정 메모의 길이는 255를 초과할 수 없습니다."); + } + } + public Long getId() { return Id; } diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java index ca410979..4c7f6458 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java @@ -39,4 +39,18 @@ public class ScheduleTest { assertThatThrownBy(() -> new Schedule(title, startDateTime, endDateTime, memo)) .isInstanceOf(InvalidScheduleException.class); } + + @DisplayName("일정 메모의 길이가 255를 초과하는 경우 예외를 던진다.") + @Test + void 일정_메모의_길이가_255를_초과하는_경우_예외를_던진다() { + // given + String title = "알록달록 팀회의"; + LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); + LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); + String memo = "1".repeat(256); + + // when & then + assertThatThrownBy(() -> new Schedule(title, startDateTime, endDateTime, memo)) + .isInstanceOf(InvalidScheduleException.class); + } } From 2a24f6dc5fcbc5bbd421f762290e45612180b084 Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 7 Jul 2022 14:16:29 +0900 Subject: [PATCH 0060/1011] =?UTF-8?q?feat:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=A0=9C=EB=AA=A9=20=EC=9B=90=EC=8B=9C=EA=B0=92=EC=9D=84=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=EB=A1=9C=20=ED=8F=AC=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/schedule/domain/Period.java | 2 +- .../dallog/schedule/domain/Schedule.java | 16 +++------- .../allog/dallog/schedule/domain/Title.java | 32 +++++++++++++++++++ .../dallog/schedule/domain/ScheduleTest.java | 17 ---------- .../dallog/schedule/domain/TitleTest.java | 21 ++++++++++++ 5 files changed, 58 insertions(+), 30 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/schedule/domain/Title.java create mode 100644 backend/src/test/java/com/allog/dallog/schedule/domain/TitleTest.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java index 74ff349e..5d4d7d55 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java @@ -7,7 +7,7 @@ @Embeddable public class Period { - + @Column(nullable = false) private LocalDateTime startDateTime; diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java index eeaf8f7a..85dd17c4 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java @@ -14,15 +14,14 @@ @Table(name = "SCHEDULES") public class Schedule { - private static final int MAX_TITLE_LENGTH = 20; private static final int MAX_MEMO_LENGTH = 255; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long Id; - @Column(length = 20, nullable = false) - private String title; + @Embedded + private Title title; @Embedded private Period period; @@ -35,19 +34,12 @@ protected Schedule() { public Schedule(final String title, final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String memo) { - validateTitleLength(title); validateMemoLength(memo); - this.title = title; + this.title = new Title(title); this.period = new Period(startDateTime, endDateTime); this.memo = memo; } - private void validateTitleLength(String title) { - if (title.length() > MAX_TITLE_LENGTH) { - throw new InvalidScheduleException("일정 제목의 길이는 20을 초과할 수 없습니다."); - } - } - private void validateMemoLength(String memo) { if (memo.length() > MAX_MEMO_LENGTH) { throw new InvalidScheduleException("일정 메모의 길이는 255를 초과할 수 없습니다."); @@ -59,7 +51,7 @@ public Long getId() { } public String getTitle() { - return title; + return title.getValue(); } public LocalDateTime getStartDateTime() { diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Title.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Title.java new file mode 100644 index 00000000..f17afeb9 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Title.java @@ -0,0 +1,32 @@ +package com.allog.dallog.schedule.domain; + +import com.allog.dallog.schedule.exception.InvalidScheduleException; +import javax.persistence.Column; +import javax.persistence.Embeddable; + +@Embeddable +public class Title { + + private static final int MAX_TITLE_LENGTH = 20; + + @Column(name = "title", length = 20, nullable = false) + private String value; + + protected Title() { + } + + public Title(final String value) { + validateLength(value); + this.value = value; + } + + private void validateLength(final String value) { + if (value.length() > MAX_TITLE_LENGTH) { + throw new InvalidScheduleException("일정 제목의 길이는 20을 초과할 수 없습니다."); + } + } + + public String getValue() { + return value; + } +} diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java index 4c7f6458..2a398546 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java @@ -7,8 +7,6 @@ import java.time.LocalDateTime; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; public class ScheduleTest { @@ -25,21 +23,6 @@ public class ScheduleTest { assertDoesNotThrow(() -> new Schedule(title, startDateTime, endDateTime, memo)); } - @DisplayName("일정 제목의 길이가 20을 초과하는 경우 예외를 던진다.") - @ParameterizedTest - @ValueSource(strings = {"일이삼사오육칠팔구십일이삼사오육칠팔구십일", - "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 회의"}) - void 일정_제목의_길이가_20을_초과하는_경우_예외를_던진다(final String title) { - // given - LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); - LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); - String memo = "알록달록 팀회의 - 선릉 큰 강의실"; - - // when & then - assertThatThrownBy(() -> new Schedule(title, startDateTime, endDateTime, memo)) - .isInstanceOf(InvalidScheduleException.class); - } - @DisplayName("일정 메모의 길이가 255를 초과하는 경우 예외를 던진다.") @Test void 일정_메모의_길이가_255를_초과하는_경우_예외를_던진다() { diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/TitleTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/TitleTest.java new file mode 100644 index 00000000..e657b11e --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/TitleTest.java @@ -0,0 +1,21 @@ +package com.allog.dallog.schedule.domain; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.allog.dallog.schedule.exception.InvalidScheduleException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class TitleTest { + + @DisplayName("일정 제목의 길이가 20을 초과하는 경우 예외를 던진다.") + @ParameterizedTest + @ValueSource(strings = {"일이삼사오육칠팔구십일이삼사오육칠팔구십일", + "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 회의"}) + void 일정_제목의_길이가_20을_초과하는_경우_예외를_던진다(final String title) { + // when & then + assertThatThrownBy(() -> new Title(title)) + .isInstanceOf(InvalidScheduleException.class); + } +} From 9d1739dc79caffa0ca6a6a0518171474bc82eb05 Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 7 Jul 2022 14:43:57 +0900 Subject: [PATCH 0061/1011] =?UTF-8?q?feat:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EB=A9=94=EB=AA=A8=20=EC=9B=90=EC=8B=9C=EA=B0=92=EC=9D=84=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=EB=A1=9C=20=ED=8F=AC=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: leaver --- .../allog/dallog/schedule/domain/Memo.java | 32 +++++++++++++++++++ .../dallog/schedule/domain/Schedule.java | 23 ++++--------- .../dallog/schedule/domain/MemoTest.java | 21 ++++++++++++ .../dallog/schedule/domain/ScheduleTest.java | 16 ---------- 4 files changed, 59 insertions(+), 33 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/schedule/domain/Memo.java create mode 100644 backend/src/test/java/com/allog/dallog/schedule/domain/MemoTest.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Memo.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Memo.java new file mode 100644 index 00000000..5fce690c --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Memo.java @@ -0,0 +1,32 @@ +package com.allog.dallog.schedule.domain; + +import com.allog.dallog.schedule.exception.InvalidScheduleException; +import javax.persistence.Column; +import javax.persistence.Embeddable; + +@Embeddable +public class Memo { + + private static final int MAX_MEMO_LENGTH = 255; + + @Column(name = "memo", nullable = false) + private String value; + + protected Memo() { + } + + public Memo(final String value) { + validateLength(value); + this.value = value; + } + + private void validateLength(final String memo) { + if (memo.length() > MAX_MEMO_LENGTH) { + throw new InvalidScheduleException("일정 메모의 길이는 255를 초과할 수 없습니다."); + } + } + + public String getValue() { + return value; + } +} diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java index 85dd17c4..9cd0d22d 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java @@ -1,8 +1,6 @@ package com.allog.dallog.schedule.domain; -import com.allog.dallog.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; -import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -14,11 +12,9 @@ @Table(name = "SCHEDULES") public class Schedule { - private static final int MAX_MEMO_LENGTH = 255; - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long Id; + private Long id; @Embedded private Title title; @@ -26,28 +22,21 @@ public class Schedule { @Embedded private Period period; - @Column(nullable = false) - private String memo; + @Embedded + private Memo memo; protected Schedule() { } public Schedule(final String title, final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String memo) { - validateMemoLength(memo); this.title = new Title(title); this.period = new Period(startDateTime, endDateTime); - this.memo = memo; - } - - private void validateMemoLength(String memo) { - if (memo.length() > MAX_MEMO_LENGTH) { - throw new InvalidScheduleException("일정 메모의 길이는 255를 초과할 수 없습니다."); - } + this.memo = new Memo(memo); } public Long getId() { - return Id; + return id; } public String getTitle() { @@ -63,6 +52,6 @@ public LocalDateTime getEndDateTime() { } public String getMemo() { - return memo; + return memo.getValue(); } } diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/MemoTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/MemoTest.java new file mode 100644 index 00000000..40fddb31 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/MemoTest.java @@ -0,0 +1,21 @@ +package com.allog.dallog.schedule.domain; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.allog.dallog.schedule.exception.InvalidScheduleException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class MemoTest { + + @DisplayName("일정 메모의 길이가 255를 초과하는 경우 예외를 던진다.") + @Test + void 일정_메모의_길이가_255를_초과하는_경우_예외를_던진다() { + // given + String memo = "1".repeat(256); + + // when & then + assertThatThrownBy(() -> new Memo(memo)) + .isInstanceOf(InvalidScheduleException.class); + } +} diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java index 2a398546..b05aab30 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java @@ -1,9 +1,7 @@ package com.allog.dallog.schedule.domain; -import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import com.allog.dallog.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -22,18 +20,4 @@ public class ScheduleTest { // when & then assertDoesNotThrow(() -> new Schedule(title, startDateTime, endDateTime, memo)); } - - @DisplayName("일정 메모의 길이가 255를 초과하는 경우 예외를 던진다.") - @Test - void 일정_메모의_길이가_255를_초과하는_경우_예외를_던진다() { - // given - String title = "알록달록 팀회의"; - LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); - LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); - String memo = "1".repeat(256); - - // when & then - assertThatThrownBy(() -> new Schedule(title, startDateTime, endDateTime, memo)) - .isInstanceOf(InvalidScheduleException.class); - } } From 001ee27be33601b4442da0442a701475a2978a0a Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 7 Jul 2022 14:56:13 +0900 Subject: [PATCH 0062/1011] =?UTF-8?q?refactor:=20InvalidPeriodException=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/schedule/domain/Period.java | 6 +++--- .../schedule/exception/InvalidPeriodException.java | 12 ------------ .../com/allog/dallog/schedule/domain/PeriodTest.java | 5 ++--- 3 files changed, 5 insertions(+), 18 deletions(-) delete mode 100644 backend/src/main/java/com/allog/dallog/schedule/exception/InvalidPeriodException.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java index 5d4d7d55..1339a59e 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java @@ -1,13 +1,13 @@ package com.allog.dallog.schedule.domain; -import com.allog.dallog.schedule.exception.InvalidPeriodException; +import com.allog.dallog.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; import javax.persistence.Column; import javax.persistence.Embeddable; @Embeddable public class Period { - + @Column(nullable = false) private LocalDateTime startDateTime; @@ -26,7 +26,7 @@ public Period(final LocalDateTime startDateTime, final LocalDateTime endDateTime private void validate(final LocalDateTime startDateTime, final LocalDateTime endDateTime) { if (startDateTime.isAfter(endDateTime)) { - throw new InvalidPeriodException("종료일시가 시작일시보다 이전일 수 없습니다."); + throw new InvalidScheduleException("종료일시가 시작일시보다 이전일 수 없습니다."); } } diff --git a/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidPeriodException.java b/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidPeriodException.java deleted file mode 100644 index 7c9d5c9d..00000000 --- a/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidPeriodException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.allog.dallog.schedule.exception; - -public class InvalidPeriodException extends RuntimeException { - - public InvalidPeriodException() { - super("잘못된 기간입니다."); - } - - public InvalidPeriodException(final String message) { - super(message); - } -} diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java index 46e6d2bf..7c4e6eb7 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java @@ -2,7 +2,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.allog.dallog.schedule.exception.InvalidPeriodException; +import com.allog.dallog.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -18,7 +18,6 @@ class PeriodTest { // when & then assertThatThrownBy(() -> new Period(startDateTime, endDateTime)) - .isInstanceOf(InvalidPeriodException.class) - .hasMessage("종료일시가 시작일시보다 이전일 수 없습니다."); + .isInstanceOf(InvalidScheduleException.class); } } From f892bdc3a3f0b04200a6933a01e0ae074053bd01 Mon Sep 17 00:00:00 2001 From: koo Date: Mon, 11 Jul 2022 21:08:18 +0900 Subject: [PATCH 0063/1011] =?UTF-8?q?test:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=EA=B8=B0=EB=8A=A5=20=EC=97=A3=EC=A7=80=20?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=8A=A4=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/ScheduleRepositoryTest.java | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java index e19339f8..a3605d33 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java @@ -36,4 +36,114 @@ class ScheduleRepositoryTest { // then assertThat(schedules).hasSize(1); } + + @DisplayName("시작일시와 종료일시를 전달할 때 일정의 시작날짜가 시작일시와 같으면 조회된다.") + @Test + void 시작일시와_종료일시를_전달할_때_일정의_시작날짜가_시작일시와_같으면_조회된다() { + // given + Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 7, 1, 0, 0), + LocalDateTime.of(2022, 7, 15, 16, 20), "달록"); + Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), + LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + + scheduleRepository.save(schedule1); + scheduleRepository.save(schedule2); + + LocalDateTime startDate = LocalDateTime.of(2022, 7, 1, 0, 0); + LocalDateTime endDate = LocalDateTime.of(2022, 7, 31, 0, 0); + + // when + List schedules = scheduleRepository.findByBetween(startDate, endDate); + + // then + assertThat(schedules).hasSize(1); + } + + @DisplayName("시작일시와 종료일시를 전달할 때 일정의 시작날짜가 종료일시와 같으면 조회된다.") + @Test + void 시작일시와_종료일시를_전달할_때_일정의_시작날짜가_종료일시와_같으면_조회된다() { + // given + Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 7, 31, 0, 0), + LocalDateTime.of(2022, 8, 12, 13, 10), "달록"); + Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), + LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + + scheduleRepository.save(schedule1); + scheduleRepository.save(schedule2); + + LocalDateTime startDate = LocalDateTime.of(2022, 7, 1, 0, 0); + LocalDateTime endDate = LocalDateTime.of(2022, 7, 31, 0, 0); + + // when + List schedules = scheduleRepository.findByBetween(startDate, endDate); + + // then + assertThat(schedules).hasSize(1); + } + + @DisplayName("시작일시와 종료일시를 전달할 때 일정의 시작날짜가 종료일시 이후이면 조회되지 않는다.") + @Test + void 시작일시와_종료일시를_전달할_때_일정의_시작날짜가_종료일시_이후이면_조회되지_않는다() { + // given + Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 7, 31, 0, 1), + LocalDateTime.of(2022, 8, 12, 13, 10), "달록"); + Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), + LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + + scheduleRepository.save(schedule1); + scheduleRepository.save(schedule2); + + LocalDateTime startDate = LocalDateTime.of(2022, 7, 1, 0, 0); + LocalDateTime endDate = LocalDateTime.of(2022, 7, 31, 0, 0); + + // when + List schedules = scheduleRepository.findByBetween(startDate, endDate); + + // then + assertThat(schedules).hasSize(0); + } + + @DisplayName("시작일시와 종료일시를 전달할 때 일정의 종료날짜가 시작일시와 같으면 조회된다.") + @Test + void 시작일시와_종료일시를_전달할_때_일정의_종료날짜가_시작일시와_같으면_조회된다() { + // given + Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 6, 12, 13, 40), + LocalDateTime.of(2022, 7, 1, 0, 0), "달록"); + Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), + LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + + scheduleRepository.save(schedule1); + scheduleRepository.save(schedule2); + + LocalDateTime startDate = LocalDateTime.of(2022, 7, 1, 0, 0); + LocalDateTime endDate = LocalDateTime.of(2022, 7, 31, 0, 0); + + // when + List schedules = scheduleRepository.findByBetween(startDate, endDate); + + // then + assertThat(schedules).hasSize(1); + } + + @DisplayName("시작일시와 종료일시를 전달할 때 일정의 종료날짜가 시작일시 이전이면 조회되지 않는다.") + @Test + void 시작일시와_종료일시를_전달할_때_일정의_종료날짜가_시작일시_이전이면_조회되지_않는다() { + // given + Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 6, 12, 13, 40), + LocalDateTime.of(2022, 6, 30, 23, 59), "달록"); + Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), + LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + + scheduleRepository.save(schedule1); + scheduleRepository.save(schedule2); + + LocalDateTime startDate = LocalDateTime.of(2022, 7, 1, 0, 0); + LocalDateTime endDate = LocalDateTime.of(2022, 7, 31, 0, 0); + + // when + List schedules = scheduleRepository.findByBetween(startDate, endDate); + + // then + assertThat(schedules).hasSize(0); + } } From c5d85812e7b12769bc9ec88e1dc2b017ed27079e Mon Sep 17 00:00:00 2001 From: koo Date: Mon, 11 Jul 2022 21:08:50 +0900 Subject: [PATCH 0064/1011] =?UTF-8?q?test:=20ScheduleService=EC=97=90=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EB=93=B1=EB=A1=9D=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../schedule/service/ScheduleServiceTest.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java index 999ede41..9fe2be6f 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java @@ -1,9 +1,11 @@ package com.allog.dallog.schedule.service; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; import com.allog.dallog.schedule.dto.response.ScheduleResponse; +import com.allog.dallog.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; import java.util.List; import org.junit.jupiter.api.DisplayName; @@ -36,6 +38,57 @@ class ScheduleServiceTest { assertThat(id).isNotNull(); } + @DisplayName("새로운 일정을 생성 할 떄 일정 제목의 길이가 20을 초과하는 경우 예외를 던진다.") + @Test + void 새로운_일정을_생성_할_때_일정_제목의_길이가_20을_초과하는_경우_예외를_던진다() { + // given + String title = "일이삼사오육칠팔구십일이삼사오육칠팔구십일"; + LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); + LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); + String memo = "알록달록 팀회의 - 선릉 큰 강의실"; + + ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, + startDateTime, endDateTime, memo); + + // when & then + assertThatThrownBy(() -> scheduleService.save(scheduleCreateRequest)). + isInstanceOf(InvalidScheduleException.class); + } + + @DisplayName("새로운 일정을 생성 할 떄 일정 메모의 길이가 255를 초과하는 경우 예외를 던진다.") + @Test + void 새로운_일정을_생성_할_때_일정_메모의_길이가_255를_초과하는_경우_예외를_던진다() { + // given + String title = "알록달록 회의"; + LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); + LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); + String memo = "1".repeat(256); + + ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, + startDateTime, endDateTime, memo); + + // when & then + assertThatThrownBy(() -> scheduleService.save(scheduleCreateRequest)). + isInstanceOf(InvalidScheduleException.class); + } + + @DisplayName("새로운 일정을 생성 할 떄 종료일시가 시작일시 이전이라면 예외를 던진다.") + @Test + void 새로운_일정을_생성_할_때_종료일시가_시작일시_이전이라면_예외를_던진다() { + // given + String title = "알록달록 회의"; + LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 7, 12, 30); + LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); + String memo = "1".repeat(256); + + ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, + startDateTime, endDateTime, memo); + + // when & then + assertThatThrownBy(() -> scheduleService.save(scheduleCreateRequest)). + isInstanceOf(InvalidScheduleException.class); + } + @DisplayName("연도와 월을 전달받아 해당 월에 해당하는 일정 목록을 가져온다.") @Test void 연도와_월을_전달받아_해당_월에_해당하는_일정_목록을_가져온다() { From b8df926bc2ac358e8eb8b8c0a7ee09c430539432 Mon Sep 17 00:00:00 2001 From: koo Date: Mon, 11 Jul 2022 21:09:08 +0900 Subject: [PATCH 0065/1011] =?UTF-8?q?refactor:=20SchedulesAcceptanceTest?= =?UTF-8?q?=EC=9D=98=20=EC=9B=94=EB=B3=84=20=EC=9D=BC=EC=A0=95=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EC=9D=B8=EC=88=98=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/acceptance/SchedulesAcceptanceTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java index 3b8aaf1d..422c358f 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java @@ -32,9 +32,9 @@ class SchedulesAcceptanceTest extends AcceptanceTest { 상태코드_201이_반환된다(response); } - @DisplayName("월별 일정정보를 조회한다.") + @DisplayName("월별 일정정보를 조회하면 상태코드 200을 반환한다.") @Test - void 월별_일정정보를_조회한다() { + void 월별_일정정보를_조회하면_상태코드_200을_반환한다() { // given int year = 2022; int month = 7; From 6a12ac1d923c713013fd87cae6d3c0cb9dcfe7ff Mon Sep 17 00:00:00 2001 From: koo Date: Wed, 13 Jul 2022 11:13:16 +0900 Subject: [PATCH 0066/1011] =?UTF-8?q?refactor:=20Schedule=EC=9D=98=20?= =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20VO=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Schedule의 Title, Memo VO객체 제거 --- .../dallog/schedule/domain/Schedule.java | 35 ++++++++++++++----- .../dallog/schedule/domain/MemoTest.java | 21 ----------- .../dallog/schedule/domain/ScheduleTest.java | 34 ++++++++++++++++++ .../dallog/schedule/domain/TitleTest.java | 21 ----------- 4 files changed, 61 insertions(+), 50 deletions(-) delete mode 100644 backend/src/test/java/com/allog/dallog/schedule/domain/MemoTest.java delete mode 100644 backend/src/test/java/com/allog/dallog/schedule/domain/TitleTest.java diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java index 9cd0d22d..65701440 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java @@ -1,6 +1,8 @@ package com.allog.dallog.schedule.domain; +import com.allog.dallog.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; +import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -12,27 +14,44 @@ @Table(name = "SCHEDULES") public class Schedule { + private static final int MAX_TITLE_LENGTH = 20; + private static final int MAX_MEMO_LENGTH = 255; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Embedded - private Title title; + @Column(name = "TITLE", nullable = false) + private String title; @Embedded private Period period; - @Embedded - private Memo memo; + @Column(name = "MEMO", nullable = false) + private String memo; protected Schedule() { } public Schedule(final String title, final LocalDateTime startDateTime, final LocalDateTime endDateTime, final String memo) { - this.title = new Title(title); + validateTitleLength(title); + validateMemoLength(memo); + this.title = title; this.period = new Period(startDateTime, endDateTime); - this.memo = new Memo(memo); + this.memo = memo; + } + + private void validateTitleLength(final String title) { + if (title.length() > MAX_TITLE_LENGTH) { + throw new InvalidScheduleException("일정 제목의 길이는 20을 초과할 수 없습니다."); + } + } + + private void validateMemoLength(final String memo) { + if (memo.length() > MAX_MEMO_LENGTH) { + throw new InvalidScheduleException("일정 메모의 길이는 255를 초과할 수 없습니다."); + } } public Long getId() { @@ -40,7 +59,7 @@ public Long getId() { } public String getTitle() { - return title.getValue(); + return title; } public LocalDateTime getStartDateTime() { @@ -52,6 +71,6 @@ public LocalDateTime getEndDateTime() { } public String getMemo() { - return memo.getValue(); + return memo; } } diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/MemoTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/MemoTest.java deleted file mode 100644 index 40fddb31..00000000 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/MemoTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.allog.dallog.schedule.domain; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import com.allog.dallog.schedule.exception.InvalidScheduleException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -class MemoTest { - - @DisplayName("일정 메모의 길이가 255를 초과하는 경우 예외를 던진다.") - @Test - void 일정_메모의_길이가_255를_초과하는_경우_예외를_던진다() { - // given - String memo = "1".repeat(256); - - // when & then - assertThatThrownBy(() -> new Memo(memo)) - .isInstanceOf(InvalidScheduleException.class); - } -} diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java index b05aab30..42c95e53 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java @@ -1,10 +1,14 @@ package com.allog.dallog.schedule.domain; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import com.allog.dallog.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; public class ScheduleTest { @@ -20,4 +24,34 @@ public class ScheduleTest { // when & then assertDoesNotThrow(() -> new Schedule(title, startDateTime, endDateTime, memo)); } + + @DisplayName("일정 제목의 길이가 20을 초과하는 경우 예외를 던진다.") + @ParameterizedTest + @ValueSource(strings = {"일이삼사오육칠팔구십일이삼사오육칠팔구십일", + "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 회의"}) + void 일정_제목의_길이가_20을_초과하는_경우_예외를_던진다(final String title) { + //given + String titleForSave = title; + LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); + LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); + String memo = "알록달록 팀회의 - 선릉 큰 강의실"; + + // when & then + assertThatThrownBy(() -> new Schedule(titleForSave, startDateTime, endDateTime, memo)) + .isInstanceOf(InvalidScheduleException.class); + } + + @DisplayName("일정 메모의 길이가 255를 초과하는 경우 예외를 던진다.") + @Test + void 일정_메모의_길이가_255를_초과하는_경우_예외를_던진다() { + // given + String title = "알록달록 회의"; + LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); + LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); + String memo = "1".repeat(256); + + // when & then + assertThatThrownBy(() -> new Schedule(title, startDateTime, endDateTime, memo)) + .isInstanceOf(InvalidScheduleException.class); + } } diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/TitleTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/TitleTest.java deleted file mode 100644 index e657b11e..00000000 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/TitleTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.allog.dallog.schedule.domain; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -import com.allog.dallog.schedule.exception.InvalidScheduleException; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -class TitleTest { - - @DisplayName("일정 제목의 길이가 20을 초과하는 경우 예외를 던진다.") - @ParameterizedTest - @ValueSource(strings = {"일이삼사오육칠팔구십일이삼사오육칠팔구십일", - "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 회의"}) - void 일정_제목의_길이가_20을_초과하는_경우_예외를_던진다(final String title) { - // when & then - assertThatThrownBy(() -> new Title(title)) - .isInstanceOf(InvalidScheduleException.class); - } -} From 58c630505be11029dd459372eb0dce7a213874c4 Mon Sep 17 00:00:00 2001 From: koo Date: Wed, 13 Jul 2022 11:20:05 +0900 Subject: [PATCH 0067/1011] =?UTF-8?q?refactor:=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=EC=9D=98=20=EA=B5=AC=EA=B8=80=20?= =?UTF-8?q?=EC=BB=A8=EB=B2=A4=EC=85=98=EC=9D=84=20=EC=9A=B0=ED=85=8C?= =?UTF-8?q?=EC=BD=94=20=EC=BB=A8=EB=B2=A4=EC=85=98=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/DallogApplication.java | 6 ++-- .../controller/ScheduleController.java | 4 +-- .../allog/dallog/schedule/domain/Memo.java | 32 ------------------- .../allog/dallog/schedule/domain/Period.java | 1 - .../dallog/schedule/domain/Schedule.java | 4 +-- .../allog/dallog/schedule/domain/Title.java | 32 ------------------- .../dto/request/ScheduleCreateRequest.java | 4 +-- .../dto/response/ScheduleResponse.java | 4 +-- .../schedule/service/ScheduleService.java | 9 +++--- .../acceptance/SchedulesAcceptanceTest.java | 27 ++++++++-------- .../domain/ScheduleRepositoryTest.java | 24 +++++++------- .../schedule/service/ScheduleServiceTest.java | 29 ++++++++--------- 12 files changed, 54 insertions(+), 122 deletions(-) delete mode 100644 backend/src/main/java/com/allog/dallog/schedule/domain/Memo.java delete mode 100644 backend/src/main/java/com/allog/dallog/schedule/domain/Title.java diff --git a/backend/src/main/java/com/allog/dallog/DallogApplication.java b/backend/src/main/java/com/allog/dallog/DallogApplication.java index 12175e2c..b8454e11 100644 --- a/backend/src/main/java/com/allog/dallog/DallogApplication.java +++ b/backend/src/main/java/com/allog/dallog/DallogApplication.java @@ -6,8 +6,8 @@ @SpringBootApplication public class DallogApplication { - public static void main(String[] args) { - SpringApplication.run(DallogApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(DallogApplication.class, args); + } } diff --git a/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java b/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java index fd38c5e2..1221bae6 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java +++ b/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java @@ -32,8 +32,8 @@ public ResponseEntity save(@Valid @RequestBody final ScheduleCreateRequest } @GetMapping - public ResponseEntity> findByYearAndMonth( - @RequestParam final int year, @RequestParam final int month) { + public ResponseEntity> findByYearAndMonth(@RequestParam final int year, + @RequestParam final int month) { List responses = scheduleService.findByYearAndMonth(year, month); return ResponseEntity.ok(new ListResponse<>(responses)); } diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Memo.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Memo.java deleted file mode 100644 index 5fce690c..00000000 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Memo.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.allog.dallog.schedule.domain; - -import com.allog.dallog.schedule.exception.InvalidScheduleException; -import javax.persistence.Column; -import javax.persistence.Embeddable; - -@Embeddable -public class Memo { - - private static final int MAX_MEMO_LENGTH = 255; - - @Column(name = "memo", nullable = false) - private String value; - - protected Memo() { - } - - public Memo(final String value) { - validateLength(value); - this.value = value; - } - - private void validateLength(final String memo) { - if (memo.length() > MAX_MEMO_LENGTH) { - throw new InvalidScheduleException("일정 메모의 길이는 255를 초과할 수 없습니다."); - } - } - - public String getValue() { - return value; - } -} diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java index 1339a59e..cb9c890a 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java @@ -19,7 +19,6 @@ protected Period() { public Period(final LocalDateTime startDateTime, final LocalDateTime endDateTime) { validate(startDateTime, endDateTime); - this.startDateTime = startDateTime; this.endDateTime = endDateTime; } diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java index 65701440..5e8819d5 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java @@ -33,8 +33,8 @@ public class Schedule { protected Schedule() { } - public Schedule(final String title, final LocalDateTime startDateTime, - final LocalDateTime endDateTime, final String memo) { + public Schedule(final String title, final LocalDateTime startDateTime, final LocalDateTime endDateTime, + final String memo) { validateTitleLength(title); validateMemoLength(memo); this.title = title; diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Title.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Title.java deleted file mode 100644 index f17afeb9..00000000 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Title.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.allog.dallog.schedule.domain; - -import com.allog.dallog.schedule.exception.InvalidScheduleException; -import javax.persistence.Column; -import javax.persistence.Embeddable; - -@Embeddable -public class Title { - - private static final int MAX_TITLE_LENGTH = 20; - - @Column(name = "title", length = 20, nullable = false) - private String value; - - protected Title() { - } - - public Title(final String value) { - validateLength(value); - this.value = value; - } - - private void validateLength(final String value) { - if (value.length() > MAX_TITLE_LENGTH) { - throw new InvalidScheduleException("일정 제목의 길이는 20을 초과할 수 없습니다."); - } - } - - public String getValue() { - return value; - } -} diff --git a/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java b/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java index a7535e57..75fa5a8c 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java +++ b/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java @@ -22,8 +22,8 @@ public class ScheduleCreateRequest { private ScheduleCreateRequest() { } - public ScheduleCreateRequest(final String title, final LocalDateTime startDateTime, - final LocalDateTime endDateTime, final String memo) { + public ScheduleCreateRequest(final String title, final LocalDateTime startDateTime, final LocalDateTime endDateTime, + final String memo) { this.title = title; this.startDateTime = startDateTime; this.endDateTime = endDateTime; diff --git a/backend/src/main/java/com/allog/dallog/schedule/dto/response/ScheduleResponse.java b/backend/src/main/java/com/allog/dallog/schedule/dto/response/ScheduleResponse.java index 8410afb1..554e807b 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/dto/response/ScheduleResponse.java +++ b/backend/src/main/java/com/allog/dallog/schedule/dto/response/ScheduleResponse.java @@ -13,11 +13,11 @@ public class ScheduleResponse { public ScheduleResponse(final Schedule schedule) { this(schedule.getId(), schedule.getTitle(), schedule.getStartDateTime(), - schedule.getEndDateTime(), schedule.getMemo()); + schedule.getEndDateTime(), schedule.getMemo()); } public ScheduleResponse(final Long id, final String title, final LocalDateTime startDateTime, - final LocalDateTime endDateTime, final String memo) { + final LocalDateTime endDateTime, final String memo) { this.id = id; this.title = title; this.startDateTime = startDateTime; diff --git a/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java b/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java index cfee72d6..3dacce1b 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java +++ b/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java @@ -32,12 +32,11 @@ public List findByYearAndMonth(int year, int month) { LocalDate startDate = LocalDate.of(year, month, 1); LocalDate endDate = startDate.plusDays(startDate.lengthOfMonth()); - List schedules = scheduleRepository.findByBetween( - LocalDateTime.of(startDate, LocalTime.MIN), - LocalDateTime.of(endDate, LocalTime.MIN)); + List schedules = scheduleRepository.findByBetween(LocalDateTime.of(startDate, LocalTime.MIN), + LocalDateTime.of(endDate, LocalTime.MIN)); return schedules.stream() - .map(ScheduleResponse::new) - .collect(Collectors.toList()); + .map(ScheduleResponse::new) + .collect(Collectors.toList()); } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java index 422c358f..30449938 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java @@ -25,8 +25,7 @@ class SchedulesAcceptanceTest extends AcceptanceTest { String memo = "알록달록 회의가 있어요"; // given & when - ExtractableResponse response = 새로운_일정을_등록한다(title, startDateTime, endDateTime, - memo); + ExtractableResponse response = 새로운_일정을_등록한다(title, startDateTime, endDateTime, memo); // then 상태코드_201이_반환된다(response); @@ -49,8 +48,8 @@ class SchedulesAcceptanceTest extends AcceptanceTest { 상태코드_200이_반환된다(response); } - private ExtractableResponse 새로운_일정을_등록한다(final String title, - final String startDateTime, final String endDateTime, final String memo) { + private ExtractableResponse 새로운_일정을_등록한다(final String title, final String startDateTime, + final String endDateTime, final String memo) { Map params = new HashMap<>(); params.put("title", title); params.put("startDateTime", startDateTime); @@ -58,25 +57,25 @@ class SchedulesAcceptanceTest extends AcceptanceTest { params.put("memo", memo); return RestAssured.given().log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(params) - .when().post("/api/schedules") - .then().log().all() - .extract(); + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(params) + .when().post("/api/schedules") + .then().log().all() + .extract(); } private ExtractableResponse 월별_일정을_조회한다(final int year, final int month) { return RestAssured.given().log().all() - .when().get("/api/schedules?year={year}&month={month}", year, month) - .then().log().all() - .extract(); + .when().get("/api/schedules?year={year}&month={month}", year, month) + .then().log().all() + .extract(); } - private void 상태코드_200이_반환된다(ExtractableResponse response) { + private void 상태코드_200이_반환된다(final ExtractableResponse response) { assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); } - private void 상태코드_201이_반환된다(ExtractableResponse response) { + private void 상태코드_201이_반환된다(final ExtractableResponse response) { assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); } } diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java index a3605d33..0e4ac470 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java @@ -20,9 +20,9 @@ class ScheduleRepositoryTest { void 시작일시와_종료일시를_전달하면_그_사이에_해당하는_일정을_조회한다() { // given Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 7, 15, 14, 20), - LocalDateTime.of(2022, 7, 15, 16, 20), "달록"); + LocalDateTime.of(2022, 7, 15, 16, 20), "달록"); Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), - LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); scheduleRepository.save(schedule1); scheduleRepository.save(schedule2); @@ -42,9 +42,9 @@ class ScheduleRepositoryTest { void 시작일시와_종료일시를_전달할_때_일정의_시작날짜가_시작일시와_같으면_조회된다() { // given Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 7, 1, 0, 0), - LocalDateTime.of(2022, 7, 15, 16, 20), "달록"); + LocalDateTime.of(2022, 7, 15, 16, 20), "달록"); Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), - LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); scheduleRepository.save(schedule1); scheduleRepository.save(schedule2); @@ -64,9 +64,9 @@ class ScheduleRepositoryTest { void 시작일시와_종료일시를_전달할_때_일정의_시작날짜가_종료일시와_같으면_조회된다() { // given Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 7, 31, 0, 0), - LocalDateTime.of(2022, 8, 12, 13, 10), "달록"); + LocalDateTime.of(2022, 8, 12, 13, 10), "달록"); Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), - LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); scheduleRepository.save(schedule1); scheduleRepository.save(schedule2); @@ -86,9 +86,9 @@ class ScheduleRepositoryTest { void 시작일시와_종료일시를_전달할_때_일정의_시작날짜가_종료일시_이후이면_조회되지_않는다() { // given Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 7, 31, 0, 1), - LocalDateTime.of(2022, 8, 12, 13, 10), "달록"); + LocalDateTime.of(2022, 8, 12, 13, 10), "달록"); Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), - LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); scheduleRepository.save(schedule1); scheduleRepository.save(schedule2); @@ -108,9 +108,9 @@ class ScheduleRepositoryTest { void 시작일시와_종료일시를_전달할_때_일정의_종료날짜가_시작일시와_같으면_조회된다() { // given Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 6, 12, 13, 40), - LocalDateTime.of(2022, 7, 1, 0, 0), "달록"); + LocalDateTime.of(2022, 7, 1, 0, 0), "달록"); Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), - LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); scheduleRepository.save(schedule1); scheduleRepository.save(schedule2); @@ -130,9 +130,9 @@ class ScheduleRepositoryTest { void 시작일시와_종료일시를_전달할_때_일정의_종료날짜가_시작일시_이전이면_조회되지_않는다() { // given Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 6, 12, 13, 40), - LocalDateTime.of(2022, 6, 30, 23, 59), "달록"); + LocalDateTime.of(2022, 6, 30, 23, 59), "달록"); Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), - LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); scheduleRepository.save(schedule1); scheduleRepository.save(schedule2); diff --git a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java index 9fe2be6f..4177de97 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java @@ -28,8 +28,8 @@ class ScheduleServiceTest { LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); String memo = "알록달록 팀회의 - 선릉 큰 강의실"; - ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, - startDateTime, endDateTime, memo); + ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, startDateTime, endDateTime, + memo); // when Long id = scheduleService.save(scheduleCreateRequest); @@ -47,12 +47,12 @@ class ScheduleServiceTest { LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); String memo = "알록달록 팀회의 - 선릉 큰 강의실"; - ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, - startDateTime, endDateTime, memo); + ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, startDateTime, endDateTime, + memo); // when & then assertThatThrownBy(() -> scheduleService.save(scheduleCreateRequest)). - isInstanceOf(InvalidScheduleException.class); + isInstanceOf(InvalidScheduleException.class); } @DisplayName("새로운 일정을 생성 할 떄 일정 메모의 길이가 255를 초과하는 경우 예외를 던진다.") @@ -64,12 +64,12 @@ class ScheduleServiceTest { LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); String memo = "1".repeat(256); - ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, - startDateTime, endDateTime, memo); + ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, startDateTime, endDateTime, + memo); // when & then assertThatThrownBy(() -> scheduleService.save(scheduleCreateRequest)). - isInstanceOf(InvalidScheduleException.class); + isInstanceOf(InvalidScheduleException.class); } @DisplayName("새로운 일정을 생성 할 떄 종료일시가 시작일시 이전이라면 예외를 던진다.") @@ -81,12 +81,12 @@ class ScheduleServiceTest { LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); String memo = "1".repeat(256); - ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, - startDateTime, endDateTime, memo); + ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, startDateTime, endDateTime, + memo); // when & then assertThatThrownBy(() -> scheduleService.save(scheduleCreateRequest)). - isInstanceOf(InvalidScheduleException.class); + isInstanceOf(InvalidScheduleException.class); } @DisplayName("연도와 월을 전달받아 해당 월에 해당하는 일정 목록을 가져온다.") @@ -94,12 +94,11 @@ class ScheduleServiceTest { void 연도와_월을_전달받아_해당_월에_해당하는_일정_목록을_가져온다() { // given ScheduleCreateRequest scheduleCreateRequest1 = new ScheduleCreateRequest("알록달록 회의 1", - LocalDateTime.of(2022, 7, 5, 12, 30), LocalDateTime.of(2022, 7, 6, 14, 30), - "알록달록 팀회의 - 선릉 큰 강의실"); + LocalDateTime.of(2022, 7, 5, 12, 30), LocalDateTime.of(2022, 7, 6, 14, 30), "알록달록 팀회의 - 선릉 큰 강의실"); ScheduleCreateRequest scheduleCreateRequest2 = new ScheduleCreateRequest("알록달록 회의 2", - LocalDateTime.of(2022, 8, 5, 12, 30), LocalDateTime.of(2022, 8, 6, 14, 30), - "알록달록 팀회의 - 잠실 큰 강의실"); + LocalDateTime.of(2022, 8, 5, 12, 30), LocalDateTime.of(2022, 8, 6, 14, 30), + "알록달록 팀회의 - 잠실 큰 강의실"); scheduleService.save(scheduleCreateRequest1); scheduleService.save(scheduleCreateRequest2); From 1483153e17087957c29b284efbc42d4c2b7aca6c Mon Sep 17 00:00:00 2001 From: koo Date: Wed, 13 Jul 2022 11:22:24 +0900 Subject: [PATCH 0068/1011] =?UTF-8?q?refactor:=20Period=EC=9D=98=20equals&?= =?UTF-8?q?hashcode=20=EC=98=A4=EB=B2=84=EB=9D=BC=EC=9D=B4=EB=94=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/schedule/domain/Period.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java index cb9c890a..aa39fbb1 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java @@ -2,6 +2,7 @@ import com.allog.dallog.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; +import java.util.Objects; import javax.persistence.Column; import javax.persistence.Embeddable; @@ -36,4 +37,21 @@ public LocalDateTime getStartDateTime() { public LocalDateTime getEndDateTime() { return endDateTime; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Period period = (Period) o; + return Objects.equals(startDateTime, period.startDateTime) && Objects.equals(endDateTime, period.endDateTime); + } + + @Override + public int hashCode() { + return Objects.hash(startDateTime, endDateTime); + } } From af88546fd310007fff9dcbc9503b1c9004e0233f Mon Sep 17 00:00:00 2001 From: koo Date: Wed, 13 Jul 2022 16:40:38 +0900 Subject: [PATCH 0069/1011] =?UTF-8?q?refactor:=20Schedule=EC=9D=98=20@Tabl?= =?UTF-8?q?e,=20@Column=20=EC=95=A0=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EB=84=A4=EC=9E=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/allog/dallog/schedule/domain/Schedule.java | 6 +++--- .../com/allog/dallog/schedule/service/ScheduleService.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java index 5e8819d5..5e238b75 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java @@ -11,7 +11,7 @@ import javax.persistence.Table; @Entity -@Table(name = "SCHEDULES") +@Table(name = "schedules") public class Schedule { private static final int MAX_TITLE_LENGTH = 20; @@ -21,13 +21,13 @@ public class Schedule { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(name = "TITLE", nullable = false) + @Column(name = "title", nullable = false) private String title; @Embedded private Period period; - @Column(name = "MEMO", nullable = false) + @Column(name = "memo", nullable = false) private String memo; protected Schedule() { diff --git a/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java b/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java index 3dacce1b..b9d91861 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java +++ b/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java @@ -28,7 +28,7 @@ public Long save(final ScheduleCreateRequest request) { return schedule.getId(); } - public List findByYearAndMonth(int year, int month) { + public List findByYearAndMonth(final int year, final int month) { LocalDate startDate = LocalDate.of(year, month, 1); LocalDate endDate = startDate.plusDays(startDate.lengthOfMonth()); From 326d48cb3aa871c41cf1c82c68cefbe3abaa6843 Mon Sep 17 00:00:00 2001 From: koo Date: Wed, 13 Jul 2022 16:42:36 +0900 Subject: [PATCH 0070/1011] =?UTF-8?q?refactor:=20ScheduleCreateRequeste?= =?UTF-8?q?=EC=9D=98=20=EB=B6=80=EC=A0=81=EC=A0=88=ED=95=9C=20=EC=95=A0?= =?UTF-8?q?=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @NotNull 애노테이션을 @NotBlank로 수정 --- .../dallog/schedule/dto/request/ScheduleCreateRequest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java b/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java index 75fa5a8c..5afb66bc 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java +++ b/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java @@ -2,12 +2,12 @@ import com.allog.dallog.schedule.domain.Schedule; import java.time.LocalDateTime; -import javax.validation.constraints.NotNull; +import javax.validation.constraints.NotBlank; import org.springframework.format.annotation.DateTimeFormat; public class ScheduleCreateRequest { - @NotNull + @NotBlank private String title; @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm") @@ -16,7 +16,7 @@ public class ScheduleCreateRequest { @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm") private LocalDateTime endDateTime; - @NotNull + @NotBlank private String memo; private ScheduleCreateRequest() { From 7857ec8f4050965aaf7c9596b0fac206ceb197bb Mon Sep 17 00:00:00 2001 From: koo Date: Wed, 13 Jul 2022 16:43:49 +0900 Subject: [PATCH 0071/1011] =?UTF-8?q?refactor:=20SchedulesAcceptanceTest?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=AA=85=EC=9D=84=20ScheduleA?= =?UTF-8?q?cceptanceTest=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...SchedulesAcceptanceTest.java => ScheduleAcceptanceTest.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename backend/src/test/java/com/allog/dallog/acceptance/{SchedulesAcceptanceTest.java => ScheduleAcceptanceTest.java} (98%) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java similarity index 98% rename from backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java rename to backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java index 30449938..637b4df5 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SchedulesAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java @@ -13,7 +13,7 @@ import org.springframework.http.MediaType; @DisplayName("일정 관련 기능") -class SchedulesAcceptanceTest extends AcceptanceTest { +class ScheduleAcceptanceTest extends AcceptanceTest { @DisplayName("정상적인 일정정보를 등록하면 상태코드 201을 반환한다.") @Test From ef097a095e6f561550b6bd7100d082afa8f843c3 Mon Sep 17 00:00:00 2001 From: koo Date: Thu, 14 Jul 2022 10:51:05 +0900 Subject: [PATCH 0072/1011] =?UTF-8?q?refactor:=20Schedule=20=EC=95=A0?= =?UTF-8?q?=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=BB=A8=EB=B2=A4?= =?UTF-8?q?=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/allog/dallog/schedule/domain/Schedule.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java index 5e238b75..0e4017ed 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java @@ -10,8 +10,8 @@ import javax.persistence.Id; import javax.persistence.Table; -@Entity @Table(name = "schedules") +@Entity public class Schedule { private static final int MAX_TITLE_LENGTH = 20; @@ -19,6 +19,7 @@ public class Schedule { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") private Long id; @Column(name = "title", nullable = false) From e57af04da13600fdf14704127b8ab3cb8afe01a9 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 13 Jul 2022 11:21:02 +0900 Subject: [PATCH 0073/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=83=9D=EC=84=B1=20=EC=9D=B8=EC=88=98=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/CategoryCreateRequest.java | 20 +++++++++++ .../acceptance/CategoryAcceptanceTest.java | 35 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java create mode 100644 backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java diff --git a/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java b/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java new file mode 100644 index 00000000..378c63fc --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java @@ -0,0 +1,20 @@ +package com.allog.dallog.category.dto.request; + +import javax.validation.constraints.NotBlank; + +public class CategoryCreateRequest { + + @NotBlank + private String name; + + private CategoryCreateRequest() { + } + + public CategoryCreateRequest(final String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java new file mode 100644 index 00000000..91c4426a --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -0,0 +1,35 @@ +package com.allog.dallog.acceptance; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +@DisplayName("카테고리 관련 기능") +public class CategoryAcceptanceTest extends AcceptanceTest { + + @DisplayName("정상적인 카테고리 정보를 등록하면 상태코드 201을 반환한다.") + @Test + void 정상적인_카테고리_정보를_등록하면_상태코드_201을_반환한다() { + // given + String name = "BE 공식일정"; + CategoryCreateRequest request = new CategoryCreateRequest(name); + + // when + ExtractableResponse response = RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(request) + .when().post("/api/categories") + .then().log().all() + .extract(); + + // then + assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); + } +} From 3a9cdc03e41ad08b4c3409ecf713215375036f8b Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 13 Jul 2022 15:00:27 +0900 Subject: [PATCH 0074/1011] =?UTF-8?q?feat:=20InvalidCategoryException=20?= =?UTF-8?q?=EC=BB=A4=EC=8A=A4=ED=85=80=20=EC=98=88=EC=99=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/exception/InvalidCategoryException.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/category/exception/InvalidCategoryException.java diff --git a/backend/src/main/java/com/allog/dallog/category/exception/InvalidCategoryException.java b/backend/src/main/java/com/allog/dallog/category/exception/InvalidCategoryException.java new file mode 100644 index 00000000..80b35ab8 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/category/exception/InvalidCategoryException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.category.exception; + +public class InvalidCategoryException extends RuntimeException { + + public InvalidCategoryException() { + super("잘못된 카테고리입니다."); + } + + public InvalidCategoryException(final String message) { + super(message); + } +} From 2009b6db1a802015ee98fce1e237c3b2a5b08d54 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 13 Jul 2022 15:00:54 +0900 Subject: [PATCH 0075/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20Entity=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/category/domain/Category.java | 54 +++++++++++++++++++ .../dallog/category/domain/CategoryTest.java | 33 ++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/category/domain/Category.java create mode 100644 backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java diff --git a/backend/src/main/java/com/allog/dallog/category/domain/Category.java b/backend/src/main/java/com/allog/dallog/category/domain/Category.java new file mode 100644 index 00000000..9ec8b948 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/category/domain/Category.java @@ -0,0 +1,54 @@ +package com.allog.dallog.category.domain; + +import com.allog.dallog.category.exception.InvalidCategoryException; +import java.time.LocalDateTime; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "categories") +public class Category { + + public static final int MAX_NAME_LENGTH = 20; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "name", nullable = false) + private String name; + + @Column(name = "created_at", nullable = false) + private LocalDateTime createdAt; + + protected Category() { + } + + public Category(final String name) { + validateNameLength(name); + this.name = name; + this.createdAt = LocalDateTime.now(); + } + + private void validateNameLength(final String name) { + if (name.length() > MAX_NAME_LENGTH) { + throw new InvalidCategoryException("카테고리 이름의 길이는 20을 초과할 수 없습니다."); + } + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } +} diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java new file mode 100644 index 00000000..79242998 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java @@ -0,0 +1,33 @@ +package com.allog.dallog.category.domain; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import com.allog.dallog.category.exception.InvalidCategoryException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class CategoryTest { + + @DisplayName("카테고리를 생성한다.") + @Test + void 카테고리를_생성한다() { + // given + String name = "BE 공식일정"; + + // when & then + assertDoesNotThrow(() -> new Category(name)); + } + + @DisplayName("카테고리 이름의 길이가 20을 초과하는 경우 예외를 던진다.") + @ParameterizedTest + @ValueSource(strings = {"일이삼사오육칠팔구십일이삼사오육칠팔구십일", + "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 카테고리"}) + void 카테고리_이름의_길이가_20을_초과하는_경우_예외를_던진다(final String name) { + // given & when & then + assertThatThrownBy(() -> new Category(name)) + .isInstanceOf(InvalidCategoryException.class); + } +} From 77fb4968981c990571f1c26600af0626e157b55a Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 13 Jul 2022 15:13:36 +0900 Subject: [PATCH 0076/1011] =?UTF-8?q?feat:=20CategoryRepository=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/category/domain/CategoryRepository.java | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java diff --git a/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java b/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java new file mode 100644 index 00000000..baaa202d --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java @@ -0,0 +1,6 @@ +package com.allog.dallog.category.domain; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CategoryRepository extends JpaRepository { +} From ea8f06a91da28f5800768e1410043ba4c924baa4 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 13 Jul 2022 16:53:46 +0900 Subject: [PATCH 0077/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=9D=B4=EB=A6=84=EC=9D=B4=20=EA=B3=B5=EB=B0=B1?= =?UTF-8?q?=EC=9D=B8=20=EA=B2=BD=EC=9A=B0=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/category/domain/Category.java | 3 +++ .../allog/dallog/category/domain/CategoryTest.java | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/backend/src/main/java/com/allog/dallog/category/domain/Category.java b/backend/src/main/java/com/allog/dallog/category/domain/Category.java index 9ec8b948..c630880c 100644 --- a/backend/src/main/java/com/allog/dallog/category/domain/Category.java +++ b/backend/src/main/java/com/allog/dallog/category/domain/Category.java @@ -35,6 +35,9 @@ public Category(final String name) { } private void validateNameLength(final String name) { + if (name.isBlank()) { + throw new InvalidCategoryException("카테고리 이름은 공백일 수 없습니다."); + } if (name.length() > MAX_NAME_LENGTH) { throw new InvalidCategoryException("카테고리 이름의 길이는 20을 초과할 수 없습니다."); } diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java index 79242998..f6f78b68 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java @@ -21,6 +21,17 @@ class CategoryTest { assertDoesNotThrow(() -> new Category(name)); } + @DisplayName("카테고리 이름이 공백인 경우 예외를 던진다.") + @Test + void 카테고리_이름이_공백인_경우_예외를_던진다() { + // given + String name = ""; + + // when & then + assertThatThrownBy(() -> new Category(name)) + .isInstanceOf(InvalidCategoryException.class); + } + @DisplayName("카테고리 이름의 길이가 20을 초과하는 경우 예외를 던진다.") @ParameterizedTest @ValueSource(strings = {"일이삼사오육칠팔구십일이삼사오육칠팔구십일", From e7f7e8e4d9abb36173257aa9bd6b2a04395ffed1 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 13 Jul 2022 16:56:12 +0900 Subject: [PATCH 0078/1011] =?UTF-8?q?feat:=20CategoryService=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=83=9D=EC=84=B1=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/CategoryCreateRequest.java | 5 ++ .../category/service/CategoryService.java | 24 ++++++++++ .../category/service/CategoryServiceTest.java | 47 +++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/category/service/CategoryService.java create mode 100644 backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java diff --git a/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java b/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java index 378c63fc..9efc5428 100644 --- a/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java +++ b/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java @@ -1,5 +1,6 @@ package com.allog.dallog.category.dto.request; +import com.allog.dallog.category.domain.Category; import javax.validation.constraints.NotBlank; public class CategoryCreateRequest { @@ -14,6 +15,10 @@ public CategoryCreateRequest(final String name) { this.name = name; } + public Category toEntity() { + return new Category(name); + } + public String getName() { return name; } diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java new file mode 100644 index 00000000..701f74e6 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -0,0 +1,24 @@ +package com.allog.dallog.category.service; + +import com.allog.dallog.category.domain.Category; +import com.allog.dallog.category.domain.CategoryRepository; +import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(readOnly = true) +@Service +public class CategoryService { + + private final CategoryRepository categoryRepository; + + public CategoryService(final CategoryRepository categoryRepository) { + this.categoryRepository = categoryRepository; + } + + @Transactional + public Long save(final CategoryCreateRequest request) { + Category category = categoryRepository.save(request.toEntity()); + return category.getId(); + } +} diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java new file mode 100644 index 00000000..915d6242 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -0,0 +1,47 @@ +package com.allog.dallog.category.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.exception.InvalidCategoryException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class CategoryServiceTest { + + @Autowired + private CategoryService categoryService; + + @DisplayName("새로운 카테고리를 생성한다.") + @Test + void 새로운_카테고리를_생성한다() { + // given + String name = "BE 공식일정"; + CategoryCreateRequest request = new CategoryCreateRequest(name); + + //when + Long id = categoryService.save(request); + + // then + assertThat(id).isNotNull(); + } + + @DisplayName("새로운 카테고리를 생성 할 떄 이름이 공백이거나 길이가 20을 초과하는 경우 예외를 던진다.") + @ParameterizedTest + @ValueSource(strings = {"", "일이삼사오육칠팔구십일이삼사오육칠팔구십일", + "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 카테고리"}) + void 새로운_카테고리를_생성_할_때_이름이_공백이거나_길이가_20을_초과하는_경우_예외를_던진다(final String name) { + // given + CategoryCreateRequest request = new CategoryCreateRequest(name); + + // when & then + assertThatThrownBy(() -> categoryService.save(request)). + isInstanceOf(InvalidCategoryException.class); + } +} From 46355003cbd0b9823200941969e053f3e2bc5fe3 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 13 Jul 2022 16:59:55 +0900 Subject: [PATCH 0079/1011] =?UTF-8?q?feat:=20CategoryController=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=83=9D=EC=84=B1=20api?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CategoryController.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java new file mode 100644 index 00000000..b340925e --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -0,0 +1,28 @@ +package com.allog.dallog.category.controller; + +import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.service.CategoryService; +import java.net.URI; +import javax.validation.Valid; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequestMapping("/api/categories") +@RestController +public class CategoryController { + + private final CategoryService categoryService; + + public CategoryController(final CategoryService categoryService) { + this.categoryService = categoryService; + } + + @PostMapping + public ResponseEntity save(@Valid @RequestBody final CategoryCreateRequest request) { + Long id = categoryService.save(request); + return ResponseEntity.created(URI.create("/api/categories" + id)).build(); + } +} From fa135a26e7af0ba814494fe8e45951e96f0eb272 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 13 Jul 2022 17:15:02 +0900 Subject: [PATCH 0080/1011] =?UTF-8?q?test:=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=EB=A1=9C=20=EB=B6=84=EB=A6=AC=20?= =?UTF-8?q?=EB=B0=8F=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/acceptance/AcceptanceTest.java | 13 +++++++++++++ .../acceptance/CategoryAcceptanceTest.java | 17 +++++++++-------- .../acceptance/ScheduleAcceptanceTest.java | 11 ----------- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java index 437e537c..acbbc55d 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java @@ -1,9 +1,14 @@ package com.allog.dallog.acceptance; +import static org.assertj.core.api.Assertions.assertThat; + import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; import org.junit.jupiter.api.BeforeEach; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.http.HttpStatus; import org.springframework.test.annotation.DirtiesContext; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -17,4 +22,12 @@ class AcceptanceTest { void setUp() { RestAssured.port = port; } + + protected void 상태코드_200이_반환된다(ExtractableResponse response) { + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); + } + + protected void 상태코드_201이_반환된다(ExtractableResponse response) { + assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); + } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 91c4426a..45e1ca0f 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -1,14 +1,11 @@ package com.allog.dallog.acceptance; -import static org.assertj.core.api.Assertions.assertThat; - import com.allog.dallog.category.dto.request.CategoryCreateRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @DisplayName("카테고리 관련 기능") @@ -19,17 +16,21 @@ public class CategoryAcceptanceTest extends AcceptanceTest { void 정상적인_카테고리_정보를_등록하면_상태코드_201을_반환한다() { // given String name = "BE 공식일정"; - CategoryCreateRequest request = new CategoryCreateRequest(name); // when - ExtractableResponse response = RestAssured.given().log().all() + ExtractableResponse response = 새로운_카테고리를_등록한다(name); + + // then + 상태코드_201이_반환된다(response); + } + + private ExtractableResponse 새로운_카테고리를_등록한다(final String name) { + CategoryCreateRequest request = new CategoryCreateRequest(name); + return RestAssured.given().log().all() .contentType(MediaType.APPLICATION_JSON_VALUE) .body(request) .when().post("/api/categories") .then().log().all() .extract(); - - // then - assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java index 637b4df5..1cbca0e2 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java @@ -1,7 +1,5 @@ package com.allog.dallog.acceptance; -import static org.assertj.core.api.Assertions.assertThat; - import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; @@ -9,7 +7,6 @@ import java.util.Map; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @DisplayName("일정 관련 기능") @@ -70,12 +67,4 @@ class ScheduleAcceptanceTest extends AcceptanceTest { .then().log().all() .extract(); } - - private void 상태코드_200이_반환된다(final ExtractableResponse response) { - assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); - } - - private void 상태코드_201이_반환된다(final ExtractableResponse response) { - assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); - } } From bb93d865debfadb28819634a25269517e5281c40 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 14 Jul 2022 00:20:47 +0900 Subject: [PATCH 0081/1011] =?UTF-8?q?style:=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EB=B0=8F=20=EC=BB=A8=EB=B2=A4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/category/controller/CategoryController.java | 2 +- .../main/java/com/allog/dallog/category/domain/Category.java | 3 ++- .../com/allog/dallog/category/service/CategoryServiceTest.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index b340925e..4df33d09 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -23,6 +23,6 @@ public CategoryController(final CategoryService categoryService) { @PostMapping public ResponseEntity save(@Valid @RequestBody final CategoryCreateRequest request) { Long id = categoryService.save(request); - return ResponseEntity.created(URI.create("/api/categories" + id)).build(); + return ResponseEntity.created(URI.create("/api/categories/" + id)).build(); } } diff --git a/backend/src/main/java/com/allog/dallog/category/domain/Category.java b/backend/src/main/java/com/allog/dallog/category/domain/Category.java index c630880c..15af4a0b 100644 --- a/backend/src/main/java/com/allog/dallog/category/domain/Category.java +++ b/backend/src/main/java/com/allog/dallog/category/domain/Category.java @@ -9,14 +9,15 @@ import javax.persistence.Id; import javax.persistence.Table; -@Entity @Table(name = "categories") +@Entity public class Category { public static final int MAX_NAME_LENGTH = 20; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", nullable = false) private Long id; @Column(name = "name", nullable = false) diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 915d6242..096500ce 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -25,7 +25,7 @@ class CategoryServiceTest { String name = "BE 공식일정"; CategoryCreateRequest request = new CategoryCreateRequest(name); - //when + // when Long id = categoryService.save(request); // then From 8769acc6690963260f19060724b4a93a7dc0ceb9 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 14 Jul 2022 11:02:51 +0900 Subject: [PATCH 0082/1011] =?UTF-8?q?chore:=20nullable=20=EC=A0=9C?= =?UTF-8?q?=EC=95=BD=20=EC=83=9D=EB=9E=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/allog/dallog/category/domain/Category.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/allog/dallog/category/domain/Category.java b/backend/src/main/java/com/allog/dallog/category/domain/Category.java index 15af4a0b..2c9908a1 100644 --- a/backend/src/main/java/com/allog/dallog/category/domain/Category.java +++ b/backend/src/main/java/com/allog/dallog/category/domain/Category.java @@ -17,7 +17,7 @@ public class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", nullable = false) + @Column(name = "id") private Long id; @Column(name = "name", nullable = false) From 0c39198ac3bf4bd4c96dc88883d82d4ae39ccb45 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 14 Jul 2022 13:40:18 +0900 Subject: [PATCH 0083/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=A1=B0=ED=9A=8C=20=EC=9D=B8=EC=88=98=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acceptance/CategoryAcceptanceTest.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 45e1ca0f..9ff3032d 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -1,6 +1,10 @@ package com.allog.dallog.acceptance; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.global.dto.ListResponse; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; @@ -24,6 +28,28 @@ public class CategoryAcceptanceTest extends AcceptanceTest { 상태코드_201이_반환된다(response); } + @DisplayName("카테고리를 등록하고 페이징을 통해 나누어 조회한다.") + @Test + void 카테고리를_등록하고_페이징을_통해_나누어_조회한다() { + // given + 새로운_카테고리를_등록한다("BE 공식일정"); + 새로운_카테고리를_등록한다("FE 공식일정"); + 새로운_카테고리를_등록한다("알록달록 회의"); + + int page = 1; + int limit = 8; + + // when + ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(page, limit); + ListResponse categoryResponses = response.as(ListResponse.class); + + // then + assertAll( + () -> 상태코드_200이_반환된다(response), + () -> assertThat(categoryResponses.getData()).hasSize(3) + ); + } + private ExtractableResponse 새로운_카테고리를_등록한다(final String name) { CategoryCreateRequest request = new CategoryCreateRequest(name); return RestAssured.given().log().all() @@ -33,4 +59,11 @@ public class CategoryAcceptanceTest extends AcceptanceTest { .then().log().all() .extract(); } + + private ExtractableResponse 카테고리를_페이징을_통해_조회한다(final int page, final int limit) { + return RestAssured.given().log().all() + .when().get("/api/schedules?page={page}&limit={limit}", page, limit) + .then().log().all() + .extract(); + } } From e2a0ed6015a5bf9bfa4328f6d97a570e8d444640 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 14 Jul 2022 14:00:02 +0900 Subject: [PATCH 0084/1011] =?UTF-8?q?feat:=20CategoryRepository=EC=97=90?= =?UTF-8?q?=20=EC=8A=AC=EB=9D=BC=EC=9D=B4=EC=8A=A4=EB=A5=BC=20=ED=86=B5?= =?UTF-8?q?=ED=95=9C=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/domain/CategoryRepository.java | 4 ++ .../domain/CategoryRepositoryTest.java | 56 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java diff --git a/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java b/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java index baaa202d..175f4cf4 100644 --- a/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java +++ b/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java @@ -1,6 +1,10 @@ package com.allog.dallog.category.domain; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.data.jpa.repository.JpaRepository; public interface CategoryRepository extends JpaRepository { + + Slice findSliceBy(final Pageable pageable); } diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java new file mode 100644 index 00000000..7aba7ca4 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java @@ -0,0 +1,56 @@ +package com.allog.dallog.category.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Slice; + +@DataJpaTest +class CategoryRepositoryTest { + + @Autowired + private CategoryRepository categoryRepository; + + @DisplayName("페이지와 사이즈를 받아 해당하는 구간의 카테고리를 조회한다.") + @Test + void 페이지와_리밋을_받아_해당하는_구간의_카테고리를_조회한다() { + // given + categoryRepository.save(new Category("BE 공식일정")); + categoryRepository.save(new Category("FE 공식일정")); + categoryRepository.save(new Category("알록달록 회의")); + categoryRepository.save(new Category("지원플랫폼 근로")); + categoryRepository.save(new Category("파랑의 코틀린 스터디")); + + int page = 1; + int size = 2; + PageRequest pageRequest = PageRequest.of(page, size); + + // when + Slice categories = categoryRepository.findSliceBy(pageRequest); + + // then + assertThat(categories.getContent()) + .hasSize(size) + .extracting(Category::getName) + .contains("알록달록 회의", "지원플랫폼 근로"); + } + + @DisplayName("조회 시 데이터가 존재하지 않는 경우 빈 슬라이스가 반환된다.") + @Test + void 조회_시_데이터가_존재하지_않는_경우_빈_슬라이스가_반환된다() { + // given + int page = 1; + int size = 2; + PageRequest pageRequest = PageRequest.of(page, size); + + // when + Slice categories = categoryRepository.findSliceBy(pageRequest); + + // then + assertThat(categories).hasSize(0); + } +} From 5d02dab00adecaa89d6c9b5f4ea61f6d458dce74 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 14 Jul 2022 14:19:24 +0900 Subject: [PATCH 0085/1011] =?UTF-8?q?feat:=20CategoryService=EC=97=90=20?= =?UTF-8?q?=EC=8A=AC=EB=9D=BC=EC=9D=B4=EC=8A=A4=EB=A5=BC=20=ED=86=B5?= =?UTF-8?q?=ED=95=9C=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/CategoryResponse.java | 33 +++++++++++++++++++ .../category/service/CategoryService.java | 12 +++++++ .../category/service/CategoryServiceTest.java | 27 +++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java diff --git a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java new file mode 100644 index 00000000..f8cf1b8c --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java @@ -0,0 +1,33 @@ +package com.allog.dallog.category.dto.response; + +import com.allog.dallog.category.domain.Category; +import java.time.LocalDateTime; + +public class CategoryResponse { + + private final Long id; + private final String name; + private final LocalDateTime createdAt; + + public CategoryResponse(final Category category) { + this(category.getId(), category.getName(), category.getCreatedAt()); + } + + public CategoryResponse(final Long id, final String name, final LocalDateTime createdAt) { + this.id = id; + this.name = name; + this.createdAt = createdAt; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } +} diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index 701f74e6..d99961d1 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -3,6 +3,10 @@ import com.allog.dallog.category.domain.Category; import com.allog.dallog.category.domain.CategoryRepository; import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.dto.response.CategoryResponse; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,4 +25,12 @@ public Long save(final CategoryCreateRequest request) { Category category = categoryRepository.save(request.toEntity()); return category.getId(); } + + public List findSliceBy(final PageRequest request) { + return categoryRepository.findSliceBy(request) + .getContent() + .stream() + .map(CategoryResponse::new) + .collect(Collectors.toList()); + } } diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 096500ce..99ce26f9 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -4,13 +4,16 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.exception.InvalidCategoryException; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.PageRequest; @SpringBootTest class CategoryServiceTest { @@ -44,4 +47,28 @@ class CategoryServiceTest { assertThatThrownBy(() -> categoryService.save(request)). isInstanceOf(InvalidCategoryException.class); } + + @DisplayName("페이지를 받아 해당하는 구간의 카테고리를 가져온다.") + @Test + void 페이지를_받아_해당하는_구간의_카테고리를_가져온다() { + // given + categoryService.save(new CategoryCreateRequest("BE 공식일정")); + categoryService.save(new CategoryCreateRequest("FE 공식일정")); + categoryService.save(new CategoryCreateRequest("알록달록 회의")); + categoryService.save(new CategoryCreateRequest("지원플랫폼 근로")); + categoryService.save(new CategoryCreateRequest("파랑의 코틀린 스터디")); + + int page = 1; + int size = 2; + PageRequest request = PageRequest.of(page, size); + + // when + List response = categoryService.findSliceBy(request); + + // then + assertThat(response) + .hasSize(size) + .extracting(CategoryResponse::getName) + .contains("알록달록 회의", "지원플랫폼 근로"); + } } From 3f7bd763d98507c1d0e98430dee8358bc68a94a1 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 14 Jul 2022 14:34:19 +0900 Subject: [PATCH 0086/1011] =?UTF-8?q?test:=20url=20path=20=EB=B0=8F=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/acceptance/CategoryAcceptanceTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 9ff3032d..576e49e2 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -37,10 +37,10 @@ public class CategoryAcceptanceTest extends AcceptanceTest { 새로운_카테고리를_등록한다("알록달록 회의"); int page = 1; - int limit = 8; + int size = 8; // when - ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(page, limit); + ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(page, size); ListResponse categoryResponses = response.as(ListResponse.class); // then @@ -60,9 +60,9 @@ public class CategoryAcceptanceTest extends AcceptanceTest { .extract(); } - private ExtractableResponse 카테고리를_페이징을_통해_조회한다(final int page, final int limit) { + private ExtractableResponse 카테고리를_페이징을_통해_조회한다(final int page, final int size) { return RestAssured.given().log().all() - .when().get("/api/schedules?page={page}&limit={limit}", page, limit) + .when().get("/api/categories?page={page}&size={size}", page, size) .then().log().all() .extract(); } From dbc4ce9c4f9a73432604abd80298cbd6b7eff6c1 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 14 Jul 2022 14:34:56 +0900 Subject: [PATCH 0087/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=A1=B0=ED=9A=8C=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/controller/CategoryController.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index 4df33d09..ef0c0511 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -1,13 +1,19 @@ package com.allog.dallog.category.controller; import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; +import com.allog.dallog.global.dto.ListResponse; import java.net.URI; +import java.util.List; import javax.validation.Valid; +import org.springframework.data.domain.PageRequest; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/api/categories") @@ -25,4 +31,12 @@ public ResponseEntity save(@Valid @RequestBody final CategoryCreateRequest Long id = categoryService.save(request); return ResponseEntity.created(URI.create("/api/categories/" + id)).build(); } + + @GetMapping + public ResponseEntity> findSliceBy(@RequestParam final int page, + @RequestParam final int size) { + PageRequest pageRequest = PageRequest.of(page - 1, size); + List responses = categoryService.findSliceBy(pageRequest); + return ResponseEntity.ok(new ListResponse<>(responses)); + } } From 6a69c1ef349a69c3a52eadc2c2ef1da9be4dfe62 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Tue, 12 Jul 2022 21:31:42 +0900 Subject: [PATCH 0088/1011] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=EC=9D=84?= =?UTF-8?q?=20=EB=82=98=ED=83=80=EB=82=B4=EB=8A=94=20Member=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/member/domain/Member.java | 78 +++++++++++++++++++ .../dallog/member/domain/SocialType.java | 6 ++ .../exception/InvalidMemberException.java | 12 +++ .../dallog/member/domain/MemberTest.java | 56 +++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/member/domain/Member.java create mode 100644 backend/src/main/java/com/allog/dallog/member/domain/SocialType.java create mode 100644 backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java create mode 100644 backend/src/test/java/com/allog/dallog/member/domain/MemberTest.java diff --git a/backend/src/main/java/com/allog/dallog/member/domain/Member.java b/backend/src/main/java/com/allog/dallog/member/domain/Member.java new file mode 100644 index 00000000..0ed0c1f3 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/member/domain/Member.java @@ -0,0 +1,78 @@ +package com.allog.dallog.member.domain; + +import com.allog.dallog.member.exception.InvalidMemberException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Member { + + private static final Pattern EMAIL_PATTERN = Pattern.compile("^[a-z0-9._-]+@[a-z]+[.]+[a-z]{2,3}$"); + private static final int MAX_DISPLAY_NAME_LENGTH = 10; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String email; + + private String profileImageUrl; + + private String displayName; + + @Enumerated(value = EnumType.STRING) + private SocialType socialType; + + protected Member() { + } + + public Member(final String email, final String profileImageUrl, final String displayName, + final SocialType socialType) { + validateEmail(email); + validateDisplayName(displayName); + + this.email = email; + this.profileImageUrl = profileImageUrl; + this.displayName = displayName; + this.socialType = socialType; + } + + private void validateEmail(final String email) { + Matcher matcher = EMAIL_PATTERN.matcher(email); + if (!matcher.matches()) { + throw new InvalidMemberException("이메일 형식이 올바르지 않습니다."); + } + } + + private void validateDisplayName(final String displayName) { + if (displayName.isEmpty() || displayName.length() > MAX_DISPLAY_NAME_LENGTH) { + throw new InvalidMemberException("이름 형식이 올바르지 않습니다."); + } + } + + public Long getId() { + return id; + } + + public String getEmail() { + return email; + } + + public String getProfileImageUrl() { + return profileImageUrl; + } + + public String getDisplayName() { + return displayName; + } + + public SocialType getSocialType() { + return socialType; + } +} diff --git a/backend/src/main/java/com/allog/dallog/member/domain/SocialType.java b/backend/src/main/java/com/allog/dallog/member/domain/SocialType.java new file mode 100644 index 00000000..f199cb1f --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/member/domain/SocialType.java @@ -0,0 +1,6 @@ +package com.allog.dallog.member.domain; + +public enum SocialType { + + GOOGLE, GITHUB; +} diff --git a/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java b/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java new file mode 100644 index 00000000..f50bd95b --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.member.exception; + +public class InvalidMemberException extends RuntimeException { + + public InvalidMemberException() { + super("잘못된 회원의 정보입니다."); + } + + public InvalidMemberException(final String message) { + super(message); + } +} diff --git a/backend/src/test/java/com/allog/dallog/member/domain/MemberTest.java b/backend/src/test/java/com/allog/dallog/member/domain/MemberTest.java new file mode 100644 index 00000000..3c9be418 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/member/domain/MemberTest.java @@ -0,0 +1,56 @@ +package com.allog.dallog.member.domain; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import com.allog.dallog.member.exception.InvalidMemberException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class MemberTest { + + @DisplayName("회원을 생성한다.") + @Test + void 회원을_생성한다() { + // given + String email = "dev.hyeonic@gmail.com"; + String profileImageUrl = "https://avatars.githubusercontent.com/u/59357153?v=4"; + String displayName = "매트"; + SocialType socialType = SocialType.GOOGLE; + + // when & then + assertDoesNotThrow(() -> new Member(email, profileImageUrl, displayName, socialType)); + } + + @DisplayName("회원의 email이 형식이 맞지 않으면 예외를 던진다.") + @ParameterizedTest + @ValueSource(strings = {"dev.hyeonic@", "dev.hyeonicgmail.com", "dev.hyeonic@gmail", "@gmail.com", "dev.hyeonic"}) + void 회원의_email이_형식이_맞지_않으면_예외를_던진다(final String email) { + // given + String profileImageUrl = "https://avatars.githubusercontent.com/u/59357153?v=4"; + String displayName = "매트"; + SocialType socialType = SocialType.GOOGLE; + + // when & then + assertThatThrownBy(() -> new Member(email, profileImageUrl, displayName, socialType)) + .isInstanceOf(InvalidMemberException.class) + .hasMessage("이메일 형식이 올바르지 않습니다."); + } + + @DisplayName("회원의 이름이 1 ~ 10 사이가 아닌 경우 예외를 던진다.") + @ParameterizedTest + @ValueSource(strings = {"", "일이삼사오육칠팔구십일"}) + void 회원의_이름이_1_에서_10_사이가_아닌_경우_예외를_던진다(final String displayName) { + // given + String email = "dev.hyeonic@gmail.com"; + String profileImageUrl = "https://avatars.githubusercontent.com/u/59357153?v=4"; + SocialType socialType = SocialType.GOOGLE; + + // when & then + assertThatThrownBy(() -> new Member(email, profileImageUrl, displayName, socialType)) + .isInstanceOf(InvalidMemberException.class) + .hasMessage("이름 형식이 올바르지 않습니다."); + } +} From 326938696bb66ed46c590156fe6fbcf9aab82d10 Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 12 Jul 2022 21:35:34 +0900 Subject: [PATCH 0089/1011] =?UTF-8?q?feat:=20Member=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=ED=95=84=EB=93=9C=EC=97=90=20=EC=BB=AC=EB=9F=BC=20?= =?UTF-8?q?=EC=A0=9C=EC=95=BD=EC=A1=B0=EA=B1=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/allog/dallog/member/domain/Member.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/src/main/java/com/allog/dallog/member/domain/Member.java b/backend/src/main/java/com/allog/dallog/member/domain/Member.java index 0ed0c1f3..ec0c5f76 100644 --- a/backend/src/main/java/com/allog/dallog/member/domain/Member.java +++ b/backend/src/main/java/com/allog/dallog/member/domain/Member.java @@ -3,6 +3,7 @@ import com.allog.dallog.member.exception.InvalidMemberException; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; @@ -20,10 +21,13 @@ public class Member { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Column(nullable = false) private String email; + @Column(nullable = false) private String profileImageUrl; + @Column(nullable = false) private String displayName; @Enumerated(value = EnumType.STRING) From 3a2dc9c22282b0edae83285dbebd6d0368df446d Mon Sep 17 00:00:00 2001 From: devHudi Date: Wed, 13 Jul 2022 14:31:21 +0900 Subject: [PATCH 0090/1011] =?UTF-8?q?refactor:=20Member=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Table 이름을 복수형으로 명시 - 모든 필드에 Column 어노테이션 추가 --- .../java/com/allog/dallog/member/domain/Member.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/member/domain/Member.java b/backend/src/main/java/com/allog/dallog/member/domain/Member.java index ec0c5f76..88c7c458 100644 --- a/backend/src/main/java/com/allog/dallog/member/domain/Member.java +++ b/backend/src/main/java/com/allog/dallog/member/domain/Member.java @@ -10,7 +10,9 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.Table; +@Table(name = "members") @Entity public class Member { @@ -19,18 +21,20 @@ public class Member { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") private Long id; - @Column(nullable = false) + @Column(name = "email", nullable = false) private String email; - @Column(nullable = false) + @Column(name = "profile_image_url", nullable = false) private String profileImageUrl; - @Column(nullable = false) + @Column(name = "display_name", nullable = false) private String displayName; @Enumerated(value = EnumType.STRING) + @Column(name = "social_type", nullable = false) private SocialType socialType; protected Member() { From 54d6aae2d7b4fa7ec1549a8529131833f674bd52 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 13 Jul 2022 16:13:10 +0900 Subject: [PATCH 0091/1011] =?UTF-8?q?feat:=20=EA=B5=AC=EA=B8=80=20?= =?UTF-8?q?=EC=86=8C=EC=85=9C=20=EC=9D=B8=EC=A6=9D=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EB=A7=81=ED=81=AC=20=EC=83=9D=EC=84=B1=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/auth/service/AuthService.java | 30 +++++++++++++++++++ .../src/main/resources/application.properties | 3 ++ .../dallog/auth/service/AuthServiceTest.java | 25 ++++++++++++++++ .../src/test/resources/application.properties | 9 ++++++ 4 files changed, 67 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/auth/service/AuthService.java create mode 100644 backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java create mode 100644 backend/src/test/resources/application.properties diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java new file mode 100644 index 00000000..89bdb055 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -0,0 +1,30 @@ +package com.allog.dallog.auth.service; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class AuthService { + + private static final String GOOGLE_OAUTH_END_POINT = "https://accounts.google.com/o/oauth2/v2/auth"; + + private final String googleRedirectUri; + private final String googleClientId; + private final String googleClientSecret; + + public AuthService(@Value("${oauth.google.redirect_uri}") final String googleRedirectUri, + @Value("${oauth.google.client_id}") final String googleClientId, + @Value("${oauth.google.client_secret}") final String googleClientSecret) { + this.googleRedirectUri = googleRedirectUri; + this.googleClientId = googleClientId; + this.googleClientSecret = googleClientSecret; + } + + public String generateGoogleLink() { + return GOOGLE_OAUTH_END_POINT + "?" + + "client_id=" + googleClientId + "&" + + "redirect_uri=" + googleRedirectUri + "&" + + "response_type=code&" + + "scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"; + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 2b920888..6a4ef237 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -4,3 +4,6 @@ spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE +oauth.google.redirect_uri=${GOOGLE_REDIRECT_URI} +oauth.google.client_id=${GOOGLE_CLIENT_ID} +oauth.google.client_secret=${GOOGLE_CLIENT_SECRET} diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java new file mode 100644 index 00000000..31c2af59 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -0,0 +1,25 @@ +package com.allog.dallog.auth.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class AuthServiceTest { + + @Autowired + private AuthService authService; + + @DisplayName("구글 로그인을 위한 링크를 생성한다.") + @Test + void 구글_로그인을_위한_링크를_생성한다() { + // given + String link = authService.generateGoogleLink(); + + // when & then + assertThat(link).isNotEmpty(); + } +} diff --git a/backend/src/test/resources/application.properties b/backend/src/test/resources/application.properties new file mode 100644 index 00000000..c8e22c84 --- /dev/null +++ b/backend/src/test/resources/application.properties @@ -0,0 +1,9 @@ +spring.datasource.url=jdbc:h2:~/dallog;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE +spring.datasource.username=sa +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.show-sql=true +spring.jpa.hibernate.ddl-auto=create +logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE +oauth.google.redirect_uri=http://localhost:3000 +oauth.google.client_id=hyeonic +oauth.google.client_secret=123 From d9043c6b7853657ad07f34e1ed2116c7e0de8ff2 Mon Sep 17 00:00:00 2001 From: devHudi Date: Wed, 13 Jul 2022 19:20:49 +0900 Subject: [PATCH 0092/1011] =?UTF-8?q?test:=20AuthService=20=EC=9E=90?= =?UTF-8?q?=EC=B2=B4=20=ED=86=A0=ED=81=B0=20=EC=83=9D=EC=84=B1=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oauth/client/OAuthClient.java | 9 +++++++ .../infrastructure/oauth/dto/OAuthMember.java | 26 +++++++++++++++++++ .../dallog/auth/service/AuthServiceTest.java | 17 +++++++++++- .../com/allog/dallog/config/TestConfig.java | 16 ++++++++++++ .../oauth/client/StubOAuthClient.java | 11 ++++++++ 5 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/OAuthClient.java create mode 100644 backend/src/main/java/com/allog/dallog/infrastructure/oauth/dto/OAuthMember.java create mode 100644 backend/src/test/java/com/allog/dallog/config/TestConfig.java create mode 100644 backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/OAuthClient.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/OAuthClient.java new file mode 100644 index 00000000..ff95d7de --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/OAuthClient.java @@ -0,0 +1,9 @@ +package com.allog.dallog.infrastructure.oauth.client; + +import com.allog.dallog.infrastructure.oauth.dto.OAuthMember; + +@FunctionalInterface +public interface OAuthClient { + + OAuthMember getOAuthMember(final String code); +} diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/dto/OAuthMember.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/dto/OAuthMember.java new file mode 100644 index 00000000..e4bb16e8 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/dto/OAuthMember.java @@ -0,0 +1,26 @@ +package com.allog.dallog.infrastructure.oauth.dto; + +public class OAuthMember { + + private final String email; + private final String displayName; + private final String profileImageUrl; + + public OAuthMember(final String email, final String displayName, final String profileImageUrl) { + this.email = email; + this.displayName = displayName; + this.profileImageUrl = profileImageUrl; + } + + public String getEmail() { + return email; + } + + public String getDisplayName() { + return displayName; + } + + public String getProfileImageUrl() { + return profileImageUrl; + } +} diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index 31c2af59..fcef9c40 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -2,12 +2,14 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.config.TestConfig; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -@SpringBootTest +@SpringBootTest(classes = TestConfig.class) class AuthServiceTest { @Autowired @@ -22,4 +24,17 @@ class AuthServiceTest { // when & then assertThat(link).isNotEmpty(); } + + @DisplayName("토큰 생성을 하면 OAuth 서버에서 인증 후 토큰을 반환한다") + @Test + void 토큰_생성을_하면_OAuth_서버에서_인증_후_토큰을_반환한다() { + // given + String code = "authorization code"; + + // when + TokenResponse actual = authService.generateTokenWithCode(code); + + // then + assertThat(actual.getAccessToken()).isNotEmpty(); + } } diff --git a/backend/src/test/java/com/allog/dallog/config/TestConfig.java b/backend/src/test/java/com/allog/dallog/config/TestConfig.java new file mode 100644 index 00000000..1ee28fa4 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/config/TestConfig.java @@ -0,0 +1,16 @@ +package com.allog.dallog.config; + +import com.allog.dallog.infrastructure.oauth.client.OAuthClient; +import com.allog.dallog.infrastructure.oauth.client.StubOAuthClient; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; + +@TestConfiguration +public class TestConfig { + + // SpringBootTest 환경에서 OAuthClient 실제 객체 대신 테스트 더블을 빈으로 등록하기 위한 코드 + @Bean + public OAuthClient oAuthClient() { + return new StubOAuthClient(); + } +} diff --git a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java new file mode 100644 index 00000000..7071b04d --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java @@ -0,0 +1,11 @@ +package com.allog.dallog.infrastructure.oauth.client; + +import com.allog.dallog.infrastructure.oauth.dto.OAuthMember; + +public class StubOAuthClient implements OAuthClient { + + @Override + public OAuthMember getOAuthMember(final String code) { + return new OAuthMember("Fake Email", "Fake Name", "Fake Profile Image Url"); + } +} From 75796488bad220cf1d502e19fa49ff06b14b7e3d Mon Sep 17 00:00:00 2001 From: devHudi Date: Wed, 13 Jul 2022 19:36:46 +0900 Subject: [PATCH 0093/1011] =?UTF-8?q?feat:=20OAuth=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EB=A7=81=ED=81=AC=20=EC=83=9D=EC=84=B1=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/auth/dto/TokenResponse.java | 14 ++++++++ .../dallog/auth/service/AuthService.java | 32 +++++++++---------- .../oauth/endpoint/GoogleOAuthEndpoint.java | 31 ++++++++++++++++++ .../oauth/endpoint/OAuthEndpoint.java | 7 ++++ 4 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/auth/dto/TokenResponse.java create mode 100644 backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/GoogleOAuthEndpoint.java create mode 100644 backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/OAuthEndpoint.java diff --git a/backend/src/main/java/com/allog/dallog/auth/dto/TokenResponse.java b/backend/src/main/java/com/allog/dallog/auth/dto/TokenResponse.java new file mode 100644 index 00000000..3da438d3 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/dto/TokenResponse.java @@ -0,0 +1,14 @@ +package com.allog.dallog.auth.dto; + +public class TokenResponse { + + private final String accessToken; + + public TokenResponse(final String accessToken) { + this.accessToken = accessToken; + } + + public String getAccessToken() { + return accessToken; + } +} diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index 89bdb055..bca65ed3 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -1,30 +1,28 @@ package com.allog.dallog.auth.service; -import org.springframework.beans.factory.annotation.Value; +import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.infrastructure.oauth.client.OAuthClient; +import com.allog.dallog.infrastructure.oauth.dto.OAuthMember; +import com.allog.dallog.infrastructure.oauth.endpoint.OAuthEndpoint; import org.springframework.stereotype.Service; @Service public class AuthService { - private static final String GOOGLE_OAUTH_END_POINT = "https://accounts.google.com/o/oauth2/v2/auth"; + private final OAuthEndpoint oAuthEndpoint; + private final OAuthClient oAuthClient; - private final String googleRedirectUri; - private final String googleClientId; - private final String googleClientSecret; - - public AuthService(@Value("${oauth.google.redirect_uri}") final String googleRedirectUri, - @Value("${oauth.google.client_id}") final String googleClientId, - @Value("${oauth.google.client_secret}") final String googleClientSecret) { - this.googleRedirectUri = googleRedirectUri; - this.googleClientId = googleClientId; - this.googleClientSecret = googleClientSecret; + public AuthService(final OAuthEndpoint oAuthEndpoint, final OAuthClient oAuthClient) { + this.oAuthEndpoint = oAuthEndpoint; + this.oAuthClient = oAuthClient; } public String generateGoogleLink() { - return GOOGLE_OAUTH_END_POINT + "?" - + "client_id=" + googleClientId + "&" - + "redirect_uri=" + googleRedirectUri + "&" - + "response_type=code&" - + "scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"; + return oAuthEndpoint.generate(); + } + + public TokenResponse generateTokenWithCode(final String code) { + OAuthMember oAuthMember = oAuthClient.getOAuthMember(code); + return null; } } diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/GoogleOAuthEndpoint.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/GoogleOAuthEndpoint.java new file mode 100644 index 00000000..b981b976 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/GoogleOAuthEndpoint.java @@ -0,0 +1,31 @@ +package com.allog.dallog.infrastructure.oauth.endpoint; + +import java.util.List; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class GoogleOAuthEndpoint implements OAuthEndpoint { + + private static final String GOOGLE_OAUTH_END_POINT = "https://accounts.google.com/o/oauth2/v2/auth"; + private static final List SCOPES = List.of("https://www.googleapis.com/auth/userinfo.profile", + "https://www.googleapis.com/auth/userinfo.email"); + + private final String googleRedirectUri; + private final String googleClientId; + + public GoogleOAuthEndpoint(@Value("${oauth.google.redirect_uri}") final String googleRedirectUri, + @Value("${oauth.google.client_id}") final String googleClientId) { + this.googleRedirectUri = googleRedirectUri; + this.googleClientId = googleClientId; + } + + @Override + public String generate() { + return GOOGLE_OAUTH_END_POINT + "?" + + "client_id=" + googleClientId + "&" + + "redirect_uri=" + googleRedirectUri + "&" + + "response_type=code&" + + "scope=" + String.join(" ", SCOPES); + } +} diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/OAuthEndpoint.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/OAuthEndpoint.java new file mode 100644 index 00000000..b03a9b37 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/OAuthEndpoint.java @@ -0,0 +1,7 @@ +package com.allog.dallog.infrastructure.oauth.endpoint; + +@FunctionalInterface +public interface OAuthEndpoint { + + String generate(); +} From 324c17608acb1498a81c7195052049670fc1600e Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 13 Jul 2022 19:45:15 +0900 Subject: [PATCH 0094/1011] =?UTF-8?q?feat:=20=ED=9A=8C=EC=9B=90=20email?= =?UTF-8?q?=EC=9D=84=20=EA=B8=B0=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=EA=B2=80=EC=A6=9D=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/domain/MemberRepository.java | 8 +++++ .../member/domain/MemberRepositoryTest.java | 32 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/member/domain/MemberRepository.java create mode 100644 backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java diff --git a/backend/src/main/java/com/allog/dallog/member/domain/MemberRepository.java b/backend/src/main/java/com/allog/dallog/member/domain/MemberRepository.java new file mode 100644 index 00000000..c1f1b7d1 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/member/domain/MemberRepository.java @@ -0,0 +1,8 @@ +package com.allog.dallog.member.domain; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberRepository extends JpaRepository { + + boolean existsByEmail(final String email); +} diff --git a/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java b/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java new file mode 100644 index 00000000..1088b5c6 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java @@ -0,0 +1,32 @@ +package com.allog.dallog.member.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; + +@DataJpaTest +class MemberRepositoryTest { + + @Autowired + private MemberRepository memberRepository; + + @DisplayName("중복된 이메일이 존재하는 경우 true를 반환한다.") + @Test + void 중복된_이메일이_존재하는_경우_true를_반환한다() { + // given + String email = "dev.hyeonic@gmail.com"; + String profileImageUrl = "/image.png"; + String displayName = "매트"; + Member member = new Member(email, profileImageUrl, displayName, SocialType.GOOGLE); + memberRepository.save(member); + + // when + boolean actual = memberRepository.existsByEmail(email); + + // then + assertThat(actual).isTrue(); + } +} From e617c5cf8926da532e5961e451099712989016d2 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 13 Jul 2022 20:18:39 +0900 Subject: [PATCH 0095/1011] =?UTF-8?q?feat:=20JWT=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?TokenProvider=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 4 ++ .../auth/exception/InvalidTokenException.java | 12 ++++ .../dallog/auth/support/JwtTokenProvider.java | 61 +++++++++++++++++++ .../src/main/resources/application.properties | 2 + .../src/test/resources/application.properties | 2 + 5 files changed, 81 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenException.java create mode 100644 backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java diff --git a/backend/build.gradle b/backend/build.gradle index dcbcb02b..2084efb0 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -21,6 +21,10 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'io.rest-assured:rest-assured:4.4.0' + + implementation 'io.jsonwebtoken:jjwt-api:0.11.5' + runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' + runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' } tasks.named('test') { diff --git a/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenException.java b/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenException.java new file mode 100644 index 00000000..031bc033 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.auth.exception; + +public class InvalidTokenException extends RuntimeException { + + public InvalidTokenException() { + super("유효하지 않은 토큰입니다."); + } + + public InvalidTokenException(final String message) { + super(message); + } +} diff --git a/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java b/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java new file mode 100644 index 00000000..cfe55175 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java @@ -0,0 +1,61 @@ +package com.allog.dallog.auth.support; + +import com.allog.dallog.auth.exception.InvalidTokenException; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import javax.crypto.SecretKey; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class JwtTokenProvider { + + private final SecretKey key; + private final long validityInMilliseconds; + + public JwtTokenProvider(@Value("${security.jwt.token.secret-key}") String secretKey, + @Value("${security.jwt.token.expire-length}") long validityInMilliseconds) { + this.key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); + this.validityInMilliseconds = validityInMilliseconds; + } + + public String createToken(String payload) { + Date now = new Date(); + Date validity = new Date(now.getTime() + validityInMilliseconds); + + return Jwts.builder() + .setSubject(payload) + .setIssuedAt(now) + .setExpiration(validity) + .signWith(key, SignatureAlgorithm.HS256) + .compact(); + } + + public String getPayload(String token) { + return Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody() + .getSubject(); + } + + public void validateToken(String token) { + try { + Jws claims = Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token); + + claims.getBody().getExpiration().before(new Date()); + } catch (JwtException | IllegalArgumentException e) { + throw new InvalidTokenException(); + } + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 6a4ef237..49ff2a94 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -7,3 +7,5 @@ logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE oauth.google.redirect_uri=${GOOGLE_REDIRECT_URI} oauth.google.client_id=${GOOGLE_CLIENT_ID} oauth.google.client_secret=${GOOGLE_CLIENT_SECRET} +security.jwt.token.secret-key=${JWT_SECRET_KEY} +security.jwt.token.expire-length=${JWT_EXPIRE_LENGTH} diff --git a/backend/src/test/resources/application.properties b/backend/src/test/resources/application.properties index c8e22c84..b5e9ced5 100644 --- a/backend/src/test/resources/application.properties +++ b/backend/src/test/resources/application.properties @@ -7,3 +7,5 @@ logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE oauth.google.redirect_uri=http://localhost:3000 oauth.google.client_id=hyeonic oauth.google.client_secret=123 +security.jwt.token.secret-key=fsmjgbdafmjgbasmfgadbsgmadfhgbfamjghbvmssdgsdfgdf +security.jwt.token.expire-length=3600 From 5b4f8992638b1d0933f2fdaa33817cf4b13d9990 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 13 Jul 2022 20:21:59 +0900 Subject: [PATCH 0096/1011] =?UTF-8?q?feat:=20=EC=9D=B8=EA=B0=80=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EB=A5=BC=20=EA=B8=B0=EB=B0=98=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20JWT=EB=A5=BC=20=EB=B0=9C=EA=B8=89=ED=95=98=EB=8A=94?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/auth/service/AuthService.java | 30 +++++++++++++++-- .../oauth/client/GoogleOAuthClient.java | 13 ++++++++ .../member/domain/MemberRepository.java | 3 ++ .../exception/NoSuchMemberException.java | 12 +++++++ .../dallog/member/service/MemberService.java | 32 +++++++++++++++++++ .../oauth/client/StubOAuthClient.java | 2 +- 6 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java create mode 100644 backend/src/main/java/com/allog/dallog/member/exception/NoSuchMemberException.java create mode 100644 backend/src/main/java/com/allog/dallog/member/service/MemberService.java diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index bca65ed3..7db35c5b 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -1,28 +1,54 @@ package com.allog.dallog.auth.service; import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.auth.support.JwtTokenProvider; import com.allog.dallog.infrastructure.oauth.client.OAuthClient; import com.allog.dallog.infrastructure.oauth.dto.OAuthMember; import com.allog.dallog.infrastructure.oauth.endpoint.OAuthEndpoint; +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.domain.SocialType; +import com.allog.dallog.member.service.MemberService; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Transactional(readOnly = true) @Service public class AuthService { private final OAuthEndpoint oAuthEndpoint; private final OAuthClient oAuthClient; + private final MemberService memberService; + private final JwtTokenProvider jwtTokenProvider; - public AuthService(final OAuthEndpoint oAuthEndpoint, final OAuthClient oAuthClient) { + public AuthService(final OAuthEndpoint oAuthEndpoint, final OAuthClient oAuthClient, + final MemberService memberService, final JwtTokenProvider jwtTokenProvider) { this.oAuthEndpoint = oAuthEndpoint; this.oAuthClient = oAuthClient; + this.memberService = memberService; + this.jwtTokenProvider = jwtTokenProvider; } public String generateGoogleLink() { return oAuthEndpoint.generate(); } + @Transactional public TokenResponse generateTokenWithCode(final String code) { OAuthMember oAuthMember = oAuthClient.getOAuthMember(code); - return null; + String email = oAuthMember.getEmail(); + + if (!memberService.existsByEmail(email)) { + memberService.save(generateMemberBy(oAuthMember)); + } + + Member foundMember = memberService.findByEmail(email); + String accessToken = jwtTokenProvider.createToken(String.valueOf(foundMember.getId())); + + return new TokenResponse(accessToken); + } + + private Member generateMemberBy(final OAuthMember oAuthMember) { + return new Member(oAuthMember.getEmail(), oAuthMember.getProfileImageUrl(), oAuthMember.getDisplayName(), + SocialType.GOOGLE); } } diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java new file mode 100644 index 00000000..16d3b92b --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java @@ -0,0 +1,13 @@ +package com.allog.dallog.infrastructure.oauth.client; + +import com.allog.dallog.infrastructure.oauth.dto.OAuthMember; +import org.springframework.stereotype.Component; + +@Component +public class GoogleOAuthClient implements OAuthClient { + + @Override + public OAuthMember getOAuthMember(final String code) { + return null; + } +} diff --git a/backend/src/main/java/com/allog/dallog/member/domain/MemberRepository.java b/backend/src/main/java/com/allog/dallog/member/domain/MemberRepository.java index c1f1b7d1..07dd2b2b 100644 --- a/backend/src/main/java/com/allog/dallog/member/domain/MemberRepository.java +++ b/backend/src/main/java/com/allog/dallog/member/domain/MemberRepository.java @@ -1,8 +1,11 @@ package com.allog.dallog.member.domain; +import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; public interface MemberRepository extends JpaRepository { + Optional findByEmail(final String email); + boolean existsByEmail(final String email); } diff --git a/backend/src/main/java/com/allog/dallog/member/exception/NoSuchMemberException.java b/backend/src/main/java/com/allog/dallog/member/exception/NoSuchMemberException.java new file mode 100644 index 00000000..2a4be939 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/member/exception/NoSuchMemberException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.member.exception; + +public class NoSuchMemberException extends RuntimeException { + + public NoSuchMemberException() { + super("존재하지 않는 회원입니다."); + } + + public NoSuchMemberException(final String message) { + super(message); + } +} diff --git a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java new file mode 100644 index 00000000..47d148dc --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java @@ -0,0 +1,32 @@ +package com.allog.dallog.member.service; + +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.domain.MemberRepository; +import com.allog.dallog.member.exception.NoSuchMemberException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(readOnly = true) +@Service +public class MemberService { + + private final MemberRepository memberRepository; + + public MemberService(final MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } + + @Transactional + public Member save(final Member member) { + return memberRepository.save(member); + } + + public Member findByEmail(final String email) { + return memberRepository.findByEmail(email) + .orElseThrow(NoSuchMemberException::new); + } + + public boolean existsByEmail(final String email) { + return memberRepository.existsByEmail(email); + } +} diff --git a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java index 7071b04d..66d86293 100644 --- a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java +++ b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java @@ -6,6 +6,6 @@ public class StubOAuthClient implements OAuthClient { @Override public OAuthMember getOAuthMember(final String code) { - return new OAuthMember("Fake Email", "Fake Name", "Fake Profile Image Url"); + return new OAuthMember("dev.hyeonic@gmail.com", "Fake Name", "Fake Profile Image Url"); } } From dcec92e5941902ee739dd218d43c1a78d2dae0c6 Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 14 Jul 2022 15:14:46 +0900 Subject: [PATCH 0097/1011] =?UTF-8?q?feat:=20Configuration=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RestTemplate 관련 - Web Mvc 관련 --- .../dallog/global/config/RestTemplateConfig.java | 14 ++++++++++++++ .../allog/dallog/global/config/WebConfig.java | 16 ++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/global/config/RestTemplateConfig.java create mode 100644 backend/src/main/java/com/allog/dallog/global/config/WebConfig.java diff --git a/backend/src/main/java/com/allog/dallog/global/config/RestTemplateConfig.java b/backend/src/main/java/com/allog/dallog/global/config/RestTemplateConfig.java new file mode 100644 index 00000000..ef5591f1 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/global/config/RestTemplateConfig.java @@ -0,0 +1,14 @@ +package com.allog.dallog.global.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } +} diff --git a/backend/src/main/java/com/allog/dallog/global/config/WebConfig.java b/backend/src/main/java/com/allog/dallog/global/config/WebConfig.java new file mode 100644 index 00000000..23958633 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/global/config/WebConfig.java @@ -0,0 +1,16 @@ +package com.allog.dallog.global.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedMethods("*") + .allowedOriginPatterns("*"); + } +} From bee5a38f9decdc4539d4796e31ccf935b91e0ae7 Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 14 Jul 2022 16:24:15 +0900 Subject: [PATCH 0098/1011] =?UTF-8?q?feat:=20=EA=B5=AC=EA=B8=80=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=A7=81=ED=81=AC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=EA=B5=AC=EA=B8=80=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=EC=9D=84=20=ED=86=B5=ED=95=9C=20=ED=86=A0=ED=81=B0=20=EB=B0=9C?= =?UTF-8?q?=EA=B8=89=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/DallogApplication.java | 1 - .../auth/controller/AuthController.java | 36 ++++++++ .../oauth => auth}/dto/OAuthMember.java | 2 +- .../allog/dallog/auth/dto/TokenRequest.java | 17 ++++ .../dallog/auth/service/AuthService.java | 6 +- .../dallog/auth/support/OAuthClient.java | 9 ++ .../support}/OAuthEndpoint.java | 2 +- .../dallog/global/dto/CommonResponse.java | 17 ++++ .../oauth/client/GoogleOAuthClient.java | 85 ++++++++++++++++++- .../oauth/client/OAuthClient.java | 9 -- .../oauth/dto/GoogleTokenResponse.java | 52 ++++++++++++ .../oauth/endpoint/GoogleOAuthEndpoint.java | 1 + .../src/main/resources/application.properties | 1 + .../com/allog/dallog/config/TestConfig.java | 2 +- .../oauth/client/StubOAuthClient.java | 3 +- .../src/test/resources/application.properties | 2 + 16 files changed, 226 insertions(+), 19 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java rename backend/src/main/java/com/allog/dallog/{infrastructure/oauth => auth}/dto/OAuthMember.java (91%) create mode 100644 backend/src/main/java/com/allog/dallog/auth/dto/TokenRequest.java create mode 100644 backend/src/main/java/com/allog/dallog/auth/support/OAuthClient.java rename backend/src/main/java/com/allog/dallog/{infrastructure/oauth/endpoint => auth/support}/OAuthEndpoint.java (59%) create mode 100644 backend/src/main/java/com/allog/dallog/global/dto/CommonResponse.java delete mode 100644 backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/OAuthClient.java create mode 100644 backend/src/main/java/com/allog/dallog/infrastructure/oauth/dto/GoogleTokenResponse.java diff --git a/backend/src/main/java/com/allog/dallog/DallogApplication.java b/backend/src/main/java/com/allog/dallog/DallogApplication.java index b8454e11..0d989070 100644 --- a/backend/src/main/java/com/allog/dallog/DallogApplication.java +++ b/backend/src/main/java/com/allog/dallog/DallogApplication.java @@ -9,5 +9,4 @@ public class DallogApplication { public static void main(String[] args) { SpringApplication.run(DallogApplication.class, args); } - } diff --git a/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java b/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java new file mode 100644 index 00000000..0458841b --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java @@ -0,0 +1,36 @@ +package com.allog.dallog.auth.controller; + +import com.allog.dallog.auth.dto.TokenRequest; +import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.auth.service.AuthService; +import com.allog.dallog.global.dto.CommonResponse; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/auth") +public class AuthController { + + private final AuthService authService; + + public AuthController(final AuthService authService) { + this.authService = authService; + } + + @GetMapping("/{oauthProvider}/link") + public ResponseEntity> generateLink(@PathVariable final String oauthProvider) { + return ResponseEntity.ok(new CommonResponse<>(authService.generateGoogleLink())); + } + + @PostMapping("/{oauthProvider}/token") + public ResponseEntity> generateToken(@PathVariable final String oauthProvider, + @RequestBody final TokenRequest tokenRequest) { + TokenResponse tokenResponse = authService.generateTokenWithCode(tokenRequest.getCode()); + return ResponseEntity.ok(new CommonResponse<>(tokenResponse)); + } +} diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/dto/OAuthMember.java b/backend/src/main/java/com/allog/dallog/auth/dto/OAuthMember.java similarity index 91% rename from backend/src/main/java/com/allog/dallog/infrastructure/oauth/dto/OAuthMember.java rename to backend/src/main/java/com/allog/dallog/auth/dto/OAuthMember.java index e4bb16e8..be09ce6b 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/dto/OAuthMember.java +++ b/backend/src/main/java/com/allog/dallog/auth/dto/OAuthMember.java @@ -1,4 +1,4 @@ -package com.allog.dallog.infrastructure.oauth.dto; +package com.allog.dallog.auth.dto; public class OAuthMember { diff --git a/backend/src/main/java/com/allog/dallog/auth/dto/TokenRequest.java b/backend/src/main/java/com/allog/dallog/auth/dto/TokenRequest.java new file mode 100644 index 00000000..c8a20113 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/dto/TokenRequest.java @@ -0,0 +1,17 @@ +package com.allog.dallog.auth.dto; + +public class TokenRequest { + + private String code; + + private TokenRequest() { + } + + public TokenRequest(final String code) { + this.code = code; + } + + public String getCode() { + return code; + } +} diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index 7db35c5b..2723ac41 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -1,10 +1,10 @@ package com.allog.dallog.auth.service; +import com.allog.dallog.auth.dto.OAuthMember; import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.auth.support.JwtTokenProvider; -import com.allog.dallog.infrastructure.oauth.client.OAuthClient; -import com.allog.dallog.infrastructure.oauth.dto.OAuthMember; -import com.allog.dallog.infrastructure.oauth.endpoint.OAuthEndpoint; +import com.allog.dallog.auth.support.OAuthClient; +import com.allog.dallog.auth.support.OAuthEndpoint; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.SocialType; import com.allog.dallog.member.service.MemberService; diff --git a/backend/src/main/java/com/allog/dallog/auth/support/OAuthClient.java b/backend/src/main/java/com/allog/dallog/auth/support/OAuthClient.java new file mode 100644 index 00000000..ac718657 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/support/OAuthClient.java @@ -0,0 +1,9 @@ +package com.allog.dallog.auth.support; + +import com.allog.dallog.auth.dto.OAuthMember; + +@FunctionalInterface +public interface OAuthClient { + + OAuthMember getOAuthMember(final String code); +} diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/OAuthEndpoint.java b/backend/src/main/java/com/allog/dallog/auth/support/OAuthEndpoint.java similarity index 59% rename from backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/OAuthEndpoint.java rename to backend/src/main/java/com/allog/dallog/auth/support/OAuthEndpoint.java index b03a9b37..cc24bc08 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/OAuthEndpoint.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/OAuthEndpoint.java @@ -1,4 +1,4 @@ -package com.allog.dallog.infrastructure.oauth.endpoint; +package com.allog.dallog.auth.support; @FunctionalInterface public interface OAuthEndpoint { diff --git a/backend/src/main/java/com/allog/dallog/global/dto/CommonResponse.java b/backend/src/main/java/com/allog/dallog/global/dto/CommonResponse.java new file mode 100644 index 00000000..7378087c --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/global/dto/CommonResponse.java @@ -0,0 +1,17 @@ +package com.allog.dallog.global.dto; + +public class CommonResponse { + + private T data; + + private CommonResponse() { + } + + public CommonResponse(T data) { + this.data = data; + } + + public T getData() { + return data; + } +} diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java index 16d3b92b..84b2f4af 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java @@ -1,13 +1,94 @@ package com.allog.dallog.infrastructure.oauth.client; -import com.allog.dallog.infrastructure.oauth.dto.OAuthMember; +import com.allog.dallog.auth.dto.OAuthMember; +import com.allog.dallog.auth.support.OAuthClient; +import com.allog.dallog.infrastructure.oauth.dto.GoogleTokenResponse; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; @Component public class GoogleOAuthClient implements OAuthClient { + private static final String JWT_DELIMITER = "\\."; + + private final String googleRedirectUri; + private final String googleClientId; + private final String googleClientSecret; + private final String googleTokenUri; + private final RestTemplate restTemplate; + private final ObjectMapper objectMapper; + + public GoogleOAuthClient(@Value("${oauth.google.redirect_uri}") final String googleRedirectUri, + @Value("${oauth.google.client_id}") final String googleClientId, + @Value("${oauth.google.client_secret}") final String googleClientSecret, + @Value("${oauth.google.token_uri}") final String googleTokenUri, + final RestTemplate restTemplate, final ObjectMapper objectMapper) { + this.googleRedirectUri = googleRedirectUri; + this.googleClientId = googleClientId; + this.googleClientSecret = googleClientSecret; + this.googleTokenUri = googleTokenUri; + this.restTemplate = restTemplate; + this.objectMapper = objectMapper; + } + @Override public OAuthMember getOAuthMember(final String code) { - return null; + GoogleTokenResponse googleTokenResponse = requestGoogleToken(code); + String payload = getPayloadFrom(googleTokenResponse.getIdToken()); + String decodedPayload = decodeJwtPayload(payload); + + try { + return generateOAuthMemberBy(decodedPayload); + } catch (JsonProcessingException e) { + throw new IllegalArgumentException(); + } + } + + private GoogleTokenResponse requestGoogleToken(final String code) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + MultiValueMap params = generateRequestParams(code); + + HttpEntity> request = new HttpEntity<>(params, headers); + return restTemplate.postForEntity(googleTokenUri, request, GoogleTokenResponse.class).getBody(); + } + + private MultiValueMap generateRequestParams(final String code) { + MultiValueMap params = new LinkedMultiValueMap<>(); + params.add("client_id", googleClientId); + params.add("client_secret", googleClientSecret); + params.add("code", code); + params.add("grant_type", "authorization_code"); + params.add("redirect_uri", googleRedirectUri); + return params; + } + + private String getPayloadFrom(final String jwt) { + return jwt.split(JWT_DELIMITER)[1]; + } + + private String decodeJwtPayload(final String payload) { + return new String(Base64.getUrlDecoder().decode(payload), StandardCharsets.UTF_8); + } + + private OAuthMember generateOAuthMemberBy(final String decodedIdToken) throws JsonProcessingException { + Map userInfo = objectMapper.readValue(decodedIdToken, HashMap.class); + String email = userInfo.get("email"); + String displayName = userInfo.get("name"); + String profileImageUrl = userInfo.get("picture"); + + return new OAuthMember(email, displayName, profileImageUrl); } } diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/OAuthClient.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/OAuthClient.java deleted file mode 100644 index ff95d7de..00000000 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/OAuthClient.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.allog.dallog.infrastructure.oauth.client; - -import com.allog.dallog.infrastructure.oauth.dto.OAuthMember; - -@FunctionalInterface -public interface OAuthClient { - - OAuthMember getOAuthMember(final String code); -} diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/dto/GoogleTokenResponse.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/dto/GoogleTokenResponse.java new file mode 100644 index 00000000..ec979965 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/dto/GoogleTokenResponse.java @@ -0,0 +1,52 @@ +package com.allog.dallog.infrastructure.oauth.dto; + +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; + +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +public class GoogleTokenResponse { + + private String accessToken; + private String refreshToken; + private String idToken; + private String expiresIn; + private String tokenType; + private String scope; + + private GoogleTokenResponse() { + } + + public GoogleTokenResponse(final String accessToken, final String refreshToken, final String idToken, + final String expiresIn, final String scope, final String tokenType) { + this.accessToken = accessToken; + this.refreshToken = refreshToken; + this.idToken = idToken; + this.expiresIn = expiresIn; + this.scope = scope; + this.tokenType = tokenType; + } + + public String getAccessToken() { + return accessToken; + } + + public String getRefreshToken() { + return refreshToken; + } + + public String getIdToken() { + return idToken; + } + + public String getExpiresIn() { + return expiresIn; + } + + public String getScope() { + return scope; + } + + public String getTokenType() { + return tokenType; + } +} diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/GoogleOAuthEndpoint.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/GoogleOAuthEndpoint.java index b981b976..32ed4491 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/GoogleOAuthEndpoint.java +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/GoogleOAuthEndpoint.java @@ -1,5 +1,6 @@ package com.allog.dallog.infrastructure.oauth.endpoint; +import com.allog.dallog.auth.support.OAuthEndpoint; import java.util.List; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 49ff2a94..37537561 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -7,5 +7,6 @@ logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE oauth.google.redirect_uri=${GOOGLE_REDIRECT_URI} oauth.google.client_id=${GOOGLE_CLIENT_ID} oauth.google.client_secret=${GOOGLE_CLIENT_SECRET} +oauth.google.token_uri=${GOOGLE_TOKEN_URI} security.jwt.token.secret-key=${JWT_SECRET_KEY} security.jwt.token.expire-length=${JWT_EXPIRE_LENGTH} diff --git a/backend/src/test/java/com/allog/dallog/config/TestConfig.java b/backend/src/test/java/com/allog/dallog/config/TestConfig.java index 1ee28fa4..0aebbe38 100644 --- a/backend/src/test/java/com/allog/dallog/config/TestConfig.java +++ b/backend/src/test/java/com/allog/dallog/config/TestConfig.java @@ -1,6 +1,6 @@ package com.allog.dallog.config; -import com.allog.dallog.infrastructure.oauth.client.OAuthClient; +import com.allog.dallog.auth.support.OAuthClient; import com.allog.dallog.infrastructure.oauth.client.StubOAuthClient; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; diff --git a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java index 66d86293..616dbb44 100644 --- a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java +++ b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java @@ -1,6 +1,7 @@ package com.allog.dallog.infrastructure.oauth.client; -import com.allog.dallog.infrastructure.oauth.dto.OAuthMember; +import com.allog.dallog.auth.dto.OAuthMember; +import com.allog.dallog.auth.support.OAuthClient; public class StubOAuthClient implements OAuthClient { diff --git a/backend/src/test/resources/application.properties b/backend/src/test/resources/application.properties index b5e9ced5..b7823bc2 100644 --- a/backend/src/test/resources/application.properties +++ b/backend/src/test/resources/application.properties @@ -4,8 +4,10 @@ spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE +spring.main.allow-bean-definition-overriding=true oauth.google.redirect_uri=http://localhost:3000 oauth.google.client_id=hyeonic oauth.google.client_secret=123 +oauth.google.token_uri=https://oauth2.googleapis.com/token security.jwt.token.secret-key=fsmjgbdafmjgbasmfgadbsgmadfhgbfamjghbvmssdgsdfgdf security.jwt.token.expire-length=3600 From 490693a1eb2ff46acbeb9d131440f991086851f8 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 14 Jul 2022 17:01:57 +0900 Subject: [PATCH 0099/1011] =?UTF-8?q?refactor:=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=EC=97=90=20=ED=98=84=EC=9E=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?=EB=84=98=EB=B2=84=EC=99=80=20=EC=A0=84=EC=B2=B4=20=EA=B0=9C?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FindSliceResponse 추가 --- .../controller/CategoryController.java | 12 ++++----- .../category/service/CategoryService.java | 7 +++-- .../dallog/global/dto/FindSliceResponse.java | 27 +++++++++++++++++++ .../allog/dallog/global/dto/ListResponse.java | 2 +- .../acceptance/CategoryAcceptanceTest.java | 8 +++--- .../category/service/CategoryServiceTest.java | 20 +++++++------- 6 files changed, 52 insertions(+), 24 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/global/dto/FindSliceResponse.java diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index ef0c0511..e8efac4c 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -3,9 +3,8 @@ import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; -import com.allog.dallog.global.dto.ListResponse; +import com.allog.dallog.global.dto.FindSliceResponse; import java.net.URI; -import java.util.List; import javax.validation.Valid; import org.springframework.data.domain.PageRequest; import org.springframework.http.ResponseEntity; @@ -33,10 +32,9 @@ public ResponseEntity save(@Valid @RequestBody final CategoryCreateRequest } @GetMapping - public ResponseEntity> findSliceBy(@RequestParam final int page, - @RequestParam final int size) { - PageRequest pageRequest = PageRequest.of(page - 1, size); - List responses = categoryService.findSliceBy(pageRequest); - return ResponseEntity.ok(new ListResponse<>(responses)); + public ResponseEntity> findSliceBy(@RequestParam final int page, + @RequestParam final int size) { + PageRequest pageRequest = PageRequest.of(page, size); + return ResponseEntity.ok(categoryService.findSliceBy(pageRequest)); } } diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index d99961d1..3e144a6b 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -4,6 +4,7 @@ import com.allog.dallog.category.domain.CategoryRepository; import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; +import com.allog.dallog.global.dto.FindSliceResponse; import java.util.List; import java.util.stream.Collectors; import org.springframework.data.domain.PageRequest; @@ -26,11 +27,13 @@ public Long save(final CategoryCreateRequest request) { return category.getId(); } - public List findSliceBy(final PageRequest request) { - return categoryRepository.findSliceBy(request) + public FindSliceResponse findSliceBy(final PageRequest request) { + long count = categoryRepository.count(); + List responses = categoryRepository.findSliceBy(request.previousOrFirst()) .getContent() .stream() .map(CategoryResponse::new) .collect(Collectors.toList()); + return new FindSliceResponse<>(request.getPageNumber(), count, responses); } } diff --git a/backend/src/main/java/com/allog/dallog/global/dto/FindSliceResponse.java b/backend/src/main/java/com/allog/dallog/global/dto/FindSliceResponse.java new file mode 100644 index 00000000..cab283c0 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/global/dto/FindSliceResponse.java @@ -0,0 +1,27 @@ +package com.allog.dallog.global.dto; + +import java.util.List; + +public class FindSliceResponse extends ListResponse { + + private int page; + private long totalCount; + + private FindSliceResponse() { + super(); + } + + public FindSliceResponse(final int page, final long totalCount, final List categoryResponses) { + super(categoryResponses); + this.page = page; + this.totalCount = totalCount; + } + + public int getPage() { + return page; + } + + public long getTotalCount() { + return totalCount; + } +} diff --git a/backend/src/main/java/com/allog/dallog/global/dto/ListResponse.java b/backend/src/main/java/com/allog/dallog/global/dto/ListResponse.java index fb53fe7c..8090f06c 100644 --- a/backend/src/main/java/com/allog/dallog/global/dto/ListResponse.java +++ b/backend/src/main/java/com/allog/dallog/global/dto/ListResponse.java @@ -6,7 +6,7 @@ public class ListResponse { private List data; - private ListResponse() { + protected ListResponse() { } public ListResponse(List data) { diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 576e49e2..99ef5627 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -4,7 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.category.dto.request.CategoryCreateRequest; -import com.allog.dallog.global.dto.ListResponse; +import com.allog.dallog.global.dto.FindSliceResponse; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; @@ -41,12 +41,14 @@ public class CategoryAcceptanceTest extends AcceptanceTest { // when ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(page, size); - ListResponse categoryResponses = response.as(ListResponse.class); + FindSliceResponse findSliceResponse = response.as(FindSliceResponse.class); // then assertAll( () -> 상태코드_200이_반환된다(response), - () -> assertThat(categoryResponses.getData()).hasSize(3) + () -> assertThat(findSliceResponse.getPage()).isEqualTo(page), + () -> assertThat(findSliceResponse.getTotalCount()).isEqualTo(3), + () -> assertThat(findSliceResponse.getData()).hasSize(3) ); } diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 99ce26f9..69969b4c 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -2,11 +2,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.exception.InvalidCategoryException; -import java.util.List; +import com.allog.dallog.global.dto.FindSliceResponse; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -37,15 +38,13 @@ class CategoryServiceTest { @DisplayName("새로운 카테고리를 생성 할 떄 이름이 공백이거나 길이가 20을 초과하는 경우 예외를 던진다.") @ParameterizedTest - @ValueSource(strings = {"", "일이삼사오육칠팔구십일이삼사오육칠팔구십일", - "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 카테고리"}) + @ValueSource(strings = {"", "일이삼사오육칠팔구십일이삼사오육칠팔구십일", "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 카테고리"}) void 새로운_카테고리를_생성_할_때_이름이_공백이거나_길이가_20을_초과하는_경우_예외를_던진다(final String name) { // given CategoryCreateRequest request = new CategoryCreateRequest(name); // when & then - assertThatThrownBy(() -> categoryService.save(request)). - isInstanceOf(InvalidCategoryException.class); + assertThatThrownBy(() -> categoryService.save(request)).isInstanceOf(InvalidCategoryException.class); } @DisplayName("페이지를 받아 해당하는 구간의 카테고리를 가져온다.") @@ -58,17 +57,16 @@ class CategoryServiceTest { categoryService.save(new CategoryCreateRequest("지원플랫폼 근로")); categoryService.save(new CategoryCreateRequest("파랑의 코틀린 스터디")); - int page = 1; + int page = 2; int size = 2; PageRequest request = PageRequest.of(page, size); // when - List response = categoryService.findSliceBy(request); + FindSliceResponse response = categoryService.findSliceBy(request); // then - assertThat(response) - .hasSize(size) - .extracting(CategoryResponse::getName) - .contains("알록달록 회의", "지원플랫폼 근로"); + assertAll(() -> assertThat(response.getData()).hasSize(size).extracting(CategoryResponse::getName) + .contains("알록달록 회의", "지원플랫폼 근로"), () -> assertThat(response.getPage()).isEqualTo(page), + () -> assertThat(response.getTotalCount()).isEqualTo(5)); } } From a6ae1640eb6f65e47cd2b92d9430460c59091964 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Fri, 15 Jul 2022 00:17:49 +0900 Subject: [PATCH 0100/1011] =?UTF-8?q?refactor:=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4,=20=EB=A9=94=EC=84=9C=EB=93=9C,=20=EB=B3=80=EC=88=98?= =?UTF-8?q?=EB=AA=85=20=EB=B0=8F=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CategoryController.java | 8 +++--- .../category/service/CategoryService.java | 7 +++-- .../dallog/global/dto/FindByPageResponse.java | 21 +++++++++++++++ .../dallog/global/dto/FindSliceResponse.java | 27 ------------------- .../acceptance/CategoryAcceptanceTest.java | 15 +++++------ .../domain/CategoryRepositoryTest.java | 2 +- .../category/service/CategoryServiceTest.java | 17 +++++++----- 7 files changed, 47 insertions(+), 50 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/global/dto/FindByPageResponse.java delete mode 100644 backend/src/main/java/com/allog/dallog/global/dto/FindSliceResponse.java diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index e8efac4c..20c44e47 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -3,7 +3,7 @@ import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; -import com.allog.dallog.global.dto.FindSliceResponse; +import com.allog.dallog.global.dto.FindByPageResponse; import java.net.URI; import javax.validation.Valid; import org.springframework.data.domain.PageRequest; @@ -32,9 +32,9 @@ public ResponseEntity save(@Valid @RequestBody final CategoryCreateRequest } @GetMapping - public ResponseEntity> findSliceBy(@RequestParam final int page, - @RequestParam final int size) { + public ResponseEntity> findAll(@RequestParam final int page, + @RequestParam final int size) { PageRequest pageRequest = PageRequest.of(page, size); - return ResponseEntity.ok(categoryService.findSliceBy(pageRequest)); + return ResponseEntity.ok(categoryService.findAll(pageRequest)); } } diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index 3e144a6b..a00c675e 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -4,7 +4,7 @@ import com.allog.dallog.category.domain.CategoryRepository; import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; -import com.allog.dallog.global.dto.FindSliceResponse; +import com.allog.dallog.global.dto.FindByPageResponse; import java.util.List; import java.util.stream.Collectors; import org.springframework.data.domain.PageRequest; @@ -27,13 +27,12 @@ public Long save(final CategoryCreateRequest request) { return category.getId(); } - public FindSliceResponse findSliceBy(final PageRequest request) { - long count = categoryRepository.count(); + public FindByPageResponse findAll(final PageRequest request) { List responses = categoryRepository.findSliceBy(request.previousOrFirst()) .getContent() .stream() .map(CategoryResponse::new) .collect(Collectors.toList()); - return new FindSliceResponse<>(request.getPageNumber(), count, responses); + return new FindByPageResponse<>(request.getPageNumber(), responses); } } diff --git a/backend/src/main/java/com/allog/dallog/global/dto/FindByPageResponse.java b/backend/src/main/java/com/allog/dallog/global/dto/FindByPageResponse.java new file mode 100644 index 00000000..14df3bf0 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/global/dto/FindByPageResponse.java @@ -0,0 +1,21 @@ +package com.allog.dallog.global.dto; + +import java.util.List; + +public class FindByPageResponse extends ListResponse { + + private int page; + + private FindByPageResponse() { + super(); + } + + public FindByPageResponse(final int page, final List responses) { + super(responses); + this.page = page; + } + + public int getPage() { + return page; + } +} diff --git a/backend/src/main/java/com/allog/dallog/global/dto/FindSliceResponse.java b/backend/src/main/java/com/allog/dallog/global/dto/FindSliceResponse.java deleted file mode 100644 index cab283c0..00000000 --- a/backend/src/main/java/com/allog/dallog/global/dto/FindSliceResponse.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.allog.dallog.global.dto; - -import java.util.List; - -public class FindSliceResponse extends ListResponse { - - private int page; - private long totalCount; - - private FindSliceResponse() { - super(); - } - - public FindSliceResponse(final int page, final long totalCount, final List categoryResponses) { - super(categoryResponses); - this.page = page; - this.totalCount = totalCount; - } - - public int getPage() { - return page; - } - - public long getTotalCount() { - return totalCount; - } -} diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 99ef5627..99a6b18e 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -4,7 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.category.dto.request.CategoryCreateRequest; -import com.allog.dallog.global.dto.FindSliceResponse; +import com.allog.dallog.global.dto.FindByPageResponse; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; @@ -41,15 +41,14 @@ public class CategoryAcceptanceTest extends AcceptanceTest { // when ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(page, size); - FindSliceResponse findSliceResponse = response.as(FindSliceResponse.class); + FindByPageResponse findByPageResponse = response.as(FindByPageResponse.class); // then - assertAll( - () -> 상태코드_200이_반환된다(response), - () -> assertThat(findSliceResponse.getPage()).isEqualTo(page), - () -> assertThat(findSliceResponse.getTotalCount()).isEqualTo(3), - () -> assertThat(findSliceResponse.getData()).hasSize(3) - ); + assertAll(() -> { + 상태코드_200이_반환된다(response); + assertThat(findByPageResponse.getPage()).isEqualTo(page); + assertThat(findByPageResponse.getData()).hasSize(3); + }); } private ExtractableResponse 새로운_카테고리를_등록한다(final String name) { diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java index 7aba7ca4..640e2748 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java @@ -17,7 +17,7 @@ class CategoryRepositoryTest { @DisplayName("페이지와 사이즈를 받아 해당하는 구간의 카테고리를 조회한다.") @Test - void 페이지와_리밋을_받아_해당하는_구간의_카테고리를_조회한다() { + void 페이지와_사이즈를_받아_해당하는_구간의_카테고리를_조회한다() { // given categoryRepository.save(new Category("BE 공식일정")); categoryRepository.save(new Category("FE 공식일정")); diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 69969b4c..c66c225b 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -7,7 +7,7 @@ import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.exception.InvalidCategoryException; -import com.allog.dallog.global.dto.FindSliceResponse; +import com.allog.dallog.global.dto.FindByPageResponse; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -44,7 +44,8 @@ class CategoryServiceTest { CategoryCreateRequest request = new CategoryCreateRequest(name); // when & then - assertThatThrownBy(() -> categoryService.save(request)).isInstanceOf(InvalidCategoryException.class); + assertThatThrownBy(() -> categoryService.save(request)) + .isInstanceOf(InvalidCategoryException.class); } @DisplayName("페이지를 받아 해당하는 구간의 카테고리를 가져온다.") @@ -62,11 +63,15 @@ class CategoryServiceTest { PageRequest request = PageRequest.of(page, size); // when - FindSliceResponse response = categoryService.findSliceBy(request); + FindByPageResponse response = categoryService.findAll(request); // then - assertAll(() -> assertThat(response.getData()).hasSize(size).extracting(CategoryResponse::getName) - .contains("알록달록 회의", "지원플랫폼 근로"), () -> assertThat(response.getPage()).isEqualTo(page), - () -> assertThat(response.getTotalCount()).isEqualTo(5)); + assertAll(() -> { + assertThat(response.getData()) + .hasSize(size) + .extracting(CategoryResponse::getName) + .contains("알록달록 회의", "지원플랫폼 근로"); + assertThat(response.getPage()).isEqualTo(page); + }); } } From 870ee7395dc97ceeb08232a15bebcb9d359dd451 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 14 Jul 2022 16:12:07 +0900 Subject: [PATCH 0101/1011] =?UTF-8?q?feat:=20JPA=20auditing=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BaseEntity에 생성일시와 수정일시 구현 - 다른 Entity가 상속받도록 수정 - test 추가 --- .../com/allog/dallog/DallogApplication.java | 2 ++ .../dallog/category/domain/Category.java | 12 ++------ .../dallog/global/domain/BaseEntity.java | 30 +++++++++++++++++++ .../dallog/schedule/domain/Schedule.java | 3 +- .../domain/CategoryRepositoryTest.java | 16 +++++++--- 5 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/global/domain/BaseEntity.java diff --git a/backend/src/main/java/com/allog/dallog/DallogApplication.java b/backend/src/main/java/com/allog/dallog/DallogApplication.java index b8454e11..96499e12 100644 --- a/backend/src/main/java/com/allog/dallog/DallogApplication.java +++ b/backend/src/main/java/com/allog/dallog/DallogApplication.java @@ -2,7 +2,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +@EnableJpaAuditing @SpringBootApplication public class DallogApplication { diff --git a/backend/src/main/java/com/allog/dallog/category/domain/Category.java b/backend/src/main/java/com/allog/dallog/category/domain/Category.java index 2c9908a1..0915bb03 100644 --- a/backend/src/main/java/com/allog/dallog/category/domain/Category.java +++ b/backend/src/main/java/com/allog/dallog/category/domain/Category.java @@ -1,7 +1,7 @@ package com.allog.dallog.category.domain; import com.allog.dallog.category.exception.InvalidCategoryException; -import java.time.LocalDateTime; +import com.allog.dallog.global.domain.BaseEntity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -11,7 +11,7 @@ @Table(name = "categories") @Entity -public class Category { +public class Category extends BaseEntity { public static final int MAX_NAME_LENGTH = 20; @@ -23,16 +23,12 @@ public class Category { @Column(name = "name", nullable = false) private String name; - @Column(name = "created_at", nullable = false) - private LocalDateTime createdAt; - protected Category() { } public Category(final String name) { validateNameLength(name); this.name = name; - this.createdAt = LocalDateTime.now(); } private void validateNameLength(final String name) { @@ -51,8 +47,4 @@ public Long getId() { public String getName() { return name; } - - public LocalDateTime getCreatedAt() { - return createdAt; - } } diff --git a/backend/src/main/java/com/allog/dallog/global/domain/BaseEntity.java b/backend/src/main/java/com/allog/dallog/global/domain/BaseEntity.java new file mode 100644 index 00000000..4bf55527 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/global/domain/BaseEntity.java @@ -0,0 +1,30 @@ +package com.allog.dallog.global.domain; + +import java.time.LocalDateTime; +import javax.persistence.Column; +import javax.persistence.EntityListeners; +import javax.persistence.MappedSuperclass; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public abstract class BaseEntity { + + @CreatedDate + @Column(name = "created_at", updatable = false) + private LocalDateTime createdAt; + + @LastModifiedDate + @Column(name = "updated_at", updatable = false) + private LocalDateTime updatedAt; + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } +} diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java index 0e4017ed..d852cd01 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java +++ b/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java @@ -1,5 +1,6 @@ package com.allog.dallog.schedule.domain; +import com.allog.dallog.global.domain.BaseEntity; import com.allog.dallog.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; import javax.persistence.Column; @@ -12,7 +13,7 @@ @Table(name = "schedules") @Entity -public class Schedule { +public class Schedule extends BaseEntity { private static final int MAX_TITLE_LENGTH = 20; private static final int MAX_MEMO_LENGTH = 255; diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java index 640e2748..bd4abcc5 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java @@ -1,7 +1,9 @@ package com.allog.dallog.category.domain; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import java.util.Objects; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -33,10 +35,16 @@ class CategoryRepositoryTest { Slice categories = categoryRepository.findSliceBy(pageRequest); // then - assertThat(categories.getContent()) - .hasSize(size) - .extracting(Category::getName) - .contains("알록달록 회의", "지원플랫폼 근로"); + assertAll( + () -> assertThat(categories.getContent()) + .hasSize(size) + .extracting(Category::getName) + .contains("알록달록 회의", "지원플랫폼 근로"), + () -> assertThat(categories.getContent().stream() + .map(Category::getCreatedAt) + .allMatch(Objects::nonNull)) + .isTrue() + ); } @DisplayName("조회 시 데이터가 존재하지 않는 경우 빈 슬라이스가 반환된다.") From f22af63d4ce24692b936c6c5de8d531dd3557d07 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Fri, 15 Jul 2022 15:46:35 +0900 Subject: [PATCH 0102/1011] =?UTF-8?q?fix:=20=EC=96=B4=EB=85=B8=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/allog/dallog/global/domain/BaseEntity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/global/domain/BaseEntity.java b/backend/src/main/java/com/allog/dallog/global/domain/BaseEntity.java index 4bf55527..a802b802 100644 --- a/backend/src/main/java/com/allog/dallog/global/domain/BaseEntity.java +++ b/backend/src/main/java/com/allog/dallog/global/domain/BaseEntity.java @@ -13,11 +13,11 @@ public abstract class BaseEntity { @CreatedDate - @Column(name = "created_at", updatable = false) + @Column(name = "created_at", nullable = false, updatable = false) private LocalDateTime createdAt; @LastModifiedDate - @Column(name = "updated_at", updatable = false) + @Column(name = "updated_at") private LocalDateTime updatedAt; public LocalDateTime getCreatedAt() { From e180f4bbbdbef0bb0608ca6508b11ac70fa4148e Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Fri, 15 Jul 2022 15:47:59 +0900 Subject: [PATCH 0103/1011] =?UTF-8?q?refactor:=20JPA=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/allog/dallog/DallogApplication.java | 2 -- .../java/com/allog/dallog/global/config/JpaConfig.java | 9 +++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/global/config/JpaConfig.java diff --git a/backend/src/main/java/com/allog/dallog/DallogApplication.java b/backend/src/main/java/com/allog/dallog/DallogApplication.java index 96499e12..b8454e11 100644 --- a/backend/src/main/java/com/allog/dallog/DallogApplication.java +++ b/backend/src/main/java/com/allog/dallog/DallogApplication.java @@ -2,9 +2,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -@EnableJpaAuditing @SpringBootApplication public class DallogApplication { diff --git a/backend/src/main/java/com/allog/dallog/global/config/JpaConfig.java b/backend/src/main/java/com/allog/dallog/global/config/JpaConfig.java new file mode 100644 index 00000000..6397a069 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/global/config/JpaConfig.java @@ -0,0 +1,9 @@ +package com.allog.dallog.global.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +@Configuration +@EnableJpaAuditing +public class JpaConfig { +} From 3a7fde50538ade273a34ab834afb953bb9eea165 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Thu, 14 Jul 2022 15:04:24 +0900 Subject: [PATCH 0104/1011] =?UTF-8?q?chore:=20prettier=20import=20order=20?= =?UTF-8?q?=EA=B7=9C=EC=B9=99=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/.prettierrc.json | 15 +++- frontend/package.json | 2 + frontend/yarn.lock | 139 +++++++++++++++++++++++++++++++++++--- 3 files changed, 146 insertions(+), 10 deletions(-) diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json index c9a045c4..03007670 100644 --- a/frontend/.prettierrc.json +++ b/frontend/.prettierrc.json @@ -8,5 +8,18 @@ "bracketSpacing": true, "bracketSameLine": false, "arrowParens": "always", - "endOfLine": "auto" + "endOfLine": "auto", + "importOrder": [ + "@/hooks/(.*)$", + "@/@types", + "@/styles/(.*)$", + "@/(components/@common/|components/|pages/)(.*)$", + "@/constants", + "@/utils", + "@/(api|mocks)/(.*)$", + "^[./]" + ], + "importOrderSeparation": true, + "importOrderSortSpecifiers": true, + "importOrderCaseInsensitive": true } diff --git a/frontend/package.json b/frontend/package.json index bc46ff3c..465d31d6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,6 +10,7 @@ "start": "webpack --mode development", "storybook": "start-storybook -p 6006", "build-storybook": "build-storybook", + "pretty": "prettier . --write", "check-lint": "eslint . --ext .js,.jsx,.ts,.tsx", "check-prettier": "prettier -c ./src" }, @@ -37,6 +38,7 @@ "@storybook/manager-webpack5": "^6.5.9", "@storybook/react": "^6.5.9", "@storybook/testing-library": "^0.0.13", + "@trivago/prettier-plugin-sort-imports": "^3.2.0", "@types/body-parser": "^1.19.2", "@types/graceful-fs": "^4.1.5", "@types/node": "^18.0.1", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 1d5d3b04..dbdafed2 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -10,7 +10,7 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.5.5", "@babel/code-frame@^7.8.3": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== @@ -44,6 +44,28 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/core@7.13.10": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.10.tgz#07de050bbd8193fcd8a3c27918c0890613a94559" + integrity sha512-bfIYcT0BdKeAZrovpMqX2Mx5NrgAckGbwT982AkdS5GNfn3KMGiprlBAtmBcFZRUmpaufS6WZFP8trvx8ptFDw== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.9" + "@babel/helper-compilation-targets" "^7.13.10" + "@babel/helper-module-transforms" "^7.13.0" + "@babel/helpers" "^7.13.10" + "@babel/parser" "^7.13.10" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + lodash "^4.17.19" + semver "^6.3.0" + source-map "^0.5.0" + "@babel/core@^7.1.0", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.18.6", "@babel/core@^7.7.5": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.6.tgz#54a107a3c298aee3fe5e1947a6464b9b6faca03d" @@ -65,7 +87,16 @@ json5 "^2.2.1" semver "^6.3.0" -"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.18.6": +"@babel/generator@7.13.9": + version "7.13.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.9.tgz#3a7aa96f9efb8e2be42d38d80e2ceb4c64d8de39" + integrity sha512-mHOOmY0Axl/JCTkxTU6Lf5sWOg/v8nUa+Xkt4zMTftX0wqmb6Sh7J8gvcehBw7q0AhrhAR+FDacKjCZ2X8K+Sw== + dependencies: + "@babel/types" "^7.13.0" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.13.0", "@babel/generator@^7.13.9", "@babel/generator@^7.18.6", "@babel/generator@^7.18.7": version "7.18.7" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.7.tgz#2aa78da3c05aadfc82dbac16c99552fc802284bd" integrity sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A== @@ -89,7 +120,7 @@ "@babel/helper-explode-assignable-expression" "^7.18.6" "@babel/types" "^7.18.6" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.18.6": +"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.13.10", "@babel/helper-compilation-targets@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz#18d35bfb9f83b1293c22c55b3d576c1315b6ed96" integrity sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg== @@ -160,7 +191,7 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-function-name@^7.18.6": +"@babel/helper-function-name@^7.12.13", "@babel/helper-function-name@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz#8334fecb0afba66e6d87a7e8c6bb7fed79926b83" integrity sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw== @@ -203,6 +234,20 @@ "@babel/traverse" "^7.18.6" "@babel/types" "^7.18.6" +"@babel/helper-module-transforms@^7.13.0": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.8.tgz#4f8408afead0188cfa48672f9d0e5787b61778c8" + integrity sha512-che3jvZwIcZxrwh63VfnFTUzcAM9v/lznYkkRxIBGMPt1SudOKHAEec0SIRCfiuIzTcF7VGj/CaTT6gY4eWxvA== + dependencies: + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.18.6" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.8" + "@babel/types" "^7.18.8" + "@babel/helper-optimise-call-expression@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" @@ -255,14 +300,14 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-split-export-declaration@^7.18.6": +"@babel/helper-split-export-declaration@^7.12.13", "@babel/helper-split-export-declaration@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== dependencies: "@babel/types" "^7.18.6" -"@babel/helper-validator-identifier@^7.18.6": +"@babel/helper-validator-identifier@^7.12.11", "@babel/helper-validator-identifier@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== @@ -282,7 +327,7 @@ "@babel/traverse" "^7.18.6" "@babel/types" "^7.18.6" -"@babel/helpers@^7.12.5", "@babel/helpers@^7.18.6": +"@babel/helpers@^7.12.5", "@babel/helpers@^7.13.10", "@babel/helpers@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.6.tgz#4c966140eaa1fcaa3d5a8c09d7db61077d4debfd" integrity sha512-vzSiiqbQOghPngUYt/zWGvK3LAsPhz55vc9XNN0xAl2gV4ieShI2OQli5duxWHD+72PZPTKAcfcZDE1Cwc5zsQ== @@ -300,11 +345,21 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/parser@7.14.6": + version "7.14.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.6.tgz#d85cc68ca3cac84eae384c06f032921f5227f4b2" + integrity sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ== + "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.6.tgz#845338edecad65ebffef058d3be851f1d28a63bc" integrity sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw== +"@babel/parser@^7.13.0", "@babel/parser@^7.13.10", "@babel/parser@^7.18.8": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.8.tgz#822146080ac9c62dac0823bb3489622e0bc1cbdf" + integrity sha512-RSKRfYX20dyH+elbJK2uqAkVyucL+xXzhqlMD5/ZXx+dAAwpyB7HsvnHe/ZUGOF+xLr5Wx9/JoXVTj6BQE2/oA== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" @@ -1081,7 +1136,7 @@ dependencies: regenerator-runtime "^0.13.2" -"@babel/template@^7.12.7", "@babel/template@^7.18.6": +"@babel/template@^7.12.13", "@babel/template@^7.12.7", "@babel/template@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31" integrity sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw== @@ -1090,6 +1145,21 @@ "@babel/parser" "^7.18.6" "@babel/types" "^7.18.6" +"@babel/traverse@7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.0.tgz#6d95752475f86ee7ded06536de309a65fc8966cc" + integrity sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.0" + "@babel/helper-function-name" "^7.12.13" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/parser" "^7.13.0" + "@babel/types" "^7.13.0" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + "@babel/traverse@^7.1.6", "@babel/traverse@^7.12.11", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.6.tgz#a228562d2f46e89258efa4ddd0416942e2fd671d" @@ -1106,6 +1176,31 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.18.8": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.8.tgz#f095e62ab46abf1da35e5a2011f43aee72d8d5b0" + integrity sha512-UNg/AcSySJYR/+mIcJQDCv00T+AqRO7j/ZEJLzpaYtgM48rMg5MnkJgyNqkzo88+p4tfRvZJCEiwwfG6h4jkRg== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.18.7" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.18.8" + "@babel/types" "^7.18.8" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.0.tgz#74424d2816f0171b4100f0ab34e9a374efdf7f80" + integrity sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@babel/types@^7.12.11", "@babel/types@^7.12.7", "@babel/types@^7.18.6", "@babel/types@^7.18.7", "@babel/types@^7.2.0", "@babel/types@^7.4.4": version "7.18.7" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.7.tgz#a4a2c910c15040ea52cdd1ddb1614a65c8041726" @@ -1114,6 +1209,14 @@ "@babel/helper-validator-identifier" "^7.18.6" to-fast-properties "^2.0.0" +"@babel/types@^7.13.0", "@babel/types@^7.18.8": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.8.tgz#c5af199951bf41ba4a6a9a6d0d8ad722b30cd42f" + integrity sha512-qwpdsmraq0aJ3osLJRApsc2ouSJCdnMeZwB0DhbtHAtRpZNZCdlbRnHIgcRKzdE1g0iOGg644fzjOBcdOz9cPw== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + to-fast-properties "^2.0.0" + "@base2/pretty-print-object@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz#371ba8be66d556812dc7fb169ebc3c08378f69d4" @@ -2538,6 +2641,19 @@ dependencies: "@babel/runtime" "^7.12.5" +"@trivago/prettier-plugin-sort-imports@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-3.2.0.tgz#7a32b6b3085c436eda0143b2710c440a4a56db90" + integrity sha512-DnwLe+z8t/dZX5xBbYZV1+C5STkyK/P6SSq3Nk6NXlJZsgvDZX2eN4ND7bMFgGV/NL/YChWzcNf6ziGba1ktQQ== + dependencies: + "@babel/core" "7.13.10" + "@babel/generator" "7.13.9" + "@babel/parser" "7.14.6" + "@babel/traverse" "7.13.0" + "@babel/types" "7.13.0" + javascript-natural-sort "0.7.1" + lodash "4.17.21" + "@types/aria-query@^4.2.0": version "4.2.2" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc" @@ -7453,6 +7569,11 @@ iterate-value@^1.0.2: es-get-iterator "^1.0.2" iterate-iterator "^1.0.1" +javascript-natural-sort@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59" + integrity sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw== + jest-haste-map@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" @@ -7779,7 +7900,7 @@ lodash.uniq@4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: +lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== From 4de6b7b2ec697f5e6af291bcb9145e84c9d6cb8e Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Thu, 14 Jul 2022 15:14:00 +0900 Subject: [PATCH 0105/1011] =?UTF-8?q?refactor:=20import=20=EC=88=9C?= =?UTF-8?q?=EC=84=9C=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/.storybook/preview.js | 4 ++-- .../@common/Button/Button.stories.tsx | 2 +- .../@common/FieldSet/FieldSet.stories.tsx | 2 +- .../components/@common/FieldSet/FieldSet.tsx | 3 +-- .../@common/ModalPortal/ModalPortal.tsx | 3 +-- .../src/components/NavBar/NavBar.stories.tsx | 2 +- frontend/src/components/NavBar/NavBar.tsx | 3 ++- .../ScheduleAddButton.stories.tsx | 2 +- .../ScheduleAddButton/ScheduleAddButton.tsx | 4 ++-- .../ScheduleAddModal.stories.tsx | 2 +- .../ScheduleAddModal/ScheduleAddModal.tsx | 19 +++++++++---------- frontend/src/index.tsx | 8 ++++---- frontend/src/mocks/browser.ts | 1 + .../src/pages/CalendarPage/CalendarPage.tsx | 6 +++--- frontend/src/styles/GlobalStyle.tsx | 2 +- 15 files changed, 31 insertions(+), 32 deletions(-) diff --git a/frontend/.storybook/preview.js b/frontend/.storybook/preview.js index 76ac274f..f02ff916 100644 --- a/frontend/.storybook/preview.js +++ b/frontend/.storybook/preview.js @@ -1,7 +1,7 @@ import { ThemeProvider } from '@emotion/react'; -import GlobalStyle from '../src/styles/GlobalStyle'; -import theme from '../src/styles/theme'; +import GlobalStyle from '@/styles/GlobalStyle'; +import theme from '@/styles/theme'; export const parameters = { actions: { argTypesRegex: '^on[A-Z].*' }, diff --git a/frontend/src/components/@common/Button/Button.stories.tsx b/frontend/src/components/@common/Button/Button.stories.tsx index 354e6949..82478d30 100644 --- a/frontend/src/components/@common/Button/Button.stories.tsx +++ b/frontend/src/components/@common/Button/Button.stories.tsx @@ -1,4 +1,4 @@ -import { ComponentStory, ComponentMeta } from '@storybook/react'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; import Button from './Button'; diff --git a/frontend/src/components/@common/FieldSet/FieldSet.stories.tsx b/frontend/src/components/@common/FieldSet/FieldSet.stories.tsx index 195ae60b..1815865a 100644 --- a/frontend/src/components/@common/FieldSet/FieldSet.stories.tsx +++ b/frontend/src/components/@common/FieldSet/FieldSet.stories.tsx @@ -1,4 +1,4 @@ -import { ComponentStory, ComponentMeta } from '@storybook/react'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; import FieldSet from './FieldSet'; diff --git a/frontend/src/components/@common/FieldSet/FieldSet.tsx b/frontend/src/components/@common/FieldSet/FieldSet.tsx index b04bbed7..0361f8ed 100644 --- a/frontend/src/components/@common/FieldSet/FieldSet.tsx +++ b/frontend/src/components/@common/FieldSet/FieldSet.tsx @@ -1,6 +1,5 @@ -import { forwardRef } from 'react'; - import { SerializedStyles, useTheme } from '@emotion/react'; +import { forwardRef } from 'react'; import { fieldSet, input, label } from './FieldSet.styles'; diff --git a/frontend/src/components/@common/ModalPortal/ModalPortal.tsx b/frontend/src/components/@common/ModalPortal/ModalPortal.tsx index 171f569f..cce11648 100644 --- a/frontend/src/components/@common/ModalPortal/ModalPortal.tsx +++ b/frontend/src/components/@common/ModalPortal/ModalPortal.tsx @@ -1,6 +1,5 @@ -import ReactDOM from 'react-dom'; - import { useTheme } from '@emotion/react'; +import ReactDOM from 'react-dom'; import { dimmer } from './ModalPortal.styles'; diff --git a/frontend/src/components/NavBar/NavBar.stories.tsx b/frontend/src/components/NavBar/NavBar.stories.tsx index 009def92..9c4dd234 100644 --- a/frontend/src/components/NavBar/NavBar.stories.tsx +++ b/frontend/src/components/NavBar/NavBar.stories.tsx @@ -1,4 +1,4 @@ -import { ComponentStory, ComponentMeta } from '@storybook/react'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; import NavBar from './NavBar'; diff --git a/frontend/src/components/NavBar/NavBar.tsx b/frontend/src/components/NavBar/NavBar.tsx index 22ee7eb2..ee15572c 100644 --- a/frontend/src/components/NavBar/NavBar.tsx +++ b/frontend/src/components/NavBar/NavBar.tsx @@ -1,6 +1,7 @@ -import { navBar } from './NavBar.styles'; import { useTheme } from '@emotion/react'; +import { navBar } from './NavBar.styles'; + function NavBar() { const theme = useTheme(); diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx index 04be8ab0..39160033 100644 --- a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.stories.tsx @@ -1,4 +1,4 @@ -import { ComponentStory, ComponentMeta } from '@storybook/react'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; import ScheduleAddButton from './ScheduleAddButton'; diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx index fb1722fe..c2147b94 100644 --- a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.tsx @@ -1,8 +1,8 @@ import { useTheme } from '@emotion/react'; -import { scheduleAddButton } from './ScheduleAddButton.styles'; +import Button from '@/components/@common/Button/Button'; -import Button from '../@common/Button/Button'; +import { scheduleAddButton } from './ScheduleAddButton.styles'; interface ScheduleAddButtonProps { onClick: () => void; diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.stories.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.stories.tsx index ae4eca84..5962b974 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.stories.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.stories.tsx @@ -1,4 +1,4 @@ -import { ComponentStory, ComponentMeta } from '@storybook/react'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; import ScheduleAddModal from './ScheduleAddModal'; diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index 8e3fb786..26b1ed39 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -1,11 +1,17 @@ -import { useRef } from 'react'; - -import { RefetchOptions, RefetchQueryFilters, useMutation, QueryObserverResult } from 'react-query'; import { useTheme } from '@emotion/react'; import { AxiosError, AxiosResponse } from 'axios'; +import { useRef } from 'react'; +import { QueryObserverResult, RefetchOptions, RefetchQueryFilters, useMutation } from 'react-query'; import { Schedule } from '@/@types'; +import Button from '@/components/@common/Button/Button'; +import FieldSet from '@/components/@common/FieldSet/FieldSet'; + +import { createPostBody } from '@/utils'; + +import scheduleApi from '@/api/schedule'; + import { allDayButton, arrow, @@ -17,13 +23,6 @@ import { scheduleAddModal, } from './ScheduleAddModal.styles'; -import Button from '../@common/Button/Button'; -import FieldSet from '../@common/FieldSet/FieldSet'; - -import { createPostBody } from '@/utils'; - -import scheduleApi from '@/api/schedule'; - interface ScheduleAddModalProps { closeModal: () => void; refetch: ( diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index fc66f2c0..33aa2904 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -1,13 +1,13 @@ -import ReactDOM from 'react-dom'; import { ThemeProvider } from '@emotion/react'; +import ReactDOM from 'react-dom'; -import theme from '@/styles/theme'; import GlobalStyle from '@/styles/GlobalStyle'; - -import App from '@/App'; +import theme from '@/styles/theme'; import { worker } from '@/mocks/browser'; +import App from './App'; + if (process.env.NODE_ENV === 'development') { worker.start(); } diff --git a/frontend/src/mocks/browser.ts b/frontend/src/mocks/browser.ts index 750e031c..9c10cad9 100644 --- a/frontend/src/mocks/browser.ts +++ b/frontend/src/mocks/browser.ts @@ -1,4 +1,5 @@ import { setupWorker } from 'msw'; + import { handlers } from './handlers'; export const worker = setupWorker(...handlers); diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index dbfc7526..4af23303 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -1,14 +1,14 @@ -import { useQuery } from 'react-query'; import { AxiosError, AxiosResponse } from 'axios'; +import { useQuery } from 'react-query'; import useModal from '@/hooks/useModal'; import { Schedule } from '@/@types'; -import PageLayout from '@/components/PageLayout/PageLayout'; +import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; import Calendar from '@/components/Calendar/Calendar'; +import PageLayout from '@/components/PageLayout/PageLayout'; import ScheduleAddButton from '@/components/ScheduleAddButton/ScheduleAddButton'; -import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; import ScheduleAddModal from '@/components/ScheduleAddModal/ScheduleAddModal'; import { CACHE_KEY } from '@/constants'; diff --git a/frontend/src/styles/GlobalStyle.tsx b/frontend/src/styles/GlobalStyle.tsx index 63ee194e..4805c3f5 100644 --- a/frontend/src/styles/GlobalStyle.tsx +++ b/frontend/src/styles/GlobalStyle.tsx @@ -1,5 +1,5 @@ +import { css, Global } from '@emotion/react'; import emotionReset from 'emotion-reset'; -import { Global, css } from '@emotion/react'; const global = css` @import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.4/dist/web/static/pretendard.css'); From b9c152df5852076bd1a1298ec156b805697a398b Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Sat, 16 Jul 2022 09:19:59 +0900 Subject: [PATCH 0106/1011] =?UTF-8?q?chore:=20react-router-dom=20=EC=84=A4?= =?UTF-8?q?=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/package.json | 3 ++- frontend/yarn.lock | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index 465d31d6..22fcaa06 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -21,7 +21,8 @@ "emotion-reset": "^3.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-query": "^3.39.1" + "react-query": "^3.39.1", + "react-router-dom": "^6.3.0" }, "devDependencies": { "@babel/core": "^7.18.6", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index dbdafed2..6c6ee778 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -9660,6 +9660,21 @@ react-refresh@^0.11.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A== +react-router-dom@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.3.0.tgz#a0216da813454e521905b5fa55e0e5176123f43d" + integrity sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw== + dependencies: + history "^5.2.0" + react-router "6.3.0" + +react-router@6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557" + integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ== + dependencies: + history "^5.2.0" + react-syntax-highlighter@^15.4.5: version "15.5.0" resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz#4b3eccc2325fa2ec8eff1e2d6c18fa4a9e07ab20" From f3152479ed2469d68e714a875c6993ebff31ec35 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Sat, 16 Jul 2022 09:23:02 +0900 Subject: [PATCH 0107/1011] =?UTF-8?q?feat:=20=EB=8B=AC=EB=A0=A5=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20path=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.tsx | 12 +++++++----- frontend/src/constants/index.ts | 6 +++++- frontend/src/index.tsx | 12 ++++++++---- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index d6d56ec9..acbe004b 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,14 +1,16 @@ -import { QueryClient, QueryClientProvider } from 'react-query'; +import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'; import CalendarPage from '@/pages/CalendarPage/CalendarPage'; -const queryClient = new QueryClient(); +import { PATH } from '@/constants'; function App() { return ( - - - + + + } /> + + ); } diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index ef0c3a09..752b7942 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -2,4 +2,8 @@ const CACHE_KEY = { SCHEDULES: 'schedules', }; -export { CACHE_KEY }; +const PATH = { + CALENDAR_PAGE: '/', +}; + +export { CACHE_KEY, PATH }; diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 33aa2904..9c3b79e3 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -1,5 +1,6 @@ import { ThemeProvider } from '@emotion/react'; import ReactDOM from 'react-dom'; +import { QueryClient, QueryClientProvider } from 'react-query'; import GlobalStyle from '@/styles/GlobalStyle'; import theme from '@/styles/theme'; @@ -12,12 +13,15 @@ if (process.env.NODE_ENV === 'development') { worker.start(); } +const queryClient = new QueryClient(); const rootElement = document.getElementById('root'); ReactDOM.render( - - - - , + + + + + + , rootElement ); From 9bd5ffb1f08aa64c7f61e0a8c35aeb6789c5c09a Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 14 Jul 2022 12:45:36 +0900 Subject: [PATCH 0108/1011] =?UTF-8?q?feat:=20storybook=20=EC=A0=88?= =?UTF-8?q?=EB=8C=80=EA=B2=BD=EB=A1=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/.storybook/main.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/frontend/.storybook/main.js b/frontend/.storybook/main.js index 09b55fd9..1029233b 100644 --- a/frontend/.storybook/main.js +++ b/frontend/.storybook/main.js @@ -1,3 +1,5 @@ +const path = require('path'); + module.exports = { stories: ['../src/**/*.stories.@(tsx)'], addons: [ @@ -9,4 +11,12 @@ module.exports = { core: { builder: '@storybook/builder-webpack5', }, + webpackFinal: async (config) => { + config.resolve.alias = { + ...config.resolve.alias, + '@': path.resolve(__dirname, '../src/'), + }; + config.resolve.extensions.push('.ts', '.tsx'); + return config; + }, }; From 09ae7860a51b958967abda5115aabe3cd699005d Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 14 Jul 2022 13:46:48 +0900 Subject: [PATCH 0109/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EA=B0=9C=EB=B3=84=20=EC=95=84=EC=9D=B4=ED=85=9C=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/@types/index.ts | 8 ++++++- .../CategoryItem/CategoryItem.stories.tsx | 15 +++++++++++++ .../CategoryItem/CategoryItem.styles.ts | 13 ++++++++++++ .../components/CategoryItem/CategoryItem.tsx | 21 +++++++++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/CategoryItem/CategoryItem.stories.tsx create mode 100644 frontend/src/components/CategoryItem/CategoryItem.styles.ts create mode 100644 frontend/src/components/CategoryItem/CategoryItem.tsx diff --git a/frontend/src/@types/index.ts b/frontend/src/@types/index.ts index a8b520df..266215a1 100644 --- a/frontend/src/@types/index.ts +++ b/frontend/src/@types/index.ts @@ -1,3 +1,9 @@ +interface CategoryType { + id: number; + name: string; + createdAt: string; +} + interface InputRef { [index: string]: React.RefObject; } @@ -10,4 +16,4 @@ interface Schedule { memo: string; } -export { InputRef, Schedule }; +export { CategoryType, InputRef, Schedule }; diff --git a/frontend/src/components/CategoryItem/CategoryItem.stories.tsx b/frontend/src/components/CategoryItem/CategoryItem.stories.tsx new file mode 100644 index 00000000..2435a9f9 --- /dev/null +++ b/frontend/src/components/CategoryItem/CategoryItem.stories.tsx @@ -0,0 +1,15 @@ +import { ComponentStory, ComponentMeta } from '@storybook/react'; + +import CategoryItem from './CategoryItem'; + +export default { + title: 'Components/CategoryItem', + component: CategoryItem, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ; + +export const Primary = Template.bind({}); +Primary.args = { + category: { id: 1, name: '달록 공식 일정', createdAt: '2022-07-04T13:00:00' }, +}; diff --git a/frontend/src/components/CategoryItem/CategoryItem.styles.ts b/frontend/src/components/CategoryItem/CategoryItem.styles.ts new file mode 100644 index 00000000..87fecde0 --- /dev/null +++ b/frontend/src/components/CategoryItem/CategoryItem.styles.ts @@ -0,0 +1,13 @@ +import { css, Theme } from '@emotion/react'; + +const categoryLayout = ({ colors, flex }: Theme) => css` + ${flex.row} + justify-content:space-around; + + width: 90%; + height: 20rem; + margin: auto; + border-bottom: 1px solid ${colors.GRAY_400}; +`; + +export { categoryLayout }; diff --git a/frontend/src/components/CategoryItem/CategoryItem.tsx b/frontend/src/components/CategoryItem/CategoryItem.tsx new file mode 100644 index 00000000..6abb79da --- /dev/null +++ b/frontend/src/components/CategoryItem/CategoryItem.tsx @@ -0,0 +1,21 @@ +import { CategoryType } from '@/@types'; +import { useTheme } from '@emotion/react'; + +import { categoryLayout } from './CategoryItem.styles'; + +interface CategoryProps { + category: CategoryType; +} + +function CategoryItem({ category }: CategoryProps) { + const theme = useTheme(); + + return ( +
+ {category.createdAt.split('T')[0]} + {category.name} +
+ ); +} + +export default CategoryItem; From a8f0559f5196df47013a0f522af933f15f2439e5 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 14 Jul 2022 14:56:26 +0900 Subject: [PATCH 0110/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CategoryList/CategoryList.stories.tsx | 17 +++++++++++ .../CategoryList/CategoryList.styles.ts | 18 +++++++++++ .../components/CategoryList/CategoryList.tsx | 30 +++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 frontend/src/components/CategoryList/CategoryList.stories.tsx create mode 100644 frontend/src/components/CategoryList/CategoryList.styles.ts create mode 100644 frontend/src/components/CategoryList/CategoryList.tsx diff --git a/frontend/src/components/CategoryList/CategoryList.stories.tsx b/frontend/src/components/CategoryList/CategoryList.stories.tsx new file mode 100644 index 00000000..373ee025 --- /dev/null +++ b/frontend/src/components/CategoryList/CategoryList.stories.tsx @@ -0,0 +1,17 @@ +import { ComponentStory, ComponentMeta } from '@storybook/react'; + +import CategoryList from './CategoryList'; + +import { categoryDB } from '@/mocks/handlers'; + +export default { + title: 'Components/CategoryList', + component: CategoryList, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ; + +export const Primary = Template.bind({}); +Primary.args = { + categories: categoryDB.data, +}; diff --git a/frontend/src/components/CategoryList/CategoryList.styles.ts b/frontend/src/components/CategoryList/CategoryList.styles.ts new file mode 100644 index 00000000..507a051c --- /dev/null +++ b/frontend/src/components/CategoryList/CategoryList.styles.ts @@ -0,0 +1,18 @@ +import { css, Theme } from '@emotion/react'; + +const categoryLayout = ({ colors, flex }: Theme) => css` + ${flex.row} + + justify-content:space-around; + + width: 90%; + height: 12rem; + margin: auto; + border-bottom: 2px solid ${colors.GRAY_400}; + + background: ${colors.GRAY_100}; + + font-weight: 700; +`; + +export { categoryLayout }; diff --git a/frontend/src/components/CategoryList/CategoryList.tsx b/frontend/src/components/CategoryList/CategoryList.tsx new file mode 100644 index 00000000..51fbde44 --- /dev/null +++ b/frontend/src/components/CategoryList/CategoryList.tsx @@ -0,0 +1,30 @@ +import { useState } from 'react'; +import { useTheme } from '@emotion/react'; + +import { CategoryType } from '@/@types'; + +import { categoryLayout } from './CategoryList.styles'; + +import CategoryItem from '@/components/CategoryItem/CategoryItem'; + +interface CategoryListProps { + categories: CategoryType[]; +} + +function CategoryList({ categories }: CategoryListProps) { + const theme = useTheme(); + + return ( +
+
+ 생성 날짜 + 카테고리 이름 +
+ {categories.map((category) => ( + + ))} +
+ ); +} + +export default CategoryList; From bee33faed447bac27414eb86d15bd39565b592a0 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 14 Jul 2022 17:17:00 +0900 Subject: [PATCH 0111/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EA=B4=80=EB=A0=A8=20=ED=83=80=EC=9E=85=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20=EB=B0=8F=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/@types/category.ts | 13 +++++++++++++ frontend/src/@types/index.ts | 8 +------- .../src/components/CategoryItem/CategoryItem.tsx | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 frontend/src/@types/category.ts diff --git a/frontend/src/@types/category.ts b/frontend/src/@types/category.ts new file mode 100644 index 00000000..f1348529 --- /dev/null +++ b/frontend/src/@types/category.ts @@ -0,0 +1,13 @@ +interface CategoryType { + id: number; + name: string; + createdAt: string; +} + +interface CategoriesGetResponseType { + totalCount: number; + page: number; + data: CategoryType[]; +} + +export { CategoryType, CategoriesGetResponseType }; diff --git a/frontend/src/@types/index.ts b/frontend/src/@types/index.ts index 266215a1..a8b520df 100644 --- a/frontend/src/@types/index.ts +++ b/frontend/src/@types/index.ts @@ -1,9 +1,3 @@ -interface CategoryType { - id: number; - name: string; - createdAt: string; -} - interface InputRef { [index: string]: React.RefObject; } @@ -16,4 +10,4 @@ interface Schedule { memo: string; } -export { CategoryType, InputRef, Schedule }; +export { InputRef, Schedule }; diff --git a/frontend/src/components/CategoryItem/CategoryItem.tsx b/frontend/src/components/CategoryItem/CategoryItem.tsx index 6abb79da..4ecd2cce 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.tsx +++ b/frontend/src/components/CategoryItem/CategoryItem.tsx @@ -1,4 +1,4 @@ -import { CategoryType } from '@/@types'; +import { CategoryType } from '@/@types/category'; import { useTheme } from '@emotion/react'; import { categoryLayout } from './CategoryItem.styles'; From b41a35caaf4305ae39e7c6caacf2a09719369320 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 14 Jul 2022 17:23:43 +0900 Subject: [PATCH 0112/1011] =?UTF-8?q?feat:=20=EB=AA=A8=ED=82=B9=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20get=20=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=20api=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/categories.ts | 26 +++++++ frontend/src/constants/index.ts | 1 + frontend/src/mocks/data.ts | 118 ++++++++++++++++++++++++++++++++ frontend/src/mocks/handlers.ts | 33 ++++----- 4 files changed, 162 insertions(+), 16 deletions(-) create mode 100644 frontend/src/api/categories.ts create mode 100644 frontend/src/mocks/data.ts diff --git a/frontend/src/api/categories.ts b/frontend/src/api/categories.ts new file mode 100644 index 00000000..62ac6f63 --- /dev/null +++ b/frontend/src/api/categories.ts @@ -0,0 +1,26 @@ +import axios from 'axios'; + +import { CategoriesGetResponseType } from '@/@types/category'; + +const categoryApi = { + endpoint: '/api/categories', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + + get: async (page: number, size: number) => { + const response = await axios.get(categoryApi.endpoint, { + params: { page, size }, + headers: categoryApi.headers, + transformResponse: (res) => { + const categories = JSON.parse(res); + return categories; + }, + }); + + return response; + }, +}; + +export default categoryApi; diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index ef0c3a09..7d2fc9c5 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -1,5 +1,6 @@ const CACHE_KEY = { SCHEDULES: 'schedules', + CATEGORIES: 'categories', }; export { CACHE_KEY }; diff --git a/frontend/src/mocks/data.ts b/frontend/src/mocks/data.ts new file mode 100644 index 00000000..32afbc63 --- /dev/null +++ b/frontend/src/mocks/data.ts @@ -0,0 +1,118 @@ +import { Schedule } from '@/@types'; +import { CategoryType } from '@/@types/category'; + +const scheduleDB: Schedule[] = [ + { + id: 1, + title: '우테코 데모데이', + startDateTime: '2022-07-07T14:00', + endDateTime: '2022-07-07T18:00', + memo: '달록팀 스프린트 1차 발표', + }, + { + id: 2, + title: '테코톡', + startDateTime: '2022-07-09T14:00', + endDateTime: '2022-07-10T20:00', + memo: '레벨3 첫 테코톡', + }, +]; + +const categoryDB: { + data: CategoryType[]; +} = { + data: [ + { + id: 1, + name: 'BE 공식일정', + createdAt: '2022-07-04T13:00:00', + }, + { + id: 2, + name: '알록달록 팀 회의', + createdAt: '2022-07-08T15:00:00', + }, + { + id: 3, + name: '카테고리 3', + createdAt: '2022-07-05T13:00:00', + }, + { + id: 4, + name: '카테고리 4', + createdAt: '2022-07-03T15:00:00', + }, + { + id: 5, + name: '카테고리 5', + createdAt: '2022-07-02T13:00:00', + }, + { + id: 6, + name: '카테고리 6', + createdAt: '2022-07-01T15:00:00', + }, + { + id: 7, + name: '카테고리 7', + createdAt: '2022-07-11T13:00:00', + }, + { + id: 8, + name: '카테고리 8', + createdAt: '2022-07-12T15:00:00', + }, + { + id: 9, + name: '카테고리 9', + createdAt: '2022-07-13T13:00:00', + }, + { + id: 10, + name: '카테고리 10', + createdAt: '2022-07-14T15:00:00', + }, + { + id: 11, + name: '카테고리 11', + createdAt: '2022-07-15T13:00:00', + }, + { + id: 12, + name: '카테고리 12', + createdAt: '2022-07-16T15:00:00', + }, + { + id: 13, + name: '카테고리 13', + createdAt: '2022-07-18T13:00:00', + }, + { + id: 14, + name: '카테고리 14', + createdAt: '2022-07-20T15:00:00', + }, + { + id: 15, + name: '카테고리 15', + createdAt: '2022-07-12T13:00:00', + }, + { + id: 16, + name: '카테고리 16', + createdAt: '2022-07-13T15:00:00', + }, + { + id: 17, + name: '카테고리 17', + createdAt: '2022-07-25T13:00:00', + }, + { + id: 18, + name: '카테고리 18', + createdAt: '2022-07-30T15:00:00', + }, + ], +}; + +export { scheduleDB, categoryDB }; diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 35b2fc8a..a46fd539 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -3,23 +3,9 @@ import { rest } from 'msw'; import { Schedule } from '@/@types'; import scheduleApi from '@/api/schedule'; +import categoryApi from '@/api/categories'; -const scheduleDB: Schedule[] = [ - { - id: 1, - title: '우테코 데모데이', - startDateTime: '2022-07-07T14:00', - endDateTime: '2022-07-07T18:00', - memo: '달록팀 스프린트 1차 발표', - }, - { - id: 2, - title: '테코톡', - startDateTime: '2022-07-09T14:00', - endDateTime: '2022-07-10T20:00', - memo: '레벨3 첫 테코톡', - }, -]; +import { categoryDB, scheduleDB } from './data'; const handlers = [ rest.post>(scheduleApi.endpoint, (req, res, ctx) => { @@ -31,6 +17,21 @@ const handlers = [ rest.get(scheduleApi.endpoint, (req, res, ctx) => { return res(ctx.status(200), ctx.json({ schedules: scheduleDB })); }), + + rest.get(categoryApi.endpoint, (req, res, ctx) => { + const page = parseInt(req.url.searchParams.get('page') as string); + const size = parseInt(req.url.searchParams.get('size') as string); + const slicedCategories = categoryDB.data.slice((page - 1) * size, (page - 1) * size + size); + + return res( + ctx.status(200), + ctx.json({ + totalCount: 18, + page: page, + data: slicedCategories, + }) + ); + }), ]; export { handlers }; From 627c6e125d87a646179bb394e3ef51eb275d55da Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 14 Jul 2022 17:25:56 +0900 Subject: [PATCH 0113/1011] =?UTF-8?q?feat:=20intersect=20=EC=BB=A4?= =?UTF-8?q?=EC=8A=A4=ED=85=80=ED=9B=85=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/hooks/useIntersect.ts | 33 ++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 frontend/src/hooks/useIntersect.ts diff --git a/frontend/src/hooks/useIntersect.ts b/frontend/src/hooks/useIntersect.ts new file mode 100644 index 00000000..3a91692e --- /dev/null +++ b/frontend/src/hooks/useIntersect.ts @@ -0,0 +1,33 @@ +import { useCallback, useEffect, useRef } from 'react'; + +type IntersectHandler = (entry: IntersectionObserverEntry, observer: IntersectionObserver) => void; + +function useIntersect(onIntersect: IntersectHandler, options?: IntersectionObserverInit) { + const ref = useRef(null); + const callback = useCallback( + (entries: IntersectionObserverEntry[], observer: IntersectionObserver) => { + entries.forEach((entry) => { + if (entry.isIntersecting) onIntersect(entry, observer); + }); + }, + [onIntersect] + ); + + useEffect(() => { + if (!ref.current) { + return; + } + + const observer = new IntersectionObserver(callback, options); + + observer.observe(ref.current); + + return () => { + observer.disconnect(); + }; + }, [ref, options, callback]); + + return ref; +} + +export default useIntersect; From 6f32386a1ae273e6f4a037b0e1115f1cfa998136 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 14 Jul 2022 17:46:24 +0900 Subject: [PATCH 0114/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=ED=85=8C=EC=9D=B4=EB=B8=94=20?= =?UTF-8?q?=EB=AC=B4=ED=95=9C=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CategoryList/CategoryList.stories.tsx | 2 +- .../CategoryList/CategoryList.styles.ts | 6 ++- .../components/CategoryList/CategoryList.tsx | 23 +++++--- frontend/src/constants/index.ts | 6 ++- .../src/pages/CategoryPage/CategoryPage.tsx | 53 +++++++++++++++++++ 5 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 frontend/src/pages/CategoryPage/CategoryPage.tsx diff --git a/frontend/src/components/CategoryList/CategoryList.stories.tsx b/frontend/src/components/CategoryList/CategoryList.stories.tsx index 373ee025..9ab3e936 100644 --- a/frontend/src/components/CategoryList/CategoryList.stories.tsx +++ b/frontend/src/components/CategoryList/CategoryList.stories.tsx @@ -2,7 +2,7 @@ import { ComponentStory, ComponentMeta } from '@storybook/react'; import CategoryList from './CategoryList'; -import { categoryDB } from '@/mocks/handlers'; +import { categoryDB } from '@/mocks/data'; export default { title: 'Components/CategoryList', diff --git a/frontend/src/components/CategoryList/CategoryList.styles.ts b/frontend/src/components/CategoryList/CategoryList.styles.ts index 507a051c..4eb27360 100644 --- a/frontend/src/components/CategoryList/CategoryList.styles.ts +++ b/frontend/src/components/CategoryList/CategoryList.styles.ts @@ -15,4 +15,8 @@ const categoryLayout = ({ colors, flex }: Theme) => css` font-weight: 700; `; -export { categoryLayout }; +const intersectTarget = css` + height: 10rem; +`; + +export { categoryLayout, intersectTarget }; diff --git a/frontend/src/components/CategoryList/CategoryList.tsx b/frontend/src/components/CategoryList/CategoryList.tsx index 51fbde44..4b695295 100644 --- a/frontend/src/components/CategoryList/CategoryList.tsx +++ b/frontend/src/components/CategoryList/CategoryList.tsx @@ -1,28 +1,39 @@ -import { useState } from 'react'; import { useTheme } from '@emotion/react'; -import { CategoryType } from '@/@types'; +import { CategoriesGetResponseType, CategoryType } from '@/@types/category'; -import { categoryLayout } from './CategoryList.styles'; +import { categoryLayout, intersectTarget } from './CategoryList.styles'; import CategoryItem from '@/components/CategoryItem/CategoryItem'; +import useIntersect from '@/hooks/useIntersect'; +import { FetchNextPageOptions, InfiniteQueryObserverResult } from 'react-query'; +import { AxiosError, AxiosResponse } from 'axios'; interface CategoryListProps { - categories: CategoryType[]; + categoryList: CategoryType[]; + getMoreCategories: ( + options?: FetchNextPageOptions | undefined + ) => Promise, AxiosError>>; + hasNextPage: boolean | undefined; } -function CategoryList({ categories }: CategoryListProps) { +function CategoryList({ categoryList, getMoreCategories, hasNextPage }: CategoryListProps) { const theme = useTheme(); + const ref = useIntersect(() => { + hasNextPage && getMoreCategories(); + }); + return (
생성 날짜 카테고리 이름
- {categories.map((category) => ( + {categoryList.map((category) => ( ))} +
); } diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 7d2fc9c5..04b87d04 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -3,4 +3,8 @@ const CACHE_KEY = { CATEGORIES: 'categories', }; -export { CACHE_KEY }; +const API = { + CATEGORY_GET_SIZE: 4, +}; + +export { CACHE_KEY, API }; diff --git a/frontend/src/pages/CategoryPage/CategoryPage.tsx b/frontend/src/pages/CategoryPage/CategoryPage.tsx new file mode 100644 index 00000000..356a59ae --- /dev/null +++ b/frontend/src/pages/CategoryPage/CategoryPage.tsx @@ -0,0 +1,53 @@ +import { AxiosError, AxiosResponse } from 'axios'; +import { useInfiniteQuery } from 'react-query'; + +import { CategoriesGetResponseType } from '@/@types/category'; + +import CategoryList from '@/components/CategoryList/CategoryList'; +import PageLayout from '@/components/PageLayout/PageLayout'; + +import { API, CACHE_KEY } from '@/constants'; + +import categoryApi from '@/api/categories'; + +function CategoryPage() { + const { + isLoading, + error, + data: categoriesGetResponse, + fetchNextPage, + hasNextPage, + } = useInfiniteQuery, AxiosError>( + CACHE_KEY.CATEGORIES, + ({ pageParam = 1 }) => categoryApi.get(pageParam, API.CATEGORY_GET_SIZE), + { + getNextPageParam: ({ data }) => { + if (data.data.length) { + return data.page + 1; + } + }, + } + ); + + if (isLoading || categoriesGetResponse === undefined) { + return
Loading
; + } + + if (error) { + return
Error
; + } + + const categoryList = categoriesGetResponse.pages.flatMap(({ data }) => data.data); + + return ( + + + + ); +} + +export default CategoryPage; From 7452aa85cb4e41887722d20291cd215ece12ef7e Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 14 Jul 2022 18:47:00 +0900 Subject: [PATCH 0115/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=EC=97=90=20=EA=B2=80=EC=83=89=EC=B0=BD=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CategoryItem/CategoryItem.styles.ts | 8 +++---- .../components/CategoryItem/CategoryItem.tsx | 4 ++-- .../CategoryList/CategoryList.styles.ts | 11 ++++++---- .../components/CategoryList/CategoryList.tsx | 10 +++------ .../pages/CategoryPage/CategoryPage.styles.ts | 21 +++++++++++++++++++ .../src/pages/CategoryPage/CategoryPage.tsx | 20 +++++++++++++----- 6 files changed, 52 insertions(+), 22 deletions(-) create mode 100644 frontend/src/pages/CategoryPage/CategoryPage.styles.ts diff --git a/frontend/src/components/CategoryItem/CategoryItem.styles.ts b/frontend/src/components/CategoryItem/CategoryItem.styles.ts index 87fecde0..0323e740 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.styles.ts +++ b/frontend/src/components/CategoryItem/CategoryItem.styles.ts @@ -1,13 +1,13 @@ import { css, Theme } from '@emotion/react'; -const categoryLayout = ({ colors, flex }: Theme) => css` +const categoryItem = ({ colors, flex }: Theme) => css` ${flex.row} justify-content:space-around; - width: 90%; height: 20rem; - margin: auto; border-bottom: 1px solid ${colors.GRAY_400}; + + font-size: 4rem; `; -export { categoryLayout }; +export { categoryItem }; diff --git a/frontend/src/components/CategoryItem/CategoryItem.tsx b/frontend/src/components/CategoryItem/CategoryItem.tsx index 4ecd2cce..efbe2720 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.tsx +++ b/frontend/src/components/CategoryItem/CategoryItem.tsx @@ -1,7 +1,7 @@ import { CategoryType } from '@/@types/category'; import { useTheme } from '@emotion/react'; -import { categoryLayout } from './CategoryItem.styles'; +import { categoryItem } from './CategoryItem.styles'; interface CategoryProps { category: CategoryType; @@ -11,7 +11,7 @@ function CategoryItem({ category }: CategoryProps) { const theme = useTheme(); return ( -
+
{category.createdAt.split('T')[0]} {category.name}
diff --git a/frontend/src/components/CategoryList/CategoryList.styles.ts b/frontend/src/components/CategoryList/CategoryList.styles.ts index 4eb27360..4a99561a 100644 --- a/frontend/src/components/CategoryList/CategoryList.styles.ts +++ b/frontend/src/components/CategoryList/CategoryList.styles.ts @@ -1,17 +1,20 @@ import { css, Theme } from '@emotion/react'; -const categoryLayout = ({ colors, flex }: Theme) => css` +const categoryTable = css` + width: 100%; +`; + +const categoryTableHeader = ({ flex, colors }: Theme) => css` ${flex.row} justify-content:space-around; - width: 90%; height: 12rem; - margin: auto; border-bottom: 2px solid ${colors.GRAY_400}; background: ${colors.GRAY_100}; + font-size: 4rem; font-weight: 700; `; @@ -19,4 +22,4 @@ const intersectTarget = css` height: 10rem; `; -export { categoryLayout, intersectTarget }; +export { categoryTable, categoryTableHeader, intersectTarget }; diff --git a/frontend/src/components/CategoryList/CategoryList.tsx b/frontend/src/components/CategoryList/CategoryList.tsx index 4b695295..5ced3193 100644 --- a/frontend/src/components/CategoryList/CategoryList.tsx +++ b/frontend/src/components/CategoryList/CategoryList.tsx @@ -1,8 +1,6 @@ -import { useTheme } from '@emotion/react'; - import { CategoriesGetResponseType, CategoryType } from '@/@types/category'; -import { categoryLayout, intersectTarget } from './CategoryList.styles'; +import { categoryTable, categoryTableHeader, intersectTarget } from './CategoryList.styles'; import CategoryItem from '@/components/CategoryItem/CategoryItem'; import useIntersect from '@/hooks/useIntersect'; @@ -18,15 +16,13 @@ interface CategoryListProps { } function CategoryList({ categoryList, getMoreCategories, hasNextPage }: CategoryListProps) { - const theme = useTheme(); - const ref = useIntersect(() => { hasNextPage && getMoreCategories(); }); return ( -
-
+
+
생성 날짜 카테고리 이름
diff --git a/frontend/src/pages/CategoryPage/CategoryPage.styles.ts b/frontend/src/pages/CategoryPage/CategoryPage.styles.ts new file mode 100644 index 00000000..361714a5 --- /dev/null +++ b/frontend/src/pages/CategoryPage/CategoryPage.styles.ts @@ -0,0 +1,21 @@ +import { css, Theme } from '@emotion/react'; + +const categoryPage = ({ flex }: Theme) => css` + ${flex.column} + + align-items: center; + + padding: 10rem 20rem; +`; + +const categoryNav = css` + width: 100%; +`; + +const categorySearch = css` + width: 62.5rem; + height: 12.5rem; + margin-bottom: 17.5rem; +`; + +export { categoryPage, categoryNav, categorySearch }; diff --git a/frontend/src/pages/CategoryPage/CategoryPage.tsx b/frontend/src/pages/CategoryPage/CategoryPage.tsx index 356a59ae..6d893a77 100644 --- a/frontend/src/pages/CategoryPage/CategoryPage.tsx +++ b/frontend/src/pages/CategoryPage/CategoryPage.tsx @@ -9,8 +9,13 @@ import PageLayout from '@/components/PageLayout/PageLayout'; import { API, CACHE_KEY } from '@/constants'; import categoryApi from '@/api/categories'; +import FieldSet from '@/components/@common/FieldSet/FieldSet'; +import { categoryNav, categoryPage, categorySearch } from './CategoryPage.styles'; +import { useTheme } from '@emotion/react'; function CategoryPage() { + const theme = useTheme(); + const { isLoading, error, @@ -41,11 +46,16 @@ function CategoryPage() { return ( - +
+
+
+
+ +
); } From 50fe5d2d7afcb52f10b80405df02c75a6b92e6e6 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 14 Jul 2022 18:49:40 +0900 Subject: [PATCH 0116/1011] =?UTF-8?q?fix:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=8A=A4=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=A7=A4=EA=B0=9C=EB=B3=80=EC=88=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/CategoryList/CategoryList.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/CategoryList/CategoryList.stories.tsx b/frontend/src/components/CategoryList/CategoryList.stories.tsx index 9ab3e936..ca47ad85 100644 --- a/frontend/src/components/CategoryList/CategoryList.stories.tsx +++ b/frontend/src/components/CategoryList/CategoryList.stories.tsx @@ -13,5 +13,5 @@ const Template: ComponentStory = (args) => Date: Sat, 16 Jul 2022 10:29:16 +0900 Subject: [PATCH 0117/1011] =?UTF-8?q?refactor:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/.storybook/main.js | 1 + frontend/src/api/categories.ts | 4 ---- frontend/src/components/CategoryItem/CategoryItem.tsx | 4 ++-- frontend/src/components/CategoryList/CategoryList.styles.ts | 2 +- frontend/src/hooks/useIntersect.ts | 4 +++- frontend/src/mocks/handlers.ts | 2 +- 6 files changed, 8 insertions(+), 9 deletions(-) diff --git a/frontend/.storybook/main.js b/frontend/.storybook/main.js index 1029233b..b640a76b 100644 --- a/frontend/.storybook/main.js +++ b/frontend/.storybook/main.js @@ -17,6 +17,7 @@ module.exports = { '@': path.resolve(__dirname, '../src/'), }; config.resolve.extensions.push('.ts', '.tsx'); + return config; }, }; diff --git a/frontend/src/api/categories.ts b/frontend/src/api/categories.ts index 62ac6f63..fdccef56 100644 --- a/frontend/src/api/categories.ts +++ b/frontend/src/api/categories.ts @@ -13,10 +13,6 @@ const categoryApi = { const response = await axios.get(categoryApi.endpoint, { params: { page, size }, headers: categoryApi.headers, - transformResponse: (res) => { - const categories = JSON.parse(res); - return categories; - }, }); return response; diff --git a/frontend/src/components/CategoryItem/CategoryItem.tsx b/frontend/src/components/CategoryItem/CategoryItem.tsx index efbe2720..ae65f07f 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.tsx +++ b/frontend/src/components/CategoryItem/CategoryItem.tsx @@ -3,11 +3,11 @@ import { useTheme } from '@emotion/react'; import { categoryItem } from './CategoryItem.styles'; -interface CategoryProps { +interface CategoryItemProps { category: CategoryType; } -function CategoryItem({ category }: CategoryProps) { +function CategoryItem({ category }: CategoryItemProps) { const theme = useTheme(); return ( diff --git a/frontend/src/components/CategoryList/CategoryList.styles.ts b/frontend/src/components/CategoryList/CategoryList.styles.ts index 4a99561a..1f6570fb 100644 --- a/frontend/src/components/CategoryList/CategoryList.styles.ts +++ b/frontend/src/components/CategoryList/CategoryList.styles.ts @@ -7,7 +7,7 @@ const categoryTable = css` const categoryTableHeader = ({ flex, colors }: Theme) => css` ${flex.row} - justify-content:space-around; + justify-content: space-around; height: 12rem; border-bottom: 2px solid ${colors.GRAY_400}; diff --git a/frontend/src/hooks/useIntersect.ts b/frontend/src/hooks/useIntersect.ts index 3a91692e..9458cf94 100644 --- a/frontend/src/hooks/useIntersect.ts +++ b/frontend/src/hooks/useIntersect.ts @@ -7,7 +7,9 @@ function useIntersect(onIntersect: IntersectHandler, options?: IntersectionObser const callback = useCallback( (entries: IntersectionObserverEntry[], observer: IntersectionObserver) => { entries.forEach((entry) => { - if (entry.isIntersecting) onIntersect(entry, observer); + if (entry.isIntersecting) { + onIntersect(entry, observer); + } }); }, [onIntersect] diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index a46fd539..91ccea8e 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -27,7 +27,7 @@ const handlers = [ ctx.status(200), ctx.json({ totalCount: 18, - page: page, + page, data: slicedCategories, }) ); From 2f0a1ad40edc88c1f7f62f303f8bf94096b33efc Mon Sep 17 00:00:00 2001 From: jhy979 Date: Sat, 16 Jul 2022 10:45:08 +0900 Subject: [PATCH 0118/1011] =?UTF-8?q?refactor:=20import=20=EC=88=9C?= =?UTF-8?q?=EC=84=9C=20prettier=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/CategoryItem/CategoryItem.stories.tsx | 2 +- .../src/components/CategoryItem/CategoryItem.tsx | 3 ++- .../components/CategoryList/CategoryList.stories.tsx | 6 +++--- .../src/components/CategoryList/CategoryList.tsx | 12 +++++++----- frontend/src/mocks/handlers.ts | 2 +- frontend/src/pages/CategoryPage/CategoryPage.tsx | 5 +++-- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/CategoryItem/CategoryItem.stories.tsx b/frontend/src/components/CategoryItem/CategoryItem.stories.tsx index 2435a9f9..535154b9 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.stories.tsx +++ b/frontend/src/components/CategoryItem/CategoryItem.stories.tsx @@ -1,4 +1,4 @@ -import { ComponentStory, ComponentMeta } from '@storybook/react'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; import CategoryItem from './CategoryItem'; diff --git a/frontend/src/components/CategoryItem/CategoryItem.tsx b/frontend/src/components/CategoryItem/CategoryItem.tsx index ae65f07f..c2eedc38 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.tsx +++ b/frontend/src/components/CategoryItem/CategoryItem.tsx @@ -1,6 +1,7 @@ -import { CategoryType } from '@/@types/category'; import { useTheme } from '@emotion/react'; +import { CategoryType } from '@/@types/category'; + import { categoryItem } from './CategoryItem.styles'; interface CategoryItemProps { diff --git a/frontend/src/components/CategoryList/CategoryList.stories.tsx b/frontend/src/components/CategoryList/CategoryList.stories.tsx index ca47ad85..e4262129 100644 --- a/frontend/src/components/CategoryList/CategoryList.stories.tsx +++ b/frontend/src/components/CategoryList/CategoryList.stories.tsx @@ -1,9 +1,9 @@ -import { ComponentStory, ComponentMeta } from '@storybook/react'; - -import CategoryList from './CategoryList'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; import { categoryDB } from '@/mocks/data'; +import CategoryList from './CategoryList'; + export default { title: 'Components/CategoryList', component: CategoryList, diff --git a/frontend/src/components/CategoryList/CategoryList.tsx b/frontend/src/components/CategoryList/CategoryList.tsx index 5ced3193..bd2b1110 100644 --- a/frontend/src/components/CategoryList/CategoryList.tsx +++ b/frontend/src/components/CategoryList/CategoryList.tsx @@ -1,11 +1,13 @@ -import { CategoriesGetResponseType, CategoryType } from '@/@types/category'; +import { AxiosError, AxiosResponse } from 'axios'; +import { FetchNextPageOptions, InfiniteQueryObserverResult } from 'react-query'; -import { categoryTable, categoryTableHeader, intersectTarget } from './CategoryList.styles'; +import useIntersect from '@/hooks/useIntersect'; + +import { CategoriesGetResponseType, CategoryType } from '@/@types/category'; import CategoryItem from '@/components/CategoryItem/CategoryItem'; -import useIntersect from '@/hooks/useIntersect'; -import { FetchNextPageOptions, InfiniteQueryObserverResult } from 'react-query'; -import { AxiosError, AxiosResponse } from 'axios'; + +import { categoryTable, categoryTableHeader, intersectTarget } from './CategoryList.styles'; interface CategoryListProps { categoryList: CategoryType[]; diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 91ccea8e..2ea43662 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -2,8 +2,8 @@ import { rest } from 'msw'; import { Schedule } from '@/@types'; -import scheduleApi from '@/api/schedule'; import categoryApi from '@/api/categories'; +import scheduleApi from '@/api/schedule'; import { categoryDB, scheduleDB } from './data'; diff --git a/frontend/src/pages/CategoryPage/CategoryPage.tsx b/frontend/src/pages/CategoryPage/CategoryPage.tsx index 6d893a77..7be2f754 100644 --- a/frontend/src/pages/CategoryPage/CategoryPage.tsx +++ b/frontend/src/pages/CategoryPage/CategoryPage.tsx @@ -1,17 +1,18 @@ +import { useTheme } from '@emotion/react'; import { AxiosError, AxiosResponse } from 'axios'; import { useInfiniteQuery } from 'react-query'; import { CategoriesGetResponseType } from '@/@types/category'; +import FieldSet from '@/components/@common/FieldSet/FieldSet'; import CategoryList from '@/components/CategoryList/CategoryList'; import PageLayout from '@/components/PageLayout/PageLayout'; import { API, CACHE_KEY } from '@/constants'; import categoryApi from '@/api/categories'; -import FieldSet from '@/components/@common/FieldSet/FieldSet'; + import { categoryNav, categoryPage, categorySearch } from './CategoryPage.styles'; -import { useTheme } from '@emotion/react'; function CategoryPage() { const theme = useTheme(); From 73d5fbaf4850b833a4d18e968a5ebb954767e6c6 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Sat, 16 Jul 2022 11:01:42 +0900 Subject: [PATCH 0119/1011] =?UTF-8?q?refactor:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/CategoryItem/CategoryItem.styles.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/components/CategoryItem/CategoryItem.styles.ts b/frontend/src/components/CategoryItem/CategoryItem.styles.ts index 0323e740..576d3fdc 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.styles.ts +++ b/frontend/src/components/CategoryItem/CategoryItem.styles.ts @@ -2,6 +2,7 @@ import { css, Theme } from '@emotion/react'; const categoryItem = ({ colors, flex }: Theme) => css` ${flex.row} + justify-content:space-around; height: 20rem; From 9a8e57c6af474bfe845ef59104546dbfb66e65db Mon Sep 17 00:00:00 2001 From: jhy979 Date: Fri, 15 Jul 2022 10:27:36 +0900 Subject: [PATCH 0120/1011] =?UTF-8?q?feat:=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=AA=A8=EB=8B=AC=20=EC=A2=85=EC=9D=BC=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/@common/FieldSet/FieldSet.tsx | 20 ++++++++- .../ScheduleAddModal.styles.ts | 6 +-- .../ScheduleAddModal/ScheduleAddModal.tsx | 42 +++++++++++++++---- frontend/src/utils/index.ts | 14 +++++-- frontend/yarn.lock | 7 ++++ 5 files changed, 72 insertions(+), 17 deletions(-) diff --git a/frontend/src/components/@common/FieldSet/FieldSet.tsx b/frontend/src/components/@common/FieldSet/FieldSet.tsx index 0361f8ed..7f436157 100644 --- a/frontend/src/components/@common/FieldSet/FieldSet.tsx +++ b/frontend/src/components/@common/FieldSet/FieldSet.tsx @@ -7,10 +7,19 @@ interface FieldSetProps extends React.HTMLAttributes { type?: string; cssProp?: SerializedStyles; labelText?: string; + defaultValue?: string; refProp?: React.MutableRefObject; } -function FieldSet({ type = 'text', id, cssProp, labelText, placeholder, refProp }: FieldSetProps) { +function FieldSet({ + type = 'text', + id, + cssProp, + labelText, + placeholder, + defaultValue, + refProp, +}: FieldSetProps) { const theme = useTheme(); return ( @@ -20,7 +29,14 @@ function FieldSet({ type = 'text', id, cssProp, labelText, placeholder, refProp {labelText} )} - +
); } diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts index 33c92ffc..fd8a0ce3 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.styles.ts @@ -16,17 +16,17 @@ const form = ({ flex }: Theme) => css` justify-content: space-between; `; -const allDayButton = ({ colors }: Theme) => css` +const allDayButton = ({ colors }: Theme, isAllDay: boolean) => css` width: 100%; height: 9rem; border: 1px solid ${colors.GRAY_500}; border-radius: 8px; filter: drop-shadow(0 2px 2px ${colors.GRAY_400}); - background: ${colors.WHITE}; + background: ${isAllDay ? colors.YELLOW_500 : colors.WHITE}; font-size: 5rem; - color: ${colors.GRAY_600}; + color: ${isAllDay ? colors.WHITE : colors.GRAY_600}; `; const dateTime = ({ flex }: Theme) => css` diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index 26b1ed39..ce89b917 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -1,17 +1,16 @@ import { useTheme } from '@emotion/react'; import { AxiosError, AxiosResponse } from 'axios'; -import { useRef } from 'react'; +import { useRef, useState } from 'react'; import { QueryObserverResult, RefetchOptions, RefetchQueryFilters, useMutation } from 'react-query'; import { Schedule } from '@/@types'; -import Button from '@/components/@common/Button/Button'; -import FieldSet from '@/components/@common/FieldSet/FieldSet'; - -import { createPostBody } from '@/utils'; +import { createPostBody, getDate, getDateTime } from '@/utils'; import scheduleApi from '@/api/schedule'; +import Button from '../@common/Button/Button'; +import FieldSet from '../@common/FieldSet/FieldSet'; import { allDayButton, arrow, @@ -31,6 +30,7 @@ interface ScheduleAddModalProps { } function ScheduleAddModal({ closeModal, refetch }: ScheduleAddModalProps) { + const [isAllDay, setAllDay] = useState(true); const theme = useTheme(); const { @@ -48,6 +48,10 @@ function ScheduleAddModal({ closeModal, refetch }: ScheduleAddModalProps) { }, }); + const handleClickAllDayButton = () => { + setAllDay((prev) => !prev); + }; + const inputRef = { title: useRef(null), startDateTime: useRef(null), @@ -80,15 +84,35 @@ function ScheduleAddModal({ closeModal, refetch }: ScheduleAddModalProps) { if (error) return <>Error; + const dateFieldSet = isAllDay + ? { + type: 'date', + defaultValue: getDate(), + } + : { + type: 'datetime-local', + defaultValue: getDateTime(), + }; + return (
- -
-
+ +
+

-
+
diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts index 80d7ce1a..bed9120c 100644 --- a/frontend/src/utils/index.ts +++ b/frontend/src/utils/index.ts @@ -1,6 +1,6 @@ import { InputRef } from '@/@types'; -function createPostBody(inputRef: InputRef) { +const createPostBody = (inputRef: InputRef) => { const inputElements = Object.values(inputRef).map((el) => el.current); const isValidInputRefs = inputElements.every((el) => el instanceof HTMLInputElement); @@ -17,6 +17,14 @@ function createPostBody(inputRef: InputRef) { }, {}); return body; -} +}; -export { createPostBody }; +const getDate = () => { + return new Date(+new Date() + 3240 * 10000).toISOString().split('T')[0]; +}; + +const getDateTime = () => { + return new Date(+new Date() + 3240 * 10000).toISOString().replace(/\..*/, '').slice(0, -3); +}; + +export { createPostBody, getDate, getDateTime }; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 6c6ee778..76eff81b 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -6760,6 +6760,13 @@ highlight.js@^10.4.1, highlight.js@~10.7.0: resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== +history@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b" + integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ== + dependencies: + "@babel/runtime" "^7.7.6" + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" From c856151a5d8dffa9d385087d993906985373fbcd Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Sun, 17 Jul 2022 03:46:48 +0900 Subject: [PATCH 0121/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=83=9D=EC=84=B1=20=EB=AA=A8=EB=8B=AC=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/@common/FieldSet/FieldSet.tsx | 3 + .../CategoryAddModal.styles.ts | 69 +++++++++++++++++++ .../CategoryAddModal/CategoryAddModal.tsx | 51 ++++++++++++++ .../ScheduleAddModal/ScheduleAddModal.tsx | 2 +- 4 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/CategoryAddModal/CategoryAddModal.styles.ts create mode 100644 frontend/src/components/CategoryAddModal/CategoryAddModal.tsx diff --git a/frontend/src/components/@common/FieldSet/FieldSet.tsx b/frontend/src/components/@common/FieldSet/FieldSet.tsx index 7f436157..f98ae37c 100644 --- a/frontend/src/components/@common/FieldSet/FieldSet.tsx +++ b/frontend/src/components/@common/FieldSet/FieldSet.tsx @@ -8,6 +8,7 @@ interface FieldSetProps extends React.HTMLAttributes { cssProp?: SerializedStyles; labelText?: string; defaultValue?: string; + autoFocus?: boolean; refProp?: React.MutableRefObject; } @@ -18,6 +19,7 @@ function FieldSet({ labelText, placeholder, defaultValue, + autoFocus, refProp, }: FieldSetProps) { const theme = useTheme(); @@ -35,6 +37,7 @@ function FieldSet({ css={input(theme)} placeholder={placeholder} defaultValue={defaultValue} + autoFocus={autoFocus} ref={refProp} />
diff --git a/frontend/src/components/CategoryAddModal/CategoryAddModal.styles.ts b/frontend/src/components/CategoryAddModal/CategoryAddModal.styles.ts new file mode 100644 index 00000000..1a3c4e86 --- /dev/null +++ b/frontend/src/components/CategoryAddModal/CategoryAddModal.styles.ts @@ -0,0 +1,69 @@ +import { css, Theme } from '@emotion/react'; + +const categoryAddModal = ({ colors, flex }: Theme) => css` + ${flex.column} + + width: 120rem; + height: 160rem; + padding: 12.5rem; + border-radius: 12px; + justify-content: space-between; + + background: ${colors.WHITE}; +`; + +const title = ({ colors }: Theme) => css` + font-size: 8rem; + font-weight: bold; + color: ${colors.GRAY_700}; +`; + +const form = ({ flex }: Theme) => css` + ${flex.column}; + + width: 100%; + height: 100%; + justify-content: space-between; +`; + +const content = ({ flex }: Theme) => css` + ${flex.column}; + + width: 100%; + height: 100%; + justify-content: center; +`; + +const controlButtons = ({ flex }: Theme) => css` + ${flex.row} + + align-self: flex-end; + gap: 5rem; +`; + +const cancelButton = ({ colors }: Theme) => css` + width: 22.5rem; + height: 10rem; + border: 2px solid ${colors.GRAY_500}; + border-radius: 8px; + filter: drop-shadow(0 2px 2px ${colors.GRAY_400}); + + background: ${colors.WHITE}; + + font-size: 5rem; + color: ${colors.GRAY_600}; +`; + +const saveButton = ({ colors }: Theme) => css` + width: 22.5rem; + height: 10rem; + border-radius: 8px; + filter: drop-shadow(0px 2px 2px ${colors.GRAY_400}); + + background: ${colors.YELLOW_500}; + + font-size: 5rem; + color: ${colors.WHITE}; +`; + +export { cancelButton, categoryAddModal, content, controlButtons, form, saveButton, title }; diff --git a/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx b/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx new file mode 100644 index 00000000..2259468a --- /dev/null +++ b/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx @@ -0,0 +1,51 @@ +import { useTheme } from '@emotion/react'; + +import Button from '@/components/@common/Button/Button'; +import FieldSet from '@/components/@common/FieldSet/FieldSet'; + +import { + cancelButton, + categoryAddModal, + content, + controlButtons, + form, + saveButton, + title, +} from './CategoryAddModal.styles'; + +interface CategoryAddModalProps { + closeModal: () => void; +} + +function CategoryAddModal({ closeModal }: CategoryAddModalProps) { + const theme = useTheme(); + + const handleClickLoginModal = (e: React.MouseEvent) => { + e.stopPropagation(); + }; + + const handleSubmitCategoryAddForm = (e: React.FormEvent) => { + e.preventDefault(); + }; + + return ( +
+

새 카테고리 만들기

+ +
+
+
+
+ + +
+ +
+ ); +} + +export default CategoryAddModal; diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index ce89b917..ad64ee26 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -63,7 +63,7 @@ function ScheduleAddModal({ closeModal, refetch }: ScheduleAddModalProps) { e.stopPropagation(); }; - const handleSubmitScheduleAddForm = async (e: React.FormEvent) => { + const handleSubmitScheduleAddForm = (e: React.FormEvent) => { e.preventDefault(); const body = createPostBody(inputRef); From 1d57c55504aae02e37d3361b69e38267c6da2ea1 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Sun, 17 Jul 2022 03:56:48 +0900 Subject: [PATCH 0122/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=83=9D=EC=84=B1=20=EB=AA=A8=EB=8B=AC=20=EC=8A=A4?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=EB=B6=81=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CategoryAddModal/CategoryAddModal.stories.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 frontend/src/components/CategoryAddModal/CategoryAddModal.stories.tsx diff --git a/frontend/src/components/CategoryAddModal/CategoryAddModal.stories.tsx b/frontend/src/components/CategoryAddModal/CategoryAddModal.stories.tsx new file mode 100644 index 00000000..91a4003d --- /dev/null +++ b/frontend/src/components/CategoryAddModal/CategoryAddModal.stories.tsx @@ -0,0 +1,12 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; + +import CategoryAddModal from './CategoryAddModal'; + +export default { + title: 'Components/CategoryAddModal', + component: CategoryAddModal, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ; + +export const Primary = Template.bind({}); From 8609ba994521de21608084f8bb5425cd51e96a3f Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Thu, 14 Jul 2022 15:26:33 +0900 Subject: [PATCH 0123/1011] =?UTF-8?q?chore:=20storybook=EC=97=90=20react-q?= =?UTF-8?q?uery=20provider=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/.storybook/preview.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/.storybook/preview.js b/frontend/.storybook/preview.js index f02ff916..4e9f7e43 100644 --- a/frontend/.storybook/preview.js +++ b/frontend/.storybook/preview.js @@ -1,8 +1,11 @@ import { ThemeProvider } from '@emotion/react'; +import { QueryClient, QueryClientProvider } from 'react-query'; import GlobalStyle from '@/styles/GlobalStyle'; import theme from '@/styles/theme'; +const queryClient = new QueryClient(); + export const parameters = { actions: { argTypesRegex: '^on[A-Z].*' }, controls: { @@ -17,7 +20,9 @@ export const decorators = [ (Story) => ( - + + + ), ]; From 759c8a6a2f105900027736085988ce6407b9cfe7 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Sat, 16 Jul 2022 14:19:40 +0900 Subject: [PATCH 0124/1011] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EB=AA=A8=EB=8B=AC=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LoginModal/LoginModal.styles.ts | 44 +++++++++++++++++++ .../src/components/LoginModal/LoginModal.tsx | 20 +++++++++ 2 files changed, 64 insertions(+) create mode 100644 frontend/src/components/LoginModal/LoginModal.styles.ts create mode 100644 frontend/src/components/LoginModal/LoginModal.tsx diff --git a/frontend/src/components/LoginModal/LoginModal.styles.ts b/frontend/src/components/LoginModal/LoginModal.styles.ts new file mode 100644 index 00000000..b8e98eed --- /dev/null +++ b/frontend/src/components/LoginModal/LoginModal.styles.ts @@ -0,0 +1,44 @@ +import { css, Theme } from '@emotion/react'; + +const loginModal = ({ colors, flex }: Theme) => css` + ${flex.column} + + width: 120rem; + height: 160rem; + padding: 12.5rem; + border-radius: 12px; + + background: ${colors.WHITE}; +`; + +const title = ({ colors }: Theme) => css` + font-size: 8rem; + font-weight: bold; + color: ${colors.GRAY_700}; +`; + +const content = ({ flex }: Theme) => css` + ${flex.column} + + height: 100%; +`; + +const googleLoginButton = ({ colors }: Theme) => css` + width: 75rem; + height: 15rem; + padding: 2rem; + border: 1px solid ${colors.GRAY_400}; + border-radius: 8px; + box-shadow: 2px 2px 2px ${colors.GRAY_400}; + + background: ${colors.WHITE}; + + font-size: 4rem; + color: ${colors.BLACK}8a; + + &:hover { + box-shadow: 3px 3px 3px ${colors.GRAY_500}; + } +`; + +export { content, googleLoginButton, loginModal, title }; diff --git a/frontend/src/components/LoginModal/LoginModal.tsx b/frontend/src/components/LoginModal/LoginModal.tsx new file mode 100644 index 00000000..c02a935d --- /dev/null +++ b/frontend/src/components/LoginModal/LoginModal.tsx @@ -0,0 +1,20 @@ +import Button from '@/components/@common/Button/Button'; + +import { content, googleLoginButton, loginModal, title } from './LoginModal.styles'; + +function LoginModal() { + const handleClickLoginModal = (e: React.MouseEvent) => { + e.stopPropagation(); + }; + + return ( +
+

로그인

+
+ +
+
+ ); +} + +export default LoginModal; From 93201ed29a217fb837a54b27a7fe39b84232f709 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Sat, 16 Jul 2022 14:23:30 +0900 Subject: [PATCH 0125/1011] =?UTF-8?q?feat:=20=EC=8B=9C=EC=9E=91=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.tsx | 2 ++ .../src/components/@common/Button/Button.tsx | 4 ++-- .../src/components/NavBar/NavBar.stories.tsx | 2 +- .../src/components/NavBar/NavBar.styles.ts | 16 +++++++++++++--- frontend/src/components/NavBar/NavBar.tsx | 18 +++++++++++++++--- .../src/components/PageLayout/PageLayout.tsx | 5 +++-- frontend/src/constants/index.ts | 1 + frontend/src/pages/StartPage/StartPage.tsx | 19 +++++++++++++++++++ 8 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 frontend/src/pages/StartPage/StartPage.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index acbe004b..e97f1520 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,6 +1,7 @@ import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'; import CalendarPage from '@/pages/CalendarPage/CalendarPage'; +import StartPage from '@/pages/StartPage/StartPage'; import { PATH } from '@/constants'; @@ -9,6 +10,7 @@ function App() { } /> + } /> ); diff --git a/frontend/src/components/@common/Button/Button.tsx b/frontend/src/components/@common/Button/Button.tsx index 82b1de48..eea7841d 100644 --- a/frontend/src/components/@common/Button/Button.tsx +++ b/frontend/src/components/@common/Button/Button.tsx @@ -1,10 +1,10 @@ -import { SerializedStyles } from '@emotion/react'; +import { SerializedStyles, Theme } from '@emotion/react'; import { button } from './Button.styles'; interface ButtonProps { type?: 'button' | 'submit' | 'reset'; - cssProp?: SerializedStyles; + cssProp?: SerializedStyles | (({ colors, flex }: Theme) => SerializedStyles); onClick?: (e?: React.FormEvent) => void; children?: string | JSX.Element | JSX.Element[]; } diff --git a/frontend/src/components/NavBar/NavBar.stories.tsx b/frontend/src/components/NavBar/NavBar.stories.tsx index 9c4dd234..12d1362b 100644 --- a/frontend/src/components/NavBar/NavBar.stories.tsx +++ b/frontend/src/components/NavBar/NavBar.stories.tsx @@ -7,6 +7,6 @@ export default { component: NavBar, } as ComponentMeta; -const Template: ComponentStory = () => ; +const Template: ComponentStory = (args) => ; export const Primary = Template.bind({}); diff --git a/frontend/src/components/NavBar/NavBar.styles.ts b/frontend/src/components/NavBar/NavBar.styles.ts index 4a5ddb6f..557c7339 100644 --- a/frontend/src/components/NavBar/NavBar.styles.ts +++ b/frontend/src/components/NavBar/NavBar.styles.ts @@ -1,6 +1,8 @@ import { css, Theme } from '@emotion/react'; -const navBar = ({ colors }: Theme) => css` +const navBar = ({ colors, flex }: Theme) => css` + ${flex.row} + position: fixed; top: 0; left: 0; @@ -9,9 +11,17 @@ const navBar = ({ colors }: Theme) => css` height: 16rem; padding: 2rem; - background: ${colors.YELLOW_500}; + background: ${colors.WHITE}; box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25); `; -export { navBar }; +const loginButton = ({ colors }: Theme) => css` + background: transparent; + + font-size: 5rem; + font-weight: bold; + color: ${colors.GRAY_700}; +`; + +export { loginButton, navBar }; diff --git a/frontend/src/components/NavBar/NavBar.tsx b/frontend/src/components/NavBar/NavBar.tsx index ee15572c..c352bde4 100644 --- a/frontend/src/components/NavBar/NavBar.tsx +++ b/frontend/src/components/NavBar/NavBar.tsx @@ -1,11 +1,23 @@ import { useTheme } from '@emotion/react'; -import { navBar } from './NavBar.styles'; +import Button from '@/components/@common/Button/Button'; -function NavBar() { +import { loginButton, navBar } from './NavBar.styles'; + +interface NavBarProps { + openLoginModal?: () => void; +} + +function NavBar({ openLoginModal }: NavBarProps) { const theme = useTheme(); - return
; + return ( +
+ +
+ ); } export default NavBar; diff --git a/frontend/src/components/PageLayout/PageLayout.tsx b/frontend/src/components/PageLayout/PageLayout.tsx index da75c9b6..a96a5487 100644 --- a/frontend/src/components/PageLayout/PageLayout.tsx +++ b/frontend/src/components/PageLayout/PageLayout.tsx @@ -3,13 +3,14 @@ import NavBar from '@/components/NavBar/NavBar'; import { content } from './PageLayout.styles'; interface PageLayoutProps { + openLoginModal?: () => void; children: JSX.Element | JSX.Element[]; } -function PageLayout({ children }: PageLayoutProps) { +function PageLayout({ openLoginModal, children }: PageLayoutProps) { return ( <> - +
{children}
); diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index e456fea2..83b1e4c9 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -9,6 +9,7 @@ const CACHE_KEY = { const PATH = { CALENDAR_PAGE: '/', + START_PAGE: '/start', }; export { API, CACHE_KEY, PATH }; diff --git a/frontend/src/pages/StartPage/StartPage.tsx b/frontend/src/pages/StartPage/StartPage.tsx new file mode 100644 index 00000000..f5da2a02 --- /dev/null +++ b/frontend/src/pages/StartPage/StartPage.tsx @@ -0,0 +1,19 @@ +import useModal from '@/hooks/useModal'; + +import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; +import LoginModal from '@/components/LoginModal/LoginModal'; +import PageLayout from '@/components/PageLayout/PageLayout'; + +function StartPage() { + const { isOpen, openModal, closeModal } = useModal(); + + return ( + + + + + + ); +} + +export default StartPage; From da7eb84c49f77db75a3768be2c2d33abf791ce33 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Sat, 16 Jul 2022 17:03:38 +0900 Subject: [PATCH 0126/1011] =?UTF-8?q?feat:=20=EA=B5=AC=EA=B8=80=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/login.ts | 22 +++++++++++++++ .../src/components/LoginModal/LoginModal.tsx | 27 ++++++++++++++++++- frontend/src/constants/index.ts | 12 ++++++--- .../src/pages/CalendarPage/CalendarPage.tsx | 21 +++++++++++++-- 4 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 frontend/src/api/login.ts diff --git a/frontend/src/api/login.ts b/frontend/src/api/login.ts new file mode 100644 index 00000000..e599d622 --- /dev/null +++ b/frontend/src/api/login.ts @@ -0,0 +1,22 @@ +import axios from 'axios'; + +const loginApi = { + baseUrl: 'http://09d2-218-39-176-142.ngrok.io/api/auth/google', + entryEndpoint: '/link', + tokenEndpoint: '/token', + + getUrl: async () => { + const { data } = await axios.get(`${loginApi.baseUrl}${loginApi.entryEndpoint}`); + + return data.data; + }, + + auth: async () => { + const code = new URLSearchParams(location.search).get('code'); + const { data } = await axios.post(`${loginApi.baseUrl}${loginApi.tokenEndpoint}`, { code }); + + return data.data.accessToken; + }, +}; + +export default loginApi; diff --git a/frontend/src/components/LoginModal/LoginModal.tsx b/frontend/src/components/LoginModal/LoginModal.tsx index c02a935d..c8f40f6a 100644 --- a/frontend/src/components/LoginModal/LoginModal.tsx +++ b/frontend/src/components/LoginModal/LoginModal.tsx @@ -1,17 +1,42 @@ +import { useQuery } from 'react-query'; + import Button from '@/components/@common/Button/Button'; +import { CACHE_KEY } from '@/constants'; + +import loginApi from '@/api/login'; + import { content, googleLoginButton, loginModal, title } from './LoginModal.styles'; function LoginModal() { + const { error, refetch } = useQuery(CACHE_KEY.ENTER, loginApi.getUrl, { + enabled: false, + onSuccess: (data) => onSuccessGetLoginUrl(data), + }); + + const onSuccessGetLoginUrl = (loginUrl: string) => { + location.href = loginUrl; + }; + const handleClickLoginModal = (e: React.MouseEvent) => { e.stopPropagation(); }; + const handleClickGoogleLoginButton = () => { + refetch(); + }; + + if (error) { + return <>Error; + } + return (

로그인

- +
); diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 83b1e4c9..91b6a344 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -3,13 +3,19 @@ const API = { }; const CACHE_KEY = { - SCHEDULES: 'schedules', + AUTH: 'auth', CATEGORIES: 'categories', + ENTER: 'enter', + SCHEDULES: 'schedules', +}; + +const STORAGE_KEY = { + ACCESS_TOKEN: 'accessToken', }; const PATH = { - CALENDAR_PAGE: '/', + CALENDAR_PAGE: '/auth', START_PAGE: '/start', }; -export { API, CACHE_KEY, PATH }; +export { API, CACHE_KEY, STORAGE_KEY, PATH }; diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index 4af23303..65b8f430 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -1,5 +1,6 @@ import { AxiosError, AxiosResponse } from 'axios'; import { useQuery } from 'react-query'; +import { useNavigate } from 'react-router-dom'; import useModal from '@/hooks/useModal'; @@ -11,11 +12,19 @@ import PageLayout from '@/components/PageLayout/PageLayout'; import ScheduleAddButton from '@/components/ScheduleAddButton/ScheduleAddButton'; import ScheduleAddModal from '@/components/ScheduleAddModal/ScheduleAddModal'; -import { CACHE_KEY } from '@/constants'; +import { CACHE_KEY, PATH, STORAGE_KEY } from '@/constants'; +import loginApi from '@/api/login'; import scheduleApi from '@/api/schedule'; function CalendarPage() { + const navigate = useNavigate(); + + const { data: accessToken } = useQuery(CACHE_KEY.AUTH, loginApi.auth, { + retry: false, + onSuccess: (data) => onSuccessAuth(data), + }); + const { isLoading, error, @@ -23,11 +32,19 @@ function CalendarPage() { refetch: refetchSchedules, } = useQuery, AxiosError>( CACHE_KEY.SCHEDULES, - scheduleApi.get + scheduleApi.get, + { + enabled: !!accessToken, + } ); const { isOpen, openModal, closeModal } = useModal(); + const onSuccessAuth = (accessToken: string) => { + localStorage.setItem(STORAGE_KEY.ACCESS_TOKEN, accessToken); + navigate(PATH.CALENDAR_PAGE); + }; + if (isLoading || schedulesGetResponse === undefined) { return <>Loading; } From 6f54b255bbb334621efa2fbb0da6fc726db1bf7c Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Mon, 18 Jul 2022 00:12:05 +0900 Subject: [PATCH 0127/1011] =?UTF-8?q?refactor:=20css=20=EC=A0=81=EC=9A=A9?= =?UTF-8?q?=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/@common/Button/Button.tsx | 2 +- frontend/src/components/LoginModal/LoginModal.tsx | 5 ++++- frontend/src/components/NavBar/NavBar.tsx | 4 ++-- .../src/components/ScheduleAddModal/ScheduleAddModal.tsx | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/@common/Button/Button.tsx b/frontend/src/components/@common/Button/Button.tsx index eea7841d..ff1db80d 100644 --- a/frontend/src/components/@common/Button/Button.tsx +++ b/frontend/src/components/@common/Button/Button.tsx @@ -4,7 +4,7 @@ import { button } from './Button.styles'; interface ButtonProps { type?: 'button' | 'submit' | 'reset'; - cssProp?: SerializedStyles | (({ colors, flex }: Theme) => SerializedStyles); + cssProp?: SerializedStyles; onClick?: (e?: React.FormEvent) => void; children?: string | JSX.Element | JSX.Element[]; } diff --git a/frontend/src/components/LoginModal/LoginModal.tsx b/frontend/src/components/LoginModal/LoginModal.tsx index c8f40f6a..b4c8818f 100644 --- a/frontend/src/components/LoginModal/LoginModal.tsx +++ b/frontend/src/components/LoginModal/LoginModal.tsx @@ -1,3 +1,4 @@ +import { useTheme } from '@emotion/react'; import { useQuery } from 'react-query'; import Button from '@/components/@common/Button/Button'; @@ -9,6 +10,8 @@ import loginApi from '@/api/login'; import { content, googleLoginButton, loginModal, title } from './LoginModal.styles'; function LoginModal() { + const theme = useTheme(); + const { error, refetch } = useQuery(CACHE_KEY.ENTER, loginApi.getUrl, { enabled: false, onSuccess: (data) => onSuccessGetLoginUrl(data), @@ -34,7 +37,7 @@ function LoginModal() {

로그인

-
diff --git a/frontend/src/components/NavBar/NavBar.tsx b/frontend/src/components/NavBar/NavBar.tsx index c352bde4..e72dd642 100644 --- a/frontend/src/components/NavBar/NavBar.tsx +++ b/frontend/src/components/NavBar/NavBar.tsx @@ -12,8 +12,8 @@ function NavBar({ openLoginModal }: NavBarProps) { const theme = useTheme(); return ( -
-
diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index ad64ee26..70f6c8d2 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -101,13 +101,13 @@ function ScheduleAddModal({ closeModal, refetch }: ScheduleAddModalProps) { -
+
-

+

Date: Mon, 18 Jul 2022 01:40:58 +0900 Subject: [PATCH 0128/1011] =?UTF-8?q?chore:=20build.gradle=EC=97=90?= =?UTF-8?q?=EC=84=9C=20JWT=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=EC=97=90=20=EC=BD=94=EB=A9=98=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/build.gradle b/backend/build.gradle index 2084efb0..8df90368 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -22,6 +22,7 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'io.rest-assured:rest-assured:4.4.0' + // JWT를 위한 의존성 implementation 'io.jsonwebtoken:jjwt-api:0.11.5' runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' From b58196cee25f2ce75f3d73bf6d11197f30b76625 Mon Sep 17 00:00:00 2001 From: devHudi Date: Mon, 18 Jul 2022 01:41:42 +0900 Subject: [PATCH 0129/1011] =?UTF-8?q?refactor:=20RestController=EC=99=80?= =?UTF-8?q?=20RequestMapping=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EC=85=98=EC=9D=98=20=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/allog/dallog/auth/controller/AuthController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java b/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java index 0458841b..f7778b93 100644 --- a/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java +++ b/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java @@ -12,8 +12,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -@RestController @RequestMapping("/api/auth") +@RestController public class AuthController { private final AuthService authService; From 65f6d7dfc3c4413e3a7576cd1e8214952664cc9b Mon Sep 17 00:00:00 2001 From: devHudi Date: Mon, 18 Jul 2022 01:44:23 +0900 Subject: [PATCH 0130/1011] =?UTF-8?q?refactor:=20=EC=B5=9C=EC=B4=88=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EC=9D=84=20=EC=A0=80=EC=9E=A5=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/auth/service/AuthService.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index 2723ac41..0967961b 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -37,9 +37,7 @@ public TokenResponse generateTokenWithCode(final String code) { OAuthMember oAuthMember = oAuthClient.getOAuthMember(code); String email = oAuthMember.getEmail(); - if (!memberService.existsByEmail(email)) { - memberService.save(generateMemberBy(oAuthMember)); - } + saveMemberIfNotExists(oAuthMember, email); Member foundMember = memberService.findByEmail(email); String accessToken = jwtTokenProvider.createToken(String.valueOf(foundMember.getId())); @@ -47,6 +45,12 @@ public TokenResponse generateTokenWithCode(final String code) { return new TokenResponse(accessToken); } + private void saveMemberIfNotExists(final OAuthMember oAuthMember, final String email) { + if (!memberService.existsByEmail(email)) { + memberService.save(generateMemberBy(oAuthMember)); + } + } + private Member generateMemberBy(final OAuthMember oAuthMember) { return new Member(oAuthMember.getEmail(), oAuthMember.getProfileImageUrl(), oAuthMember.getDisplayName(), SocialType.GOOGLE); From 767711f2180865a7ef87da2d0a4e1a6c37b1bf57 Mon Sep 17 00:00:00 2001 From: devHudi Date: Mon, 18 Jul 2022 01:44:52 +0900 Subject: [PATCH 0131/1011] =?UTF-8?q?refactor:=20final=20=ED=82=A4?= =?UTF-8?q?=EC=9B=8C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/auth/support/JwtTokenProvider.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java b/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java index cfe55175..72742118 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java @@ -19,13 +19,13 @@ public class JwtTokenProvider { private final SecretKey key; private final long validityInMilliseconds; - public JwtTokenProvider(@Value("${security.jwt.token.secret-key}") String secretKey, - @Value("${security.jwt.token.expire-length}") long validityInMilliseconds) { + public JwtTokenProvider(@Value("${security.jwt.token.secret-key}") final String secretKey, + @Value("${security.jwt.token.expire-length}") final long validityInMilliseconds) { this.key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); this.validityInMilliseconds = validityInMilliseconds; } - public String createToken(String payload) { + public String createToken(final String payload) { Date now = new Date(); Date validity = new Date(now.getTime() + validityInMilliseconds); @@ -37,7 +37,7 @@ public String createToken(String payload) { .compact(); } - public String getPayload(String token) { + public String getPayload(final String token) { return Jwts.parserBuilder() .setSigningKey(key) .build() @@ -46,7 +46,7 @@ public String getPayload(String token) { .getSubject(); } - public void validateToken(String token) { + public void validateToken(final String token) { try { Jws claims = Jwts.parserBuilder() .setSigningKey(key) From 8bf8f3b7be05cf5da413734cfb6e5f4d030b9c43 Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 14 Jul 2022 21:50:33 +0900 Subject: [PATCH 0132/1011] =?UTF-8?q?test:=20JwtTokenProvider=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/support/JwtTokenProviderTest.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java diff --git a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java b/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java new file mode 100644 index 00000000..8616643d --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java @@ -0,0 +1,65 @@ +package com.allog.dallog.auth.support; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.allog.dallog.auth.exception.InvalidTokenException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +class JwtTokenProviderTest { + + private static final String JWT_SECRET_KEY = "A".repeat(32); // Secret Key는 최소 32바이트 이상이어야함. + private static final int JWT_EXPIRE_LENGTH = 3600; + + private final JwtTokenProvider jwtTokenProvider = new JwtTokenProvider(JWT_SECRET_KEY, JWT_EXPIRE_LENGTH); + + @DisplayName("JWT 토큰을 생성한다.") + @Test + void JWT_토큰을_생성한다() { + // given + String payload = "hello"; + + // when + String actual = jwtTokenProvider.createToken(payload); + + // then + assertThat(actual.split("\\.")).hasSize(3); + } + + @DisplayName("JWT 토큰의 Payload를 가져온다.") + @Test + void JWT_토큰의_Payload를_가져온다() { + // given + String expected = "Hello"; + String token = jwtTokenProvider.createToken(expected); + + // when + String actual = jwtTokenProvider.getPayload(token); + + // then + assertThat(actual).isEqualTo(expected); + } + + @DisplayName("validateToken 메서드는 만료된 토큰을 전달하면 예외를 던진다.") + @Test + void validateToken_메서드는_만료된_토큰을_전달하면_예외를_던진다() { + // given + String expiredToken = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJoZWxsbyIsImlhdCI6MTY1NzgwMjg0MiwiZXhwIjoxNjU3ODAyODQyfQ.4feZKLtwsHneIrwvJ6YbBMIGuYpv2CqgrG5rmYhFdSI"; + + // when & then + assertThatThrownBy(() -> jwtTokenProvider.validateToken(expiredToken)) + .isInstanceOf(InvalidTokenException.class); + } + + @DisplayName("validateToken 메서드는 유효하지 않은 토큰을 전달하면 예외를 던진다.") + @Test + void validateToken_메서드는_유효하지_않은_토큰을_전달하면_예외를_던진다() { + // given + String malformedToken = "malformed"; + + // when & then + assertThatThrownBy(() -> jwtTokenProvider.validateToken(malformedToken)) + .isInstanceOf(InvalidTokenException.class); + } +} From e2615697d4e68d280388afe8a45a34e24840aae2 Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 14 Jul 2022 21:54:54 +0900 Subject: [PATCH 0133/1011] =?UTF-8?q?test:=20MemberRepository=EC=9D=98=20f?= =?UTF-8?q?indByEmail=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/domain/MemberRepositoryTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java b/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java index 1088b5c6..ad4b5b50 100644 --- a/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java @@ -13,6 +13,23 @@ class MemberRepositoryTest { @Autowired private MemberRepository memberRepository; + @DisplayName("이메일을 통해 회원을 찾는다.") + @Test + void 이메일을_통해_회원을_찾는다() { + // given + String email = "devhudi@gmail.com"; + String profileImageUrl = "/image.png"; + String displayName = "후디"; + Member member = new Member(email, profileImageUrl, displayName, SocialType.GOOGLE); + Member savedMember = memberRepository.save(member); + + // when + Member foundMember = memberRepository.findByEmail(email).get(); + + // then + assertThat(savedMember.getId()).isEqualTo(foundMember.getId()); + } + @DisplayName("중복된 이메일이 존재하는 경우 true를 반환한다.") @Test void 중복된_이메일이_존재하는_경우_true를_반환한다() { From 8d6c172baecae50576a92875cff3845922bba6ac Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 14 Jul 2022 22:05:43 +0900 Subject: [PATCH 0134/1011] =?UTF-8?q?test:=20MemberService=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/service/MemberServiceTest.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java diff --git a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java b/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java new file mode 100644 index 00000000..4869bd35 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java @@ -0,0 +1,67 @@ +package com.allog.dallog.member.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.domain.SocialType; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class MemberServiceTest { + + @Autowired + private MemberService memberService; + + @DisplayName("회원을 저장한다.") + @Test + void 회원을_저장한다() { + // given + Member member = new Member("devhudi@gmail.com", "/image.png", "후디", SocialType.GOOGLE); + + // when + Member actual = memberService.save(member); + + // then + assertThat(actual).isNotNull(); + } + + @DisplayName("이메일로 회원을 찾는다.") + @Test + void 이메일로_회원을_찾는다() { + // given + String email = "newmember@gmail.com"; + String profileImageUrl = "/image.png"; + String displayName = "후디"; + Member member = new Member(email, profileImageUrl, displayName, SocialType.GOOGLE); + Member savedMember = memberService.save(member); + + // when + Member foundMember = memberService.findByEmail(email); + + // then + assertThat(foundMember.getId()).isEqualTo(savedMember.getId()); + } + + @DisplayName("주어진 이메일로 가입된 회원이 있는지 확인한다.") + @CsvSource(value = {"registerd@gmail.com,true", "notregistered@naver.com,false"}) + @ParameterizedTest + void 주어진_이메일로_가입된_회원이_있는지_확인한다(String input, boolean expected) { + // given + String email = "registerd@gmail.com"; + String profileImageUrl = "/image.png"; + String displayName = "후디"; + Member member = new Member(email, profileImageUrl, displayName, SocialType.GOOGLE); + memberService.save(member); + + // when + boolean actual = memberService.existsByEmail(input); + + // then + assertThat(actual).isEqualTo(expected); + } +} From 70e8faf5d75d582e2af806cb2d97835564ca1e9b Mon Sep 17 00:00:00 2001 From: devHudi Date: Fri, 15 Jul 2022 15:15:51 +0900 Subject: [PATCH 0135/1011] =?UTF-8?q?test:=20AuthService=EC=9D=98=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=20=EC=83=9D=EC=84=B1=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/auth/service/AuthServiceTest.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index fcef9c40..9b8be284 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -4,6 +4,9 @@ import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.config.TestConfig; +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.domain.MemberRepository; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -15,6 +18,9 @@ class AuthServiceTest { @Autowired private AuthService authService; + @Autowired + private MemberRepository memberRepository; + @DisplayName("구글 로그인을 위한 링크를 생성한다.") @Test void 구글_로그인을_위한_링크를_생성한다() { @@ -37,4 +43,36 @@ class AuthServiceTest { // then assertThat(actual.getAccessToken()).isNotEmpty(); } + + @DisplayName("Authorization Code를 받으면 회원이 데이터베이스에 저장된다.") + @Test + void Authorization_Code를_받으면_회원이_데이터베이스에_저장된다() { + // given + String code = "authorization code"; + authService.generateTokenWithCode(code); + + // when + boolean actual = memberRepository.existsByEmail("dev.hyeonic@gmail.com"); + // SutbOAuthClient가 반환하는 OAuthMember의 이메일 + + // then + assertThat(actual).isTrue(); + } + + @DisplayName("이미 가입된 회원에 대한 Authorization Code를 전달받으면 추가로 유저가 생성되지 않는다") + @Test + void 이미_가입된_회원에_대한_Authorization_Code를_전달받으면_유저가_추가로_생성되지_않는다() { + // 이미 가입된 유저가 소셜 로그인 버튼을 클릭했을 경우엔 회원가입 과정이 생략되고, 곧바로 access token이 발급되어야 한다. + + // given + String code = "authorization code"; + authService.generateTokenWithCode(code); + + // when & then + authService.generateTokenWithCode(code); + List actual = memberRepository.findAll(); + + // then + assertThat(actual).hasSize(1); + } } From edac42c87770bf63dd3080c8f863e7d4886199f3 Mon Sep 17 00:00:00 2001 From: devHudi Date: Mon, 18 Jul 2022 01:36:42 +0900 Subject: [PATCH 0136/1011] =?UTF-8?q?test:=20JwtTokenProviderTest=EC=9D=98?= =?UTF-8?q?=20=EB=A7=8C=EB=A3=8C=20=ED=86=A0=ED=81=B0=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=97=90=EC=84=9C=20=EB=8F=99=EC=A0=81=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=A7=8C=EB=A3=8C=20=ED=86=A0=ED=81=B0=EC=9D=84=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=95=98=EB=8F=84=EB=A1=9D=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/auth/support/JwtTokenProviderTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java b/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java index 8616643d..bf2c5c99 100644 --- a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java @@ -45,7 +45,8 @@ class JwtTokenProviderTest { @Test void validateToken_메서드는_만료된_토큰을_전달하면_예외를_던진다() { // given - String expiredToken = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJoZWxsbyIsImlhdCI6MTY1NzgwMjg0MiwiZXhwIjoxNjU3ODAyODQyfQ.4feZKLtwsHneIrwvJ6YbBMIGuYpv2CqgrG5rmYhFdSI"; + JwtTokenProvider expiredJwtTokenProvider = new JwtTokenProvider(JWT_SECRET_KEY, 0); + String expiredToken = expiredJwtTokenProvider.createToken("payload"); // when & then assertThatThrownBy(() -> jwtTokenProvider.validateToken(expiredToken)) From 9579a70e261628b6e627b622f8de3425f9df0cdc Mon Sep 17 00:00:00 2001 From: devHudi Date: Mon, 18 Jul 2022 01:37:53 +0900 Subject: [PATCH 0137/1011] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20DisplayName=EA=B3=BC=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=EB=AA=85=EC=9D=B4=20=EC=9D=BC=EC=B9=98?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/allog/dallog/auth/service/AuthServiceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index 9b8be284..3229666e 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -61,7 +61,7 @@ class AuthServiceTest { @DisplayName("이미 가입된 회원에 대한 Authorization Code를 전달받으면 추가로 유저가 생성되지 않는다") @Test - void 이미_가입된_회원에_대한_Authorization_Code를_전달받으면_유저가_추가로_생성되지_않는다() { + void 이미_가입된_회원에_대한_Authorization_Code를_전달받으면_추가로_유저가_생성되지_않는다() { // 이미 가입된 유저가 소셜 로그인 버튼을 클릭했을 경우엔 회원가입 과정이 생략되고, 곧바로 access token이 발급되어야 한다. // given From 797c8a74325a0fba4f00fe167527d3924db2490e Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 18 Jul 2022 13:33:36 +0900 Subject: [PATCH 0138/1011] =?UTF-8?q?feat:=20=EB=82=B4=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/@types/profile.ts | 13 +++++ frontend/src/App.tsx | 5 ++ frontend/src/api/profile.ts | 26 +++++++++ frontend/src/constants/index.ts | 2 + frontend/src/mocks/data.ts | 12 +++- frontend/src/mocks/handlers.ts | 7 ++- frontend/src/pages/MyPage/MyPage.styles.ts | 60 +++++++++++++++++++ frontend/src/pages/MyPage/MyPage.tsx | 67 ++++++++++++++++++++++ 8 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 frontend/src/@types/profile.ts create mode 100644 frontend/src/api/profile.ts create mode 100644 frontend/src/pages/MyPage/MyPage.styles.ts create mode 100644 frontend/src/pages/MyPage/MyPage.tsx diff --git a/frontend/src/@types/profile.ts b/frontend/src/@types/profile.ts new file mode 100644 index 00000000..2bd8103e --- /dev/null +++ b/frontend/src/@types/profile.ts @@ -0,0 +1,13 @@ +interface ProfileType { + id: number; + email: string; + displayName: string; + profileImageUri: string; + socialType: string; +} + +interface ProfileGetResponseType { + data: ProfileType; +} + +export { ProfileType, ProfileGetResponseType }; diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index e97f1520..47bc598b 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -5,12 +5,17 @@ import StartPage from '@/pages/StartPage/StartPage'; import { PATH } from '@/constants'; +import CategoryPage from './pages/CategoryPage/CategoryPage'; +import MyPage from './pages/MyPage/MyPage'; + function App() { return ( } /> } /> + } /> + } /> ); diff --git a/frontend/src/api/profile.ts b/frontend/src/api/profile.ts new file mode 100644 index 00000000..b4fea33e --- /dev/null +++ b/frontend/src/api/profile.ts @@ -0,0 +1,26 @@ +import axios from 'axios'; + +import { ProfileType } from '@/@types/profile'; + +const profileApi = { + endpoint: '/api/members/me', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + + get: async (accessToken: string) => { + const response = await axios.get(profileApi.endpoint, { + headers: { ...profileApi.headers, Authorization: `Bearer ${accessToken}` }, + transformResponse: (res) => { + const profile = JSON.parse(res).data; + + return profile; + }, + }); + + return response; + }, +}; + +export default profileApi; diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 91b6a344..97cbe241 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -15,7 +15,9 @@ const STORAGE_KEY = { const PATH = { CALENDAR_PAGE: '/auth', + CATEGORY: 'category', START_PAGE: '/start', + PROFILE: 'profile', }; export { API, CACHE_KEY, STORAGE_KEY, PATH }; diff --git a/frontend/src/mocks/data.ts b/frontend/src/mocks/data.ts index 32afbc63..d41f32bb 100644 --- a/frontend/src/mocks/data.ts +++ b/frontend/src/mocks/data.ts @@ -115,4 +115,14 @@ const categoryDB: { ], }; -export { scheduleDB, categoryDB }; +const profileDB = { + data: { + id: 1, + email: 'example@email.com', + displayName: '매트', + profileImageUri: 'https://img.insight.co.kr/static/2020/05/04/700/51wlu5y2281iku1o0hms.jpg', + socialType: 'GOOGLE', + }, +}; + +export { scheduleDB, categoryDB, profileDB }; diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 2ea43662..0ca22546 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -3,9 +3,10 @@ import { rest } from 'msw'; import { Schedule } from '@/@types'; import categoryApi from '@/api/categories'; +import profileApi from '@/api/profile'; import scheduleApi from '@/api/schedule'; -import { categoryDB, scheduleDB } from './data'; +import { categoryDB, profileDB, scheduleDB } from './data'; const handlers = [ rest.post>(scheduleApi.endpoint, (req, res, ctx) => { @@ -32,6 +33,10 @@ const handlers = [ }) ); }), + + rest.get(profileApi.endpoint, (req, res, ctx) => { + return res(ctx.status(200), ctx.json(profileDB)); + }), ]; export { handlers }; diff --git a/frontend/src/pages/MyPage/MyPage.styles.ts b/frontend/src/pages/MyPage/MyPage.styles.ts new file mode 100644 index 00000000..ead9f1d5 --- /dev/null +++ b/frontend/src/pages/MyPage/MyPage.styles.ts @@ -0,0 +1,60 @@ +import { css, Theme } from '@emotion/react'; + +const myPage = ({ colors }: Theme) => css` + width: 100vw; + height: 100vh; + + background: ${colors.GRAY_100}; +`; + +const infoTable = ({ colors }: Theme) => css` + width: 60%; + padding: 4rem; + margin: 0 auto; + border: 1px solid ${colors.GRAY_500}; + + background: ${colors.WHITE}; +`; + +const infoTableHeader = ({ colors }: Theme) => css` + width: 100%; + margin: 0 auto; + padding: 4rem; + border-bottom: 1px solid ${colors.GRAY_500}; + + font-size: 5rem; +`; + +const textInfo = ({ colors, flex }: Theme) => css` + ${flex.row} + + justify-content:space-between; + + width: 96%; + padding: 3rem; + margin: 5rem auto; + border-bottom: 1px solid ${colors.GRAY_500}; + + font-size: 3.5rem; +`; + +const imageInfo = ({ flex }: Theme) => css` + ${flex.row} + + align-items: flex-start; + justify-content: space-between; + + width: 96%; + height: 40rem; + padding: 3rem; + margin: 5rem auto; + + font-size: 3.5rem; +`; + +const imageSize = css` + width: 40rem; + height: 40rem; +`; + +export { myPage, infoTable, infoTableHeader, textInfo, imageInfo, imageSize }; diff --git a/frontend/src/pages/MyPage/MyPage.tsx b/frontend/src/pages/MyPage/MyPage.tsx new file mode 100644 index 00000000..0a2772eb --- /dev/null +++ b/frontend/src/pages/MyPage/MyPage.tsx @@ -0,0 +1,67 @@ +import { useTheme } from '@emotion/react'; +import { AxiosError, AxiosResponse } from 'axios'; +import { useQuery } from 'react-query'; + +import { ProfileType } from '@/@types/profile'; + +import PageLayout from '@/components/PageLayout/PageLayout'; + +import { CACHE_KEY } from '@/constants'; + +import profileAPI from '@/api/profile'; + +import { + imageInfo, + imageSize, + infoTable, + infoTableHeader, + myPage, + textInfo, +} from './MyPage.styles'; + +function MyPage() { + const accessToken = 'Bearer aaaaaaaaaa.bbbbbbbbbb.cccccccccc'; + + const theme = useTheme(); + const { + isLoading, + error, + data: profileGetResponse, + } = useQuery, AxiosError>(CACHE_KEY.PROFILE, () => + profileAPI.get(accessToken) + ); + + if (isLoading || profileGetResponse === undefined) { + return
Loading
; + } + + if (error) { + return
Error
; + } + + const { displayName, email, profileImageUri } = profileGetResponse.data; + + return ( + +
+
+
프로필
+
+ 이름(닉네임) + {displayName} +
+
+ 계정 + {email} +
+
+ 프로필 사진 + 프로필 이미지 +
+
+
+
+ ); +} + +export default MyPage; From 3f70b6a1c11d1539d949f0c3a4ec3c5ac63eb1b7 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 18 Jul 2022 14:50:06 +0900 Subject: [PATCH 0139/1011] =?UTF-8?q?refactor:=20=EC=83=81=EB=8C=80?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=20=EC=A0=88=EB=8C=80=EA=B2=BD=EB=A1=9C?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 47bc598b..8c44c85d 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,13 +1,12 @@ import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'; import CalendarPage from '@/pages/CalendarPage/CalendarPage'; +import CategoryPage from '@/pages/CategoryPage/CategoryPage'; +import MyPage from '@/pages/MyPage/MyPage'; import StartPage from '@/pages/StartPage/StartPage'; import { PATH } from '@/constants'; -import CategoryPage from './pages/CategoryPage/CategoryPage'; -import MyPage from './pages/MyPage/MyPage'; - function App() { return ( From eeec54facdf8f54e616faff590f1a4dfc3e0be7a Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 18 Jul 2022 14:50:18 +0900 Subject: [PATCH 0140/1011] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20import=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/@common/Button/Button.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/@common/Button/Button.tsx b/frontend/src/components/@common/Button/Button.tsx index ff1db80d..82b1de48 100644 --- a/frontend/src/components/@common/Button/Button.tsx +++ b/frontend/src/components/@common/Button/Button.tsx @@ -1,4 +1,4 @@ -import { SerializedStyles, Theme } from '@emotion/react'; +import { SerializedStyles } from '@emotion/react'; import { button } from './Button.styles'; From 4bff8cc15410cc9987ca0fe5bbf35a6d2d77e360 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 18 Jul 2022 14:50:36 +0900 Subject: [PATCH 0141/1011] =?UTF-8?q?refactor:=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=EC=83=81=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/constants/index.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 97cbe241..a3957094 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -7,6 +7,7 @@ const CACHE_KEY = { CATEGORIES: 'categories', ENTER: 'enter', SCHEDULES: 'schedules', + PROFILE: 'profile', }; const STORAGE_KEY = { @@ -15,9 +16,9 @@ const STORAGE_KEY = { const PATH = { CALENDAR_PAGE: '/auth', - CATEGORY: 'category', + CATEGORY: '/category', START_PAGE: '/start', - PROFILE: 'profile', + PROFILE: '/profile', }; export { API, CACHE_KEY, STORAGE_KEY, PATH }; From 3f71df1d4e0f435ff0cdf77c0cad7d1827302f6e Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 18 Jul 2022 14:51:02 +0900 Subject: [PATCH 0142/1011] =?UTF-8?q?refactor:=20=EB=82=B4=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/MyPage/MyPage.styles.ts | 2 +- frontend/src/pages/MyPage/MyPage.tsx | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/frontend/src/pages/MyPage/MyPage.styles.ts b/frontend/src/pages/MyPage/MyPage.styles.ts index ead9f1d5..27078b68 100644 --- a/frontend/src/pages/MyPage/MyPage.styles.ts +++ b/frontend/src/pages/MyPage/MyPage.styles.ts @@ -28,7 +28,7 @@ const infoTableHeader = ({ colors }: Theme) => css` const textInfo = ({ colors, flex }: Theme) => css` ${flex.row} - justify-content:space-between; + justify-content: space-between; width: 96%; padding: 3rem; diff --git a/frontend/src/pages/MyPage/MyPage.tsx b/frontend/src/pages/MyPage/MyPage.tsx index 0a2772eb..f076720f 100644 --- a/frontend/src/pages/MyPage/MyPage.tsx +++ b/frontend/src/pages/MyPage/MyPage.tsx @@ -1,4 +1,3 @@ -import { useTheme } from '@emotion/react'; import { AxiosError, AxiosResponse } from 'axios'; import { useQuery } from 'react-query'; @@ -22,7 +21,6 @@ import { function MyPage() { const accessToken = 'Bearer aaaaaaaaaa.bbbbbbbbbb.cccccccccc'; - const theme = useTheme(); const { isLoading, error, @@ -43,7 +41,7 @@ function MyPage() { return ( -
+
프로필
From 84b9c1bae00da89174c4a9a75387cca3b373b54c Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Mon, 18 Jul 2022 16:53:23 +0900 Subject: [PATCH 0143/1011] =?UTF-8?q?fix:=20=EB=88=84=EB=9D=BD=EB=90=9C=20?= =?UTF-8?q?await=20=EC=97=B0=EC=82=B0=EC=9E=90=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/schedule.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/api/schedule.ts b/frontend/src/api/schedule.ts index 5915e00a..68e306ae 100644 --- a/frontend/src/api/schedule.ts +++ b/frontend/src/api/schedule.ts @@ -18,7 +18,7 @@ const scheduleApi = { }, post: async (body: Omit) => { - const response = axios.post(scheduleApi.endpoint, body, { + const response = await axios.post(scheduleApi.endpoint, body, { headers: scheduleApi.headers, }); From 4fb03d5932801ffc8ce11382367b1fd37371c171 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Mon, 18 Jul 2022 17:06:55 +0900 Subject: [PATCH 0144/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/{categories.ts => category.ts} | 10 +++++- .../CategoryAddModal/CategoryAddModal.tsx | 34 ++++++++++++++++++- .../src/pages/CategoryPage/CategoryPage.tsx | 2 +- 3 files changed, 43 insertions(+), 3 deletions(-) rename frontend/src/api/{categories.ts => category.ts} (61%) diff --git a/frontend/src/api/categories.ts b/frontend/src/api/category.ts similarity index 61% rename from frontend/src/api/categories.ts rename to frontend/src/api/category.ts index fdccef56..11deb87a 100644 --- a/frontend/src/api/categories.ts +++ b/frontend/src/api/category.ts @@ -1,6 +1,6 @@ import axios from 'axios'; -import { CategoriesGetResponseType } from '@/@types/category'; +import { CategoriesGetResponseType, CategoryType } from '@/@types/category'; const categoryApi = { endpoint: '/api/categories', @@ -17,6 +17,14 @@ const categoryApi = { return response; }, + + post: async (body: Pick) => { + const response = await axios.post(categoryApi.endpoint, body, { + headers: categoryApi.headers, + }); + + return response; + }, }; export default categoryApi; diff --git a/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx b/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx index 2259468a..7c81cb61 100644 --- a/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx +++ b/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx @@ -1,8 +1,17 @@ import { useTheme } from '@emotion/react'; +import { AxiosError, AxiosResponse } from 'axios'; +import { useRef } from 'react'; +import { useMutation } from 'react-query'; + +import { CategoryType } from '@/@types/category'; import Button from '@/components/@common/Button/Button'; import FieldSet from '@/components/@common/FieldSet/FieldSet'; +import { createPostBody } from '@/utils'; + +import categoryApi from '@/api/category'; + import { cancelButton, categoryAddModal, @@ -20,12 +29,35 @@ interface CategoryAddModalProps { function CategoryAddModal({ closeModal }: CategoryAddModalProps) { const theme = useTheme(); + const { mutate } = useMutation< + AxiosResponse<{ name: string }>, + AxiosError, + Pick, + unknown + >(categoryApi.post, { onSuccess: () => onSuccessPostCategory() }); + + const inputRef = { + name: useRef(null), + }; + const handleClickLoginModal = (e: React.MouseEvent) => { e.stopPropagation(); }; const handleSubmitCategoryAddForm = (e: React.FormEvent) => { e.preventDefault(); + + const body = createPostBody(inputRef); + + if (!body) { + return; + } + + mutate(body); + }; + + const onSuccessPostCategory = () => { + closeModal(); }; return ( @@ -33,7 +65,7 @@ function CategoryAddModal({ closeModal }: CategoryAddModalProps) {

새 카테고리 만들기

-
+
@@ -533,11 +529,11 @@

RequestParameters

year

-

일정을 조회할 년도

+

년도

month

-

일정을 조회할 월

+

@@ -548,19 +544,15 @@

Response

HTTP/1.1 200 OK
 Content-Type: application/json
-Transfer-Encoding: chunked
-Date: Thu, 14 Jul 2022 05:25:51 GMT
-Keep-Alive: timeout=60
-Connection: keep-alive
-Content-Length: 219
+Content-Length: 180
 
 {
   "data" : [ {
     "id" : 1,
-    "title" : "7월 팀 회식",
-    "startDateTime" : "2022-07-04T18:00:00",
-    "endDateTime" : "2022-07-04T21:00:00",
-    "memo" : "18시 호프집 회식 - 인원 6명"
+    "title" : "알록",
+    "startDateTime" : "2022-07-15T14:20:00",
+    "endDateTime" : "2022-07-15T16:20:00",
+    "memo" : "달록"
   } ]
 }
@@ -573,7 +565,7 @@

Response

diff --git a/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java b/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java index add6bb79..66edb796 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java @@ -47,13 +47,13 @@ class ScheduleControllerTest { void 일정_정보를_등록한다() throws Exception { // given Map params = new HashMap<>(); - params.put("title", "팀 회의"); - params.put("startDateTime", "2022-07-04T18:00"); - params.put("endDateTime", "2022-07-04T21:00"); + params.put("title", "알록"); + params.put("startDateTime", "2022-07-15T14:20"); + params.put("endDateTime", "2022-07-15T16:20"); params.put("memo", "세모 회의실 6시 회의"); - given(scheduleService.save(new ScheduleCreateRequest("팀 회의", LocalDateTime.of(2022, 7, 10, 0, 0), - LocalDateTime.of(2022, 7, 10, 0, 0), "세모 회의실 6시 회의"))) + given(scheduleService.save(new ScheduleCreateRequest("알록", LocalDateTime.of(2022, 7, 15, 14, 20), + LocalDateTime.of(2022, 7, 15, 16, 20), "달록"))) .willReturn(1L); // when & then @@ -74,8 +74,8 @@ class ScheduleControllerTest { void 월별_일정_정보를_조회한다() throws Exception { //given given(scheduleService.findByYearAndMonth(2022, 7)) - .willReturn(List.of(new ScheduleResponse(1L, "dd", LocalDateTime.of(2022, 7, 10, 0, 0), - LocalDateTime.of(2022, 7, 10, 10, 0), "호호"))); + .willReturn(List.of(new ScheduleResponse(1L, "알록", LocalDateTime.of(2022, 7, 15, 14, 20), + LocalDateTime.of(2022, 7, 15, 16, 20), "달록"))); // when & then mockMvc.perform(get("/api/schedules?year=2022&month=7") From 11d0a6958022fb26714c33ff3b3b28fb0e10cec0 Mon Sep 17 00:00:00 2001 From: koo Date: Mon, 18 Jul 2022 20:32:22 +0900 Subject: [PATCH 0158/1011] =?UTF-8?q?fix:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EA=B2=A9=EB=A6=AC=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/DatabaseCleaner.java | 42 ------------------- .../dallog/acceptance/AcceptanceTest.java | 4 +- .../category/service/CategoryServiceTest.java | 3 -- .../domain/ScheduleRepositoryTest.java | 2 - .../schedule/service/ScheduleServiceTest.java | 3 -- .../src/test/resources/application.properties | 2 +- 6 files changed, 3 insertions(+), 53 deletions(-) delete mode 100644 backend/src/test/java/com/allog/dallog/DatabaseCleaner.java diff --git a/backend/src/test/java/com/allog/dallog/DatabaseCleaner.java b/backend/src/test/java/com/allog/dallog/DatabaseCleaner.java deleted file mode 100644 index ab19dc81..00000000 --- a/backend/src/test/java/com/allog/dallog/DatabaseCleaner.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.allog.dallog; - -import java.util.List; -import java.util.Locale; -import java.util.stream.Collectors; -import javax.persistence.EntityManager; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; - -@Component -@Profile("test") -public class DatabaseCleaner implements InitializingBean { - - private final EntityManager entityManager; - - private List tableNames; - - public DatabaseCleaner(final EntityManager entityManager) { - this.entityManager = entityManager; - } - - @Override - public void afterPropertiesSet() { - tableNames = entityManager.getMetamodel().getEntities().stream() - .map(entry -> entry.getName().toLowerCase(Locale.ROOT)) - .collect(Collectors.toList()); - } - - @Transactional - public void execute() { - entityManager.flush(); - entityManager.createNativeQuery("SET REFERENTIAL_INTEGRITY FALSE").executeUpdate(); - for (String tableName : tableNames) { - entityManager.createNativeQuery("TRUNCATE TABLE " + tableName).executeUpdate(); - entityManager.createNativeQuery("ALTER TABLE " + tableName + " ALTER COLUMN id RESTART WITH 1") - .executeUpdate(); - } - entityManager.createNativeQuery("SET REFERENTIAL_INTEGRITY TRUE").executeUpdate(); - } -} diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java index ac2144f1..f5876d0f 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java @@ -9,9 +9,9 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpStatus; -import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.annotation.DirtiesContext; -@ActiveProfiles("test") +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class AcceptanceTest { diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 90371c44..b18a5e56 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -14,12 +14,9 @@ import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -<<<<<<< HEAD import org.springframework.data.domain.PageRequest; -======= import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.annotation.Transactional; ->>>>>>> 2cf9fb9 (refactor: 전체 테스트 코드 격리 및 변경) @ActiveProfiles("test") @Transactional diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java index 569563a4..0e4ac470 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java @@ -8,10 +8,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.test.context.ActiveProfiles; @DataJpaTest -@ActiveProfiles("test") class ScheduleRepositoryTest { @Autowired diff --git a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java index 68d39ace..92351246 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java @@ -3,7 +3,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.allog.dallog.DatabaseCleaner; import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; import com.allog.dallog.schedule.dto.response.ScheduleResponse; import com.allog.dallog.schedule.exception.InvalidScheduleException; @@ -13,10 +12,8 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.annotation.Transactional; -@ActiveProfiles("test") @Transactional @SpringBootTest class ScheduleServiceTest { diff --git a/backend/src/test/resources/application.properties b/backend/src/test/resources/application.properties index b7823bc2..264bcbae 100644 --- a/backend/src/test/resources/application.properties +++ b/backend/src/test/resources/application.properties @@ -2,7 +2,7 @@ spring.datasource.url=jdbc:h2:~/dallog;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_ spring.datasource.username=sa spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true -spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.ddl-auto=create-drop logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE spring.main.allow-bean-definition-overriding=true oauth.google.redirect_uri=http://localhost:3000 From cc627b21247a4f433582f0372321009c099aa8ae Mon Sep 17 00:00:00 2001 From: hyeonic Date: Fri, 15 Jul 2022 15:04:06 +0900 Subject: [PATCH 0159/1011] =?UTF-8?q?feat:=20RestTemplate=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EB=B9=88=20=EC=84=A4=EC=A0=95=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/global/config/RestTemplateConfig.java | 14 -------------- .../oauth/client/GoogleOAuthClient.java | 5 +++-- 2 files changed, 3 insertions(+), 16 deletions(-) delete mode 100644 backend/src/main/java/com/allog/dallog/global/config/RestTemplateConfig.java diff --git a/backend/src/main/java/com/allog/dallog/global/config/RestTemplateConfig.java b/backend/src/main/java/com/allog/dallog/global/config/RestTemplateConfig.java deleted file mode 100644 index ef5591f1..00000000 --- a/backend/src/main/java/com/allog/dallog/global/config/RestTemplateConfig.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.allog.dallog.global.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.client.RestTemplate; - -@Configuration -public class RestTemplateConfig { - - @Bean - public RestTemplate restTemplate() { - return new RestTemplate(); - } -} diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java index 84b2f4af..848c6a79 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -34,12 +35,12 @@ public GoogleOAuthClient(@Value("${oauth.google.redirect_uri}") final String goo @Value("${oauth.google.client_id}") final String googleClientId, @Value("${oauth.google.client_secret}") final String googleClientSecret, @Value("${oauth.google.token_uri}") final String googleTokenUri, - final RestTemplate restTemplate, final ObjectMapper objectMapper) { + final RestTemplateBuilder restTemplateBuilder, final ObjectMapper objectMapper) { this.googleRedirectUri = googleRedirectUri; this.googleClientId = googleClientId; this.googleClientSecret = googleClientSecret; this.googleTokenUri = googleTokenUri; - this.restTemplate = restTemplate; + this.restTemplate = restTemplateBuilder.build(); this.objectMapper = objectMapper; } From eb508a056633161c106fe4db7e1d7218e4a74944 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Fri, 15 Jul 2022 15:15:21 +0900 Subject: [PATCH 0160/1011] =?UTF-8?q?feat:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=ED=98=95=EC=8B=9D=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/EmptyAuthorizationHeaderException.java | 12 ++++++++++++ .../dallog/auth/exception/InvalidTokenException.java | 8 ++++---- .../auth/exception/InvalidTokenFormatException.java | 12 ++++++++++++ .../category/exception/InvalidCategoryException.java | 8 ++++---- .../member/exception/InvalidMemberException.java | 8 ++++---- .../member/exception/NoSuchMemberException.java | 8 ++++---- .../schedule/exception/InvalidScheduleException.java | 8 ++++---- 7 files changed, 44 insertions(+), 20 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/auth/exception/EmptyAuthorizationHeaderException.java create mode 100644 backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenFormatException.java diff --git a/backend/src/main/java/com/allog/dallog/auth/exception/EmptyAuthorizationHeaderException.java b/backend/src/main/java/com/allog/dallog/auth/exception/EmptyAuthorizationHeaderException.java new file mode 100644 index 00000000..b1eaa72d --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/exception/EmptyAuthorizationHeaderException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.auth.exception; + +public class EmptyAuthorizationHeaderException extends RuntimeException { + + public EmptyAuthorizationHeaderException(final String message) { + super(message); + } + + public EmptyAuthorizationHeaderException() { + this("header에 Authorization이 존재하지 않습니다."); + } +} diff --git a/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenException.java b/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenException.java index 031bc033..20977fd0 100644 --- a/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenException.java +++ b/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenException.java @@ -2,11 +2,11 @@ public class InvalidTokenException extends RuntimeException { - public InvalidTokenException() { - super("유효하지 않은 토큰입니다."); - } - public InvalidTokenException(final String message) { super(message); } + + public InvalidTokenException() { + this("유효하지 않은 토큰입니다."); + } } diff --git a/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenFormatException.java b/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenFormatException.java new file mode 100644 index 00000000..e97e6c51 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenFormatException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.auth.exception; + +public class InvalidTokenFormatException extends RuntimeException { + + public InvalidTokenFormatException(final String message) { + super(message); + } + + public InvalidTokenFormatException() { + this("token 형식이 잘못 되었습니다. (형식: Bearer aaaaaaaa.bbbbbbbb.cccccccc)"); + } +} diff --git a/backend/src/main/java/com/allog/dallog/category/exception/InvalidCategoryException.java b/backend/src/main/java/com/allog/dallog/category/exception/InvalidCategoryException.java index 80b35ab8..f1ff2b85 100644 --- a/backend/src/main/java/com/allog/dallog/category/exception/InvalidCategoryException.java +++ b/backend/src/main/java/com/allog/dallog/category/exception/InvalidCategoryException.java @@ -2,11 +2,11 @@ public class InvalidCategoryException extends RuntimeException { - public InvalidCategoryException() { - super("잘못된 카테고리입니다."); - } - public InvalidCategoryException(final String message) { super(message); } + + public InvalidCategoryException() { + this("잘못된 카테고리입니다."); + } } diff --git a/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java b/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java index f50bd95b..95c59d0a 100644 --- a/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java +++ b/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java @@ -2,11 +2,11 @@ public class InvalidMemberException extends RuntimeException { - public InvalidMemberException() { - super("잘못된 회원의 정보입니다."); - } - public InvalidMemberException(final String message) { super(message); } + + public InvalidMemberException() { + super("잘못된 회원의 정보입니다."); + } } diff --git a/backend/src/main/java/com/allog/dallog/member/exception/NoSuchMemberException.java b/backend/src/main/java/com/allog/dallog/member/exception/NoSuchMemberException.java index 2a4be939..2e80ad89 100644 --- a/backend/src/main/java/com/allog/dallog/member/exception/NoSuchMemberException.java +++ b/backend/src/main/java/com/allog/dallog/member/exception/NoSuchMemberException.java @@ -2,11 +2,11 @@ public class NoSuchMemberException extends RuntimeException { - public NoSuchMemberException() { - super("존재하지 않는 회원입니다."); - } - public NoSuchMemberException(final String message) { super(message); } + + public NoSuchMemberException() { + this("존재하지 않는 회원입니다."); + } } diff --git a/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidScheduleException.java b/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidScheduleException.java index 590c0a43..70c24d59 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidScheduleException.java +++ b/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidScheduleException.java @@ -2,11 +2,11 @@ public class InvalidScheduleException extends RuntimeException { - public InvalidScheduleException() { - super("잘못된 일정입니다."); - } - public InvalidScheduleException(final String message) { super(message); } + + public InvalidScheduleException() { + this("잘못된 일정입니다."); + } } From f80807ec444617d0d3e3843a6ecca2c8e7b17c1e Mon Sep 17 00:00:00 2001 From: hyeonic Date: Fri, 15 Jul 2022 15:20:58 +0900 Subject: [PATCH 0161/1011] =?UTF-8?q?feat:=20Member=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20response=20dto=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/member/dto/MemberResponse.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/member/dto/MemberResponse.java diff --git a/backend/src/main/java/com/allog/dallog/member/dto/MemberResponse.java b/backend/src/main/java/com/allog/dallog/member/dto/MemberResponse.java new file mode 100644 index 00000000..f2d55f97 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/member/dto/MemberResponse.java @@ -0,0 +1,46 @@ +package com.allog.dallog.member.dto; + +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.domain.SocialType; + +public class MemberResponse { + + private Long id; + private String email; + private String displayName; + private String profileImageUrl; + private SocialType socialType; + + private MemberResponse() { + } + + public MemberResponse(final Long id, final String email, final String displayName, final String profileImageUrl, + final SocialType socialType) { + this.id = id; + this.email = email; + this.displayName = displayName; + this.profileImageUrl = profileImageUrl; + this.socialType = socialType; + } + + public MemberResponse(final Member member) { + this(member.getId(), member.getEmail(), member.getDisplayName(), member.getProfileImageUrl(), + member.getSocialType()); + } + + public String getEmail() { + return email; + } + + public String getDisplayName() { + return displayName; + } + + public String getProfileImageUrl() { + return profileImageUrl; + } + + public SocialType getSocialType() { + return socialType; + } +} From c47ab06b80b4cf9e4ccdde221a3202d40987c91c Mon Sep 17 00:00:00 2001 From: hyeonic Date: Fri, 15 Jul 2022 15:22:22 +0900 Subject: [PATCH 0162/1011] =?UTF-8?q?feat:=20=EC=9D=B8=EC=A6=9D=EB=90=9C?= =?UTF-8?q?=20=ED=9A=8C=EC=9B=90=EC=9D=98=20=EC=A0=95=EB=B3=B4=EB=A5=BC=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A4=EA=B8=B0=20=EC=9C=84=ED=95=9C=20ArgumentReso?= =?UTF-8?q?lver=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/auth/dto/LoginMember.java | 17 +++++++++ .../auth/support/AuthenticationPrincipal.java | 11 ++++++ ...thenticationPrincipalArgumentResolver.java | 37 +++++++++++++++++++ .../auth/support/AuthorizationExtractor.java | 28 ++++++++++++++ .../allog/dallog/global/config/WebConfig.java | 14 +++++++ 5 files changed, 107 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/auth/dto/LoginMember.java create mode 100644 backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipal.java create mode 100644 backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java create mode 100644 backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java diff --git a/backend/src/main/java/com/allog/dallog/auth/dto/LoginMember.java b/backend/src/main/java/com/allog/dallog/auth/dto/LoginMember.java new file mode 100644 index 00000000..93eb6227 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/dto/LoginMember.java @@ -0,0 +1,17 @@ +package com.allog.dallog.auth.dto; + +public class LoginMember { + + private Long id; + + private LoginMember() { + } + + public LoginMember(final Long id) { + this.id = id; + } + + public Long getId() { + return id; + } +} diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipal.java b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipal.java new file mode 100644 index 00000000..afa08f2c --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipal.java @@ -0,0 +1,11 @@ +package com.allog.dallog.auth.support; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +public @interface AuthenticationPrincipal { +} diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java new file mode 100644 index 00000000..d4d6a19b --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java @@ -0,0 +1,37 @@ +package com.allog.dallog.auth.support; + +import com.allog.dallog.auth.dto.LoginMember; +import javax.servlet.http.HttpServletRequest; +import org.springframework.core.MethodParameter; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.support.WebDataBinderFactory; +import org.springframework.web.context.request.NativeWebRequest; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.method.support.ModelAndViewContainer; + +@Component +public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver { + + private final JwtTokenProvider jwtTokenProvider; + + public AuthenticationPrincipalArgumentResolver(final JwtTokenProvider jwtTokenProvider) { + this.jwtTokenProvider = jwtTokenProvider; + } + + @Override + public boolean supportsParameter(MethodParameter parameter) { + return parameter.hasParameterAnnotation(AuthenticationPrincipal.class); + } + + @Override + public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, + NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { + HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); + String accessToken = AuthorizationExtractor.extract(request); + jwtTokenProvider.validateToken(accessToken); + + Long id = Long.parseLong(jwtTokenProvider.getPayload(accessToken)); + + return new LoginMember(id); + } +} diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java b/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java new file mode 100644 index 00000000..6bc748e7 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java @@ -0,0 +1,28 @@ +package com.allog.dallog.auth.support; + +import com.allog.dallog.auth.exception.EmptyAuthorizationHeaderException; +import com.allog.dallog.auth.exception.InvalidTokenFormatException; +import java.util.Objects; +import javax.servlet.http.HttpServletRequest; +import org.springframework.http.HttpHeaders; + +public class AuthorizationExtractor { + + private static final String BEARER_TYPE = "Bearer "; + + public static String extract(HttpServletRequest request) { + String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION); + if (Objects.isNull(authorizationHeader)) { + throw new EmptyAuthorizationHeaderException(); + } + + validateAuthorizationFormat(authorizationHeader); + return authorizationHeader.substring(BEARER_TYPE.length()).trim(); + } + + private static void validateAuthorizationFormat(String authorizationHeader) { + if (!authorizationHeader.toLowerCase().startsWith(BEARER_TYPE.toLowerCase())) { + throw new InvalidTokenFormatException(); + } + } +} diff --git a/backend/src/main/java/com/allog/dallog/global/config/WebConfig.java b/backend/src/main/java/com/allog/dallog/global/config/WebConfig.java index 23958633..3a4dba3b 100644 --- a/backend/src/main/java/com/allog/dallog/global/config/WebConfig.java +++ b/backend/src/main/java/com/allog/dallog/global/config/WebConfig.java @@ -1,12 +1,26 @@ package com.allog.dallog.global.config; +import com.allog.dallog.auth.support.AuthenticationPrincipalArgumentResolver; +import java.util.List; import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { + private final AuthenticationPrincipalArgumentResolver authenticationPrincipalArgumentResolver; + + public WebConfig(final AuthenticationPrincipalArgumentResolver authenticationPrincipalArgumentResolver) { + this.authenticationPrincipalArgumentResolver = authenticationPrincipalArgumentResolver; + } + + @Override + public void addArgumentResolvers(List argumentResolvers) { + argumentResolvers.add(authenticationPrincipalArgumentResolver); + } + @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") From 321718f27d725749e103dff9d88ff055b33dcb52 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Fri, 15 Jul 2022 15:22:44 +0900 Subject: [PATCH 0163/1011] =?UTF-8?q?feat:=20=EC=9D=B8=EC=A6=9D=EB=90=9C?= =?UTF-8?q?=20=ED=9A=8C=EC=9B=90=EC=9D=98=20=EC=A0=95=EB=B3=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MemberController.java | 28 +++++++++++++++++++ .../dallog/member/service/MemberService.java | 8 ++++++ 2 files changed, 36 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/member/controller/MemberController.java diff --git a/backend/src/main/java/com/allog/dallog/member/controller/MemberController.java b/backend/src/main/java/com/allog/dallog/member/controller/MemberController.java new file mode 100644 index 00000000..9ae66872 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/member/controller/MemberController.java @@ -0,0 +1,28 @@ +package com.allog.dallog.member.controller; + +import com.allog.dallog.auth.dto.LoginMember; +import com.allog.dallog.auth.support.AuthenticationPrincipal; +import com.allog.dallog.global.dto.CommonResponse; +import com.allog.dallog.member.dto.MemberResponse; +import com.allog.dallog.member.service.MemberService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequestMapping("/api/members") +@RestController +public class MemberController { + + private final MemberService memberService; + + public MemberController(final MemberService memberService) { + this.memberService = memberService; + } + + @GetMapping("/me") + public ResponseEntity> findMe(@AuthenticationPrincipal LoginMember loginMember) { + MemberResponse response = memberService.findById(loginMember.getId()); + return ResponseEntity.ok(new CommonResponse<>(response)); + } +} diff --git a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java index 47d148dc..441d5194 100644 --- a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java +++ b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java @@ -2,6 +2,7 @@ import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; +import com.allog.dallog.member.dto.MemberResponse; import com.allog.dallog.member.exception.NoSuchMemberException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,6 +22,13 @@ public Member save(final Member member) { return memberRepository.save(member); } + public MemberResponse findById(final Long id) { + Member member = memberRepository.findById(id) + .orElseThrow(NoSuchMemberException::new); + + return new MemberResponse(member); + } + public Member findByEmail(final String email) { return memberRepository.findByEmail(email) .orElseThrow(NoSuchMemberException::new); From 79e1e6da0e04e5f5d2715252eeb548754241539e Mon Sep 17 00:00:00 2001 From: hyeonic Date: Mon, 18 Jul 2022 13:22:12 +0900 Subject: [PATCH 0164/1011] =?UTF-8?q?feat:=20=EB=88=84=EB=9D=BD=EB=90=9C?= =?UTF-8?q?=20final=20=ED=82=A4=EC=9B=8C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../support/AuthenticationPrincipalArgumentResolver.java | 6 +++--- .../allog/dallog/auth/support/AuthorizationExtractor.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java index d4d6a19b..c974e498 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java @@ -19,13 +19,13 @@ public AuthenticationPrincipalArgumentResolver(final JwtTokenProvider jwtTokenPr } @Override - public boolean supportsParameter(MethodParameter parameter) { + public boolean supportsParameter(final MethodParameter parameter) { return parameter.hasParameterAnnotation(AuthenticationPrincipal.class); } @Override - public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, - NativeWebRequest webRequest, WebDataBinderFactory binderFactory) { + public Object resolveArgument(final MethodParameter parameter, final ModelAndViewContainer mavContainer, + final NativeWebRequest webRequest, final WebDataBinderFactory binderFactory) { HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); String accessToken = AuthorizationExtractor.extract(request); jwtTokenProvider.validateToken(accessToken); diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java b/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java index 6bc748e7..ad3b0e56 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java @@ -10,7 +10,7 @@ public class AuthorizationExtractor { private static final String BEARER_TYPE = "Bearer "; - public static String extract(HttpServletRequest request) { + public static String extract(final HttpServletRequest request) { String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION); if (Objects.isNull(authorizationHeader)) { throw new EmptyAuthorizationHeaderException(); @@ -20,7 +20,7 @@ public static String extract(HttpServletRequest request) { return authorizationHeader.substring(BEARER_TYPE.length()).trim(); } - private static void validateAuthorizationFormat(String authorizationHeader) { + private static void validateAuthorizationFormat(final String authorizationHeader) { if (!authorizationHeader.toLowerCase().startsWith(BEARER_TYPE.toLowerCase())) { throw new InvalidTokenFormatException(); } From c064b8bc4a1533baad38dd706a4053a7be254282 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Mon, 18 Jul 2022 16:54:38 +0900 Subject: [PATCH 0165/1011] =?UTF-8?q?test:=20=ED=9A=8C=EC=9B=90=EC=9D=98?= =?UTF-8?q?=20=EB=B3=B8=EC=9D=B8=20=EC=A0=95=EB=B3=B4=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EC=84=B1=EA=B3=B5=20=EC=9D=B8=EC=88=98=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/auth/dto/TokenResponse.java | 5 +- .../dallog/member/dto/MemberResponse.java | 4 + .../acceptance/MemberAcceptanceTest.java | 75 +++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java diff --git a/backend/src/main/java/com/allog/dallog/auth/dto/TokenResponse.java b/backend/src/main/java/com/allog/dallog/auth/dto/TokenResponse.java index 3da438d3..c3e2417a 100644 --- a/backend/src/main/java/com/allog/dallog/auth/dto/TokenResponse.java +++ b/backend/src/main/java/com/allog/dallog/auth/dto/TokenResponse.java @@ -2,7 +2,10 @@ public class TokenResponse { - private final String accessToken; + private String accessToken; + + private TokenResponse() { + } public TokenResponse(final String accessToken) { this.accessToken = accessToken; diff --git a/backend/src/main/java/com/allog/dallog/member/dto/MemberResponse.java b/backend/src/main/java/com/allog/dallog/member/dto/MemberResponse.java index f2d55f97..cef1837c 100644 --- a/backend/src/main/java/com/allog/dallog/member/dto/MemberResponse.java +++ b/backend/src/main/java/com/allog/dallog/member/dto/MemberResponse.java @@ -28,6 +28,10 @@ public MemberResponse(final Member member) { member.getSocialType()); } + public Long getId() { + return id; + } + public String getEmail() { return email; } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java new file mode 100644 index 00000000..0766c3eb --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -0,0 +1,75 @@ +package com.allog.dallog.acceptance; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import com.allog.dallog.auth.dto.TokenRequest; +import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.config.TestConfig; +import com.allog.dallog.global.dto.CommonResponse; +import com.allog.dallog.member.dto.MemberResponse; +import io.restassured.RestAssured; +import io.restassured.common.mapper.TypeRef; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +@DisplayName("회원 관련 기능") +@Import(TestConfig.class) +public class MemberAcceptanceTest extends AcceptanceTest { + + private static final TypeRef> COMMON_OF_TOKEN_TYPE_REF = new TypeRef<>() { + }; + + private static final TypeRef> COMMON_OF_MEMBER_TYPE_REF = new TypeRef<>() { + }; + + @DisplayName("등록된 회원이 자신의 정보를 조회하면 상태코드 200을 반환한다.") + @Test + void 등록된_회원이_자신의_정보를_조회하면_상태코드_200_을_반환한다() { + // given + String oauthProvider = "google"; + String code = "sddsfsg4wedfabladsgklvdskfngdakfjgnkd"; + + CommonResponse commonResponse = 자체_토큰을_생성한다(oauthProvider, code); + TokenResponse tokenResponse = commonResponse.getData(); + + // when + ExtractableResponse response = 자신의_정보를_조회한다(tokenResponse); + CommonResponse commonMemberResponse = response.as(COMMON_OF_MEMBER_TYPE_REF); + MemberResponse memberResponse = commonMemberResponse.getData(); + + // then + assertAll(() -> { + 상태코드_200이_반환된다(response); + assertThat(memberResponse.getEmail()).isEqualTo("dev.hyeonic@gmail.com"); + assertThat(memberResponse.getDisplayName()).isEqualTo("Fake Name"); + assertThat(memberResponse.getProfileImageUrl()).isEqualTo("Fake Profile Image Url"); + }); + } + + private CommonResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { + return RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(new TokenRequest(code)) + .when().post("/api/auth/{oauthProvider}/token", oauthProvider) + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract() + .as(COMMON_OF_TOKEN_TYPE_REF); + } + + private ExtractableResponse 자신의_정보를_조회한다(final TokenResponse tokenResponse) { + return RestAssured.given().log().all() + .auth().oauth2(tokenResponse.getAccessToken()) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when().get("/api/members/me") + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract(); + } +} From dd4effaacfcd9251a61195e7d519151bf5f04dd2 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Mon, 18 Jul 2022 17:13:59 +0900 Subject: [PATCH 0166/1011] =?UTF-8?q?test:=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EC=9D=B8?= =?UTF-8?q?=EC=88=98=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/acceptance/AcceptanceTest.java | 6 +++ .../dallog/acceptance/AuthAcceptanceTest.java | 49 +++++++++++++++++++ .../acceptance/MemberAcceptanceTest.java | 3 -- 3 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java index f5876d0f..c1be3893 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java @@ -2,7 +2,10 @@ import static org.assertj.core.api.Assertions.assertThat; +import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.global.dto.CommonResponse; import io.restassured.RestAssured; +import io.restassured.common.mapper.TypeRef; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.junit.jupiter.api.BeforeEach; @@ -15,6 +18,9 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class AcceptanceTest { + protected static final TypeRef> COMMON_OF_TOKEN_TYPE_REF = new TypeRef<>() { + }; + @LocalServerPort int port; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java new file mode 100644 index 00000000..f28cdcc6 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java @@ -0,0 +1,49 @@ +package com.allog.dallog.acceptance; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +import com.allog.dallog.auth.dto.TokenRequest; +import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.config.TestConfig; +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +@DisplayName("인증 관련 기능") +@Import(TestConfig.class) +public class AuthAcceptanceTest extends AcceptanceTest { + + @DisplayName("최초 사용자거나 기존에 존재하는 회원인 경우 200을 발급한다.") + @Test + void 최초_사용자거나_기존에_존재하는_회원인_경우_200을_발급한다() { + // given + String oauthProvider = "google"; + String code = "sddsfsg4wedfabladsgklvdskfngdakfjgnkd"; + + // when + ExtractableResponse response = 자체_토큰을_생성한다(oauthProvider, code); + TokenResponse tokenResponse = response.as(COMMON_OF_TOKEN_TYPE_REF).getData(); + + // then + assertAll(() -> { + 상태코드_200이_반환된다(response); + assertThat(tokenResponse.getAccessToken()).isNotEmpty(); + }); + } + + private ExtractableResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { + return RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(new TokenRequest(code)) + .when().post("/api/auth/{oauthProvider}/token", oauthProvider) + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract(); + } +} diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java index 0766c3eb..4ffb1570 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -22,9 +22,6 @@ @Import(TestConfig.class) public class MemberAcceptanceTest extends AcceptanceTest { - private static final TypeRef> COMMON_OF_TOKEN_TYPE_REF = new TypeRef<>() { - }; - private static final TypeRef> COMMON_OF_MEMBER_TYPE_REF = new TypeRef<>() { }; From fe3c9b356c23bd137a23ece7fa91c5e8bc64faea Mon Sep 17 00:00:00 2001 From: hyeonic Date: Mon, 18 Jul 2022 21:06:34 +0900 Subject: [PATCH 0167/1011] =?UTF-8?q?fix:=20=EB=B6=88=ED=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=BB=A4=EC=8A=A4=ED=85=80=20=EC=98=88=EC=99=B8=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/exception/InvalidTokenFormatException.java | 12 ------------ .../dallog/auth/support/AuthorizationExtractor.java | 4 ++-- 2 files changed, 2 insertions(+), 14 deletions(-) delete mode 100644 backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenFormatException.java diff --git a/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenFormatException.java b/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenFormatException.java deleted file mode 100644 index e97e6c51..00000000 --- a/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenFormatException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.allog.dallog.auth.exception; - -public class InvalidTokenFormatException extends RuntimeException { - - public InvalidTokenFormatException(final String message) { - super(message); - } - - public InvalidTokenFormatException() { - this("token 형식이 잘못 되었습니다. (형식: Bearer aaaaaaaa.bbbbbbbb.cccccccc)"); - } -} diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java b/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java index ad3b0e56..b262812a 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java @@ -1,7 +1,7 @@ package com.allog.dallog.auth.support; import com.allog.dallog.auth.exception.EmptyAuthorizationHeaderException; -import com.allog.dallog.auth.exception.InvalidTokenFormatException; +import com.allog.dallog.auth.exception.InvalidTokenException; import java.util.Objects; import javax.servlet.http.HttpServletRequest; import org.springframework.http.HttpHeaders; @@ -22,7 +22,7 @@ public static String extract(final HttpServletRequest request) { private static void validateAuthorizationFormat(final String authorizationHeader) { if (!authorizationHeader.toLowerCase().startsWith(BEARER_TYPE.toLowerCase())) { - throw new InvalidTokenFormatException(); + throw new InvalidTokenException("token 형식이 잘못 되었습니다."); } } } From a5ca8829a8b26abe8e93a2fe4acc2d916562fd4f Mon Sep 17 00:00:00 2001 From: hyeonic Date: Mon, 18 Jul 2022 21:23:07 +0900 Subject: [PATCH 0168/1011] =?UTF-8?q?test:=20=EC=9D=B8=EC=A6=9D=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20fixture=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/acceptance/MemberAcceptanceTest.java | 7 ++++--- .../allog/dallog/auth/service/AuthServiceTest.java | 5 +++-- .../allog/dallog/fixture/OAuthMemberFixtures.java | 14 ++++++++++++++ .../oauth/client/StubOAuthClient.java | 4 +++- 4 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 backend/src/test/java/com/allog/dallog/fixture/OAuthMemberFixtures.java diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java index 4ffb1570..6f36f556 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -6,6 +6,7 @@ import com.allog.dallog.auth.dto.TokenRequest; import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.config.TestConfig; +import com.allog.dallog.fixture.OAuthMemberFixtures; import com.allog.dallog.global.dto.CommonResponse; import com.allog.dallog.member.dto.MemberResponse; import io.restassured.RestAssured; @@ -43,9 +44,9 @@ public class MemberAcceptanceTest extends AcceptanceTest { // then assertAll(() -> { 상태코드_200이_반환된다(response); - assertThat(memberResponse.getEmail()).isEqualTo("dev.hyeonic@gmail.com"); - assertThat(memberResponse.getDisplayName()).isEqualTo("Fake Name"); - assertThat(memberResponse.getProfileImageUrl()).isEqualTo("Fake Profile Image Url"); + assertThat(memberResponse.getEmail()).isEqualTo(OAuthMemberFixtures.EMAIL); + assertThat(memberResponse.getDisplayName()).isEqualTo(OAuthMemberFixtures.DISPLAY_NAME); + assertThat(memberResponse.getProfileImageUrl()).isEqualTo(OAuthMemberFixtures.PROFILE_IMAGE_URI); }); } diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index 3229666e..510c08ca 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -4,6 +4,7 @@ import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.config.TestConfig; +import com.allog.dallog.fixture.OAuthMemberFixtures; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; import java.util.List; @@ -48,11 +49,11 @@ class AuthServiceTest { @Test void Authorization_Code를_받으면_회원이_데이터베이스에_저장된다() { // given - String code = "authorization code"; + String code = OAuthMemberFixtures.CODE; authService.generateTokenWithCode(code); // when - boolean actual = memberRepository.existsByEmail("dev.hyeonic@gmail.com"); + boolean actual = memberRepository.existsByEmail(OAuthMemberFixtures.EMAIL); // SutbOAuthClient가 반환하는 OAuthMember의 이메일 // then diff --git a/backend/src/test/java/com/allog/dallog/fixture/OAuthMemberFixtures.java b/backend/src/test/java/com/allog/dallog/fixture/OAuthMemberFixtures.java new file mode 100644 index 00000000..cde3322d --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/fixture/OAuthMemberFixtures.java @@ -0,0 +1,14 @@ +package com.allog.dallog.fixture; + +import com.allog.dallog.auth.dto.OAuthMember; + +public class OAuthMemberFixtures { + + public static final String CODE = "authorization code"; + + public static final String EMAIL = "example@email.com"; + public static final String DISPLAY_NAME = "example"; + public static final String PROFILE_IMAGE_URI = "/image.png"; + + public static final OAuthMember OAUTH_MEMBER = new OAuthMember(EMAIL, DISPLAY_NAME, PROFILE_IMAGE_URI); +} diff --git a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java index 616dbb44..c841bf3b 100644 --- a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java +++ b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java @@ -1,5 +1,7 @@ package com.allog.dallog.infrastructure.oauth.client; +import static com.allog.dallog.fixture.OAuthMemberFixtures.OAUTH_MEMBER; + import com.allog.dallog.auth.dto.OAuthMember; import com.allog.dallog.auth.support.OAuthClient; @@ -7,6 +9,6 @@ public class StubOAuthClient implements OAuthClient { @Override public OAuthMember getOAuthMember(final String code) { - return new OAuthMember("dev.hyeonic@gmail.com", "Fake Name", "Fake Profile Image Url"); + return OAUTH_MEMBER; } } From e423f9959e332cb1990e83fd77ee406eb097c0d6 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Mon, 18 Jul 2022 21:23:44 +0900 Subject: [PATCH 0169/1011] =?UTF-8?q?test:=20WebMvcTest=EC=97=90=20?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EC=8B=A4=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?JwtTokenProvier=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/schedule/controller/ScheduleControllerTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java b/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java index 66edb796..f1585866 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java @@ -12,6 +12,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import com.allog.dallog.auth.support.JwtTokenProvider; import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; import com.allog.dallog.schedule.dto.response.ScheduleResponse; import com.allog.dallog.schedule.service.ScheduleService; @@ -26,11 +27,13 @@ import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; @AutoConfigureRestDocs @WebMvcTest(ScheduleController.class) +@Import(JwtTokenProvider.class) class ScheduleControllerTest { @Autowired From 27b7f0053af4a8c591610a7eacacd9de1123a8ad Mon Sep 17 00:00:00 2001 From: hyeonic Date: Tue, 19 Jul 2022 00:40:23 +0900 Subject: [PATCH 0170/1011] =?UTF-8?q?test:=20Member=20=EB=B0=8F=20Category?= =?UTF-8?q?=20fixture=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/fixture/CategoryFixtures.java | 10 ++++++++++ .../com/allog/dallog/fixture/MemberFixtures.java | 13 +++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 backend/src/test/java/com/allog/dallog/fixture/CategoryFixtures.java create mode 100644 backend/src/test/java/com/allog/dallog/fixture/MemberFixtures.java diff --git a/backend/src/test/java/com/allog/dallog/fixture/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/fixture/CategoryFixtures.java new file mode 100644 index 00000000..0a7481a1 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/fixture/CategoryFixtures.java @@ -0,0 +1,10 @@ +package com.allog.dallog.fixture; + +import com.allog.dallog.category.domain.Category; + +public class CategoryFixtures { + + public static final String CATEGORY_NAME = "달록"; + + public static final Category CATEGORY = new Category(CATEGORY_NAME); +} diff --git a/backend/src/test/java/com/allog/dallog/fixture/MemberFixtures.java b/backend/src/test/java/com/allog/dallog/fixture/MemberFixtures.java new file mode 100644 index 00000000..59650b99 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/fixture/MemberFixtures.java @@ -0,0 +1,13 @@ +package com.allog.dallog.fixture; + +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.domain.SocialType; + +public class MemberFixtures { + + public static final String EMAIL = "example@email.com"; + public static final String PROFILE_IMAGE_URI = "/image.png"; + public static final String DISPLAY_NAME = "example"; + + public static final Member MEMBER = new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE); +} From f60b58af7f43617f1e2e0bda4a7d41e29d65f314 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Tue, 19 Jul 2022 00:40:41 +0900 Subject: [PATCH 0171/1011] =?UTF-8?q?fix:=20Exception=20=ED=98=95=EC=8B=9D?= =?UTF-8?q?=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/member/exception/InvalidMemberException.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java b/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java index 95c59d0a..fcce6fed 100644 --- a/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java +++ b/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java @@ -7,6 +7,6 @@ public InvalidMemberException(final String message) { } public InvalidMemberException() { - super("잘못된 회원의 정보입니다."); + this("잘못된 회원의 정보입니다."); } } From 1519657e0651d6d018fd5db87900b98f6e7788aa Mon Sep 17 00:00:00 2001 From: hyeonic Date: Tue, 19 Jul 2022 00:41:18 +0900 Subject: [PATCH 0172/1011] =?UTF-8?q?feat:=20=EA=B5=AC=EB=8F=85=EC=9D=84?= =?UTF-8?q?=20=ED=91=9C=ED=98=84=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?Subscription=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subscription/domain/Subscription.java | 74 +++++++++++++++++++ .../InvalidSubscriptionException.java | 12 +++ .../subscription/domain/SubscriptionTest.java | 42 +++++++++++ 3 files changed, 128 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/subscription/domain/Subscription.java create mode 100644 backend/src/main/java/com/allog/dallog/subscription/exception/InvalidSubscriptionException.java create mode 100644 backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java diff --git a/backend/src/main/java/com/allog/dallog/subscription/domain/Subscription.java b/backend/src/main/java/com/allog/dallog/subscription/domain/Subscription.java new file mode 100644 index 00000000..737cb69a --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/subscription/domain/Subscription.java @@ -0,0 +1,74 @@ +package com.allog.dallog.subscription.domain; + +import com.allog.dallog.category.domain.Category; +import com.allog.dallog.global.domain.BaseEntity; +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.subscription.exception.InvalidSubscriptionException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +@Table(name = "subscriptions") +@Entity +public class Subscription extends BaseEntity { + + private static final Pattern COLOR_PATTERN = Pattern.compile("^#[a-fA-F\\d]{6}$"); + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "members_id", nullable = false) + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "categories_id", nullable = false) + private Category category; + + @Column(name = "color", nullable = false) + private String color; + + protected Subscription() { + } + + public Subscription(final Member member, final Category category, final String color) { + validateColor(color); + + this.member = member; + this.category = category; + this.color = color; + } + + private void validateColor(final String color) { + Matcher matcher = COLOR_PATTERN.matcher(color); + if (!matcher.matches()) { + throw new InvalidSubscriptionException("(" + color + ")는 올바른 색 정보 형식이 아닙니다."); + } + } + + public Long getId() { + return id; + } + + public Member getMember() { + return member; + } + + public Category getCategory() { + return category; + } + + public String getColor() { + return color; + } +} diff --git a/backend/src/main/java/com/allog/dallog/subscription/exception/InvalidSubscriptionException.java b/backend/src/main/java/com/allog/dallog/subscription/exception/InvalidSubscriptionException.java new file mode 100644 index 00000000..d37817cf --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/subscription/exception/InvalidSubscriptionException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.subscription.exception; + +public class InvalidSubscriptionException extends RuntimeException { + + public InvalidSubscriptionException(final String message) { + super(message); + } + + public InvalidSubscriptionException() { + this("유효하지 않은 구독 정보입니다."); + } +} diff --git a/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java b/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java new file mode 100644 index 00000000..631ed3df --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java @@ -0,0 +1,42 @@ +package com.allog.dallog.subscription.domain; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +import com.allog.dallog.category.domain.Category; +import com.allog.dallog.fixture.CategoryFixtures; +import com.allog.dallog.fixture.MemberFixtures; +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.subscription.exception.InvalidSubscriptionException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +class SubscriptionTest { + + @DisplayName("구독을 생성한다.") + @Test + void 구독을_생성한다() { + // given + Member member = MemberFixtures.MEMBER; + Category category = CategoryFixtures.CATEGORY; + String color = "#c9ad2e"; + + // when & then + assertDoesNotThrow(() -> new Subscription(member, category, color)); + } + + @DisplayName("색 정보 형식이 잘못된 경우 예외를 던진다.") + @ParameterizedTest + @ValueSource(strings = {"#111", "#1111", "#11111", "123456", "#**1234", "##12345", "334172#"}) + void 색_정보_형식이_잘못된_경우_예외를_던진다(final String color) { + // given + Member member = MemberFixtures.MEMBER; + Category category = CategoryFixtures.CATEGORY; + + // when & then + assertThatThrownBy(() -> new Subscription(member, category, color)) + .isInstanceOf(InvalidSubscriptionException.class); + } +} From d6a31c175344a4476fb4e37954afdc4c501404ec Mon Sep 17 00:00:00 2001 From: hyeonic Date: Tue, 19 Jul 2022 13:28:44 +0900 Subject: [PATCH 0173/1011] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=20=EA=B3=B5=ED=86=B5=20response=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/auth/controller/AuthController.java | 11 +++++------ .../allog/dallog/global/dto/CommonResponse.java | 17 ----------------- .../member/controller/MemberController.java | 5 ++--- .../allog/dallog/acceptance/AcceptanceTest.java | 6 ------ .../dallog/acceptance/AuthAcceptanceTest.java | 2 +- .../dallog/acceptance/MemberAcceptanceTest.java | 15 ++++----------- 6 files changed, 12 insertions(+), 44 deletions(-) delete mode 100644 backend/src/main/java/com/allog/dallog/global/dto/CommonResponse.java diff --git a/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java b/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java index f7778b93..42516873 100644 --- a/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java +++ b/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java @@ -3,7 +3,6 @@ import com.allog.dallog.auth.dto.TokenRequest; import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.auth.service.AuthService; -import com.allog.dallog.global.dto.CommonResponse; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -23,14 +22,14 @@ public AuthController(final AuthService authService) { } @GetMapping("/{oauthProvider}/link") - public ResponseEntity> generateLink(@PathVariable final String oauthProvider) { - return ResponseEntity.ok(new CommonResponse<>(authService.generateGoogleLink())); + public ResponseEntity generateLink(@PathVariable final String oauthProvider) { + return ResponseEntity.ok(authService.generateGoogleLink()); } @PostMapping("/{oauthProvider}/token") - public ResponseEntity> generateToken(@PathVariable final String oauthProvider, - @RequestBody final TokenRequest tokenRequest) { + public ResponseEntity generateToken(@PathVariable final String oauthProvider, + @RequestBody final TokenRequest tokenRequest) { TokenResponse tokenResponse = authService.generateTokenWithCode(tokenRequest.getCode()); - return ResponseEntity.ok(new CommonResponse<>(tokenResponse)); + return ResponseEntity.ok(tokenResponse); } } diff --git a/backend/src/main/java/com/allog/dallog/global/dto/CommonResponse.java b/backend/src/main/java/com/allog/dallog/global/dto/CommonResponse.java deleted file mode 100644 index 7378087c..00000000 --- a/backend/src/main/java/com/allog/dallog/global/dto/CommonResponse.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.allog.dallog.global.dto; - -public class CommonResponse { - - private T data; - - private CommonResponse() { - } - - public CommonResponse(T data) { - this.data = data; - } - - public T getData() { - return data; - } -} diff --git a/backend/src/main/java/com/allog/dallog/member/controller/MemberController.java b/backend/src/main/java/com/allog/dallog/member/controller/MemberController.java index 9ae66872..13b6455f 100644 --- a/backend/src/main/java/com/allog/dallog/member/controller/MemberController.java +++ b/backend/src/main/java/com/allog/dallog/member/controller/MemberController.java @@ -2,7 +2,6 @@ import com.allog.dallog.auth.dto.LoginMember; import com.allog.dallog.auth.support.AuthenticationPrincipal; -import com.allog.dallog.global.dto.CommonResponse; import com.allog.dallog.member.dto.MemberResponse; import com.allog.dallog.member.service.MemberService; import org.springframework.http.ResponseEntity; @@ -21,8 +20,8 @@ public MemberController(final MemberService memberService) { } @GetMapping("/me") - public ResponseEntity> findMe(@AuthenticationPrincipal LoginMember loginMember) { + public ResponseEntity findMe(@AuthenticationPrincipal LoginMember loginMember) { MemberResponse response = memberService.findById(loginMember.getId()); - return ResponseEntity.ok(new CommonResponse<>(response)); + return ResponseEntity.ok(response); } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java index c1be3893..f5876d0f 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java @@ -2,10 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import com.allog.dallog.auth.dto.TokenResponse; -import com.allog.dallog.global.dto.CommonResponse; import io.restassured.RestAssured; -import io.restassured.common.mapper.TypeRef; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.junit.jupiter.api.BeforeEach; @@ -18,9 +15,6 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) class AcceptanceTest { - protected static final TypeRef> COMMON_OF_TOKEN_TYPE_REF = new TypeRef<>() { - }; - @LocalServerPort int port; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java index f28cdcc6..8f9b944d 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java @@ -28,7 +28,7 @@ public class AuthAcceptanceTest extends AcceptanceTest { // when ExtractableResponse response = 자체_토큰을_생성한다(oauthProvider, code); - TokenResponse tokenResponse = response.as(COMMON_OF_TOKEN_TYPE_REF).getData(); + TokenResponse tokenResponse = response.as(TokenResponse.class); // then assertAll(() -> { diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java index 6f36f556..931f2cd7 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -7,10 +7,8 @@ import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.config.TestConfig; import com.allog.dallog.fixture.OAuthMemberFixtures; -import com.allog.dallog.global.dto.CommonResponse; import com.allog.dallog.member.dto.MemberResponse; import io.restassured.RestAssured; -import io.restassured.common.mapper.TypeRef; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.junit.jupiter.api.DisplayName; @@ -23,9 +21,6 @@ @Import(TestConfig.class) public class MemberAcceptanceTest extends AcceptanceTest { - private static final TypeRef> COMMON_OF_MEMBER_TYPE_REF = new TypeRef<>() { - }; - @DisplayName("등록된 회원이 자신의 정보를 조회하면 상태코드 200을 반환한다.") @Test void 등록된_회원이_자신의_정보를_조회하면_상태코드_200_을_반환한다() { @@ -33,13 +28,11 @@ public class MemberAcceptanceTest extends AcceptanceTest { String oauthProvider = "google"; String code = "sddsfsg4wedfabladsgklvdskfngdakfjgnkd"; - CommonResponse commonResponse = 자체_토큰을_생성한다(oauthProvider, code); - TokenResponse tokenResponse = commonResponse.getData(); + TokenResponse tokenResponse = 자체_토큰을_생성한다(oauthProvider, code); // when ExtractableResponse response = 자신의_정보를_조회한다(tokenResponse); - CommonResponse commonMemberResponse = response.as(COMMON_OF_MEMBER_TYPE_REF); - MemberResponse memberResponse = commonMemberResponse.getData(); + MemberResponse memberResponse = response.as(MemberResponse.class); // then assertAll(() -> { @@ -50,7 +43,7 @@ public class MemberAcceptanceTest extends AcceptanceTest { }); } - private CommonResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { + private TokenResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { return RestAssured.given().log().all() .contentType(MediaType.APPLICATION_JSON_VALUE) .body(new TokenRequest(code)) @@ -58,7 +51,7 @@ public class MemberAcceptanceTest extends AcceptanceTest { .then().log().all() .statusCode(HttpStatus.OK.value()) .extract() - .as(COMMON_OF_TOKEN_TYPE_REF); + .as(TokenResponse.class); } private ExtractableResponse 자신의_정보를_조회한다(final TokenResponse tokenResponse) { From 62beeccffd20769d2496b3349690880e3c1325e4 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 18 Jul 2022 20:52:49 +0900 Subject: [PATCH 0174/1011] =?UTF-8?q?feat:=20=EB=82=A0=EC=A7=9C=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EC=9C=A0?= =?UTF-8?q?=ED=8B=B8=20=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/utils/index.ts | 47 ++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts index bed9120c..05549428 100644 --- a/frontend/src/utils/index.ts +++ b/frontend/src/utils/index.ts @@ -27,4 +27,49 @@ const getDateTime = () => { return new Date(+new Date() + 3240 * 10000).toISOString().replace(/\..*/, '').slice(0, -3); }; -export { createPostBody, getDate, getDateTime }; +const getBeforeDate = (targetDay: Date, offset: number) => + new Date(targetDay.setDate(targetDay.getDate() - offset)); + +const getNextDate = (targetDay: Date, offset: number) => + new Date(targetDay.setDate(targetDay.getDate() + offset)); + +const getCalendarMonth = (month: number, year: number) => { + const firstDate = new Date(year, month - 1, 1); + + const calendarInfo: Date[] = []; + + while (firstDate.getMonth() === month - 1) { + calendarInfo.push(new Date(firstDate)); + firstDate.setDate(firstDate.getDate() + 1); + } + + const firstDay = calendarInfo[0].getDay(); + const lastDay = calendarInfo[calendarInfo.length - 1].getDay(); + + if (firstDay !== 0) { + Array(firstDay) + .fill(0) + .forEach((_, idx) => { + calendarInfo.unshift(getBeforeDate(new Date(year, month - 1, 1), idx + 1)); + }); + } + + if (lastDay !== 6) { + Array(6 - lastDay) + .fill(0) + .forEach((_, idx) => { + calendarInfo.push(getNextDate(new Date(year, month, 0), idx + 1)); + }); + } + + return calendarInfo.map((el) => { + return { + year: el.getFullYear(), + month: el.getMonth() + 1, + date: el.getDate(), + day: el.getDay(), + }; + }); +}; + +export { createPostBody, getDate, getDateTime, getCalendarMonth, getBeforeDate, getNextDate }; From d33273d77771d448fd61a780b3a144aeca682395 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 19 Jul 2022 13:17:13 +0900 Subject: [PATCH 0175/1011] =?UTF-8?q?feat:=20=EB=82=A0=EC=A7=9C=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=9C=A0=ED=8B=B8=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EB=B0=8F=20=ED=8C=8C=EC=9D=BC=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ScheduleAddModal/ScheduleAddModal.tsx | 3 +- frontend/src/utils/date.ts | 88 +++++++++++++++++++ frontend/src/utils/index.ts | 55 +----------- 3 files changed, 91 insertions(+), 55 deletions(-) create mode 100644 frontend/src/utils/date.ts diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index 70f6c8d2..df1ffe0c 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -5,7 +5,8 @@ import { QueryObserverResult, RefetchOptions, RefetchQueryFilters, useMutation } import { Schedule } from '@/@types'; -import { createPostBody, getDate, getDateTime } from '@/utils'; +import { createPostBody } from '@/utils'; +import { getDate, getDateTime } from '@/utils/date'; import scheduleApi from '@/api/schedule'; diff --git a/frontend/src/utils/date.ts b/frontend/src/utils/date.ts new file mode 100644 index 00000000..3cdb9423 --- /dev/null +++ b/frontend/src/utils/date.ts @@ -0,0 +1,88 @@ +const getNextYearMonth = (targetYear: number, targetMonth: number) => { + if (targetMonth === 12) { + return { year: targetYear + 1, month: 1 }; + } + + return { year: targetYear, month: targetMonth + 1 }; +}; + +const getBeforeYearMonth = (targetYear: number, targetMonth: number) => { + if (targetMonth === 1) { + return { year: targetYear - 1, month: 12 }; + } + + return { year: targetYear, month: targetMonth - 1 }; +}; + +const getThisYear = () => { + return new Date().getFullYear(); +}; + +const getThisMonth = () => { + return new Date().getMonth() + 1; +}; + +const getDate = () => { + return new Date(+new Date() + 3240 * 10000).toISOString().split('T')[0]; +}; + +const getDateTime = () => { + return new Date(+new Date() + 3240 * 10000).toISOString().replace(/\..*/, '').slice(0, -3); +}; + +const getBeforeDate = (targetDay: Date, offset: number) => + new Date(targetDay.setDate(targetDay.getDate() - offset)); + +const getNextDate = (targetDay: Date, offset: number) => + new Date(targetDay.setDate(targetDay.getDate() + offset)); + +const getCalendarMonth = (year: number, month: number) => { + const firstDate = new Date(year, month - 1, 1); + + const calendarInfo: Date[] = []; + + while (firstDate.getMonth() === month - 1) { + calendarInfo.push(new Date(firstDate)); + firstDate.setDate(firstDate.getDate() + 1); + } + + const firstDay = calendarInfo[0].getDay(); + const lastDay = calendarInfo[calendarInfo.length - 1].getDay(); + + if (firstDay !== 0) { + Array(firstDay) + .fill(0) + .forEach((_, idx) => { + calendarInfo.unshift(getBeforeDate(new Date(year, month - 1, 1), idx + 1)); + }); + } + + if (lastDay !== 6) { + Array(6 - lastDay) + .fill(0) + .forEach((_, idx) => { + calendarInfo.push(getNextDate(new Date(year, month, 0), idx + 1)); + }); + } + + return calendarInfo.map((el) => { + return { + year: el.getFullYear(), + month: el.getMonth() + 1, + date: el.getDate(), + day: el.getDay(), + }; + }); +}; + +export { + getNextYearMonth, + getBeforeYearMonth, + getThisYear, + getThisMonth, + getDate, + getDateTime, + getCalendarMonth, + getBeforeDate, + getNextDate, +}; diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts index 05549428..ad49d2e4 100644 --- a/frontend/src/utils/index.ts +++ b/frontend/src/utils/index.ts @@ -19,57 +19,4 @@ const createPostBody = (inputRef: InputRef) => { return body; }; -const getDate = () => { - return new Date(+new Date() + 3240 * 10000).toISOString().split('T')[0]; -}; - -const getDateTime = () => { - return new Date(+new Date() + 3240 * 10000).toISOString().replace(/\..*/, '').slice(0, -3); -}; - -const getBeforeDate = (targetDay: Date, offset: number) => - new Date(targetDay.setDate(targetDay.getDate() - offset)); - -const getNextDate = (targetDay: Date, offset: number) => - new Date(targetDay.setDate(targetDay.getDate() + offset)); - -const getCalendarMonth = (month: number, year: number) => { - const firstDate = new Date(year, month - 1, 1); - - const calendarInfo: Date[] = []; - - while (firstDate.getMonth() === month - 1) { - calendarInfo.push(new Date(firstDate)); - firstDate.setDate(firstDate.getDate() + 1); - } - - const firstDay = calendarInfo[0].getDay(); - const lastDay = calendarInfo[calendarInfo.length - 1].getDay(); - - if (firstDay !== 0) { - Array(firstDay) - .fill(0) - .forEach((_, idx) => { - calendarInfo.unshift(getBeforeDate(new Date(year, month - 1, 1), idx + 1)); - }); - } - - if (lastDay !== 6) { - Array(6 - lastDay) - .fill(0) - .forEach((_, idx) => { - calendarInfo.push(getNextDate(new Date(year, month, 0), idx + 1)); - }); - } - - return calendarInfo.map((el) => { - return { - year: el.getFullYear(), - month: el.getMonth() + 1, - date: el.getDate(), - day: el.getDay(), - }; - }); -}; - -export { createPostBody, getDate, getDateTime, getCalendarMonth, getBeforeDate, getNextDate }; +export { createPostBody }; From 85833adc6ad6d2a65230d3b5c99977e07599bc0a Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 19 Jul 2022 13:17:30 +0900 Subject: [PATCH 0176/1011] =?UTF-8?q?feat:=20=EC=9A=94=EC=9D=BC=20?= =?UTF-8?q?=EC=83=81=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/constants/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index a3957094..6d424562 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -21,4 +21,6 @@ const PATH = { PROFILE: '/profile', }; -export { API, CACHE_KEY, STORAGE_KEY, PATH }; +const DAYS = ['일', '월', '화', '수', '목', '금', '토']; + +export { API, CACHE_KEY, DAYS, STORAGE_KEY, PATH }; From 03873cd2b0b2a1cd704a40758a74b4b4288a1943 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 19 Jul 2022 13:18:00 +0900 Subject: [PATCH 0177/1011] =?UTF-8?q?feat:=20=EA=B0=9C=EB=B3=84=20?= =?UTF-8?q?=EB=82=A0=EC=A7=9C=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CalendarDate/CalendarDate.stories.tsx | 20 +++++++++++++ .../CalendarDate/CalendarDate.style.ts | 29 +++++++++++++++++++ .../components/CalendarDate/CalendarDate.tsx | 26 +++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 frontend/src/components/CalendarDate/CalendarDate.stories.tsx create mode 100644 frontend/src/components/CalendarDate/CalendarDate.style.ts create mode 100644 frontend/src/components/CalendarDate/CalendarDate.tsx diff --git a/frontend/src/components/CalendarDate/CalendarDate.stories.tsx b/frontend/src/components/CalendarDate/CalendarDate.stories.tsx new file mode 100644 index 00000000..08487c3d --- /dev/null +++ b/frontend/src/components/CalendarDate/CalendarDate.stories.tsx @@ -0,0 +1,20 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; + +import CalendarDate from './CalendarDate'; + +export default { + title: 'Components/CalendarDate', + component: CalendarDate, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ; + +export const Primary = Template.bind({}); +Primary.args = { + dateInfo: { + year: 2022, + month: 7, + date: 22, + day: 0, + }, +}; diff --git a/frontend/src/components/CalendarDate/CalendarDate.style.ts b/frontend/src/components/CalendarDate/CalendarDate.style.ts new file mode 100644 index 00000000..2284d24d --- /dev/null +++ b/frontend/src/components/CalendarDate/CalendarDate.style.ts @@ -0,0 +1,29 @@ +import { css, Theme } from '@emotion/react'; + +const calendarDate = ({ colors }: Theme, day: number, isThisMonth: boolean) => css` + background: ${day === 0 || day === 6 ? colors.GRAY_100 : colors.WHITE}; + + opacity: ${isThisMonth || 0.5}; +`; + +const dateBorder = ({ colors }: Theme) => css` + position: relative; + + height: 30rem; + padding: 1rem; + border-top: 1px solid ${colors.GRAY_300}; + border-right: 1px solid ${colors.GRAY_300}; +`; + +const dateText = css` + position: absolute; + top: 2rem; + right: 2rem; + + padding: 1rem; + + font-size: 4rem; + font-weight: 700; +`; + +export { calendarDate, dateText, dateBorder }; diff --git a/frontend/src/components/CalendarDate/CalendarDate.tsx b/frontend/src/components/CalendarDate/CalendarDate.tsx new file mode 100644 index 00000000..d80693aa --- /dev/null +++ b/frontend/src/components/CalendarDate/CalendarDate.tsx @@ -0,0 +1,26 @@ +import { useTheme } from '@emotion/react'; + +import { CalendarType } from '@/@types/calendar'; + +import { calendarDate, dateBorder, dateText } from './CalendarDate.style'; + +interface CalendarDateProps { + dateInfo: CalendarType; + isThisMonth: boolean; +} + +function CalendarDate({ dateInfo, isThisMonth }: CalendarDateProps) { + const theme = useTheme(); + + return ( +
+
+
+ {dateInfo.date} +
+
+
+ ); +} + +export default CalendarDate; From 7af9b014ff6d53dd9904f8d5f5caa62be174f1fb Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 19 Jul 2022 13:18:44 +0900 Subject: [PATCH 0178/1011] =?UTF-8?q?feat:=20=EB=8B=AC=EB=A0=A5=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/@types/calendar.ts | 8 ++ .../components/Calendar/Calendar.styles.ts | 46 +++++++-- frontend/src/components/Calendar/Calendar.tsx | 94 +++++++++++++++---- .../src/pages/CalendarPage/CalendarPage.tsx | 2 +- 4 files changed, 122 insertions(+), 28 deletions(-) create mode 100644 frontend/src/@types/calendar.ts diff --git a/frontend/src/@types/calendar.ts b/frontend/src/@types/calendar.ts new file mode 100644 index 00000000..c0aa76dc --- /dev/null +++ b/frontend/src/@types/calendar.ts @@ -0,0 +1,8 @@ +interface CalendarType { + year: number; + month: number; + date: number; + day: number; +} + +export { CalendarType }; diff --git a/frontend/src/components/Calendar/Calendar.styles.ts b/frontend/src/components/Calendar/Calendar.styles.ts index de637f33..57f332eb 100644 --- a/frontend/src/components/Calendar/Calendar.styles.ts +++ b/frontend/src/components/Calendar/Calendar.styles.ts @@ -1,20 +1,46 @@ import { css, Theme } from '@emotion/react'; -const calendar = ({ flex }: Theme) => css` - ${flex.column} +import { DAYS } from '@/constants'; + +const calendarHeader = ({ flex }: Theme) => css` + ${flex.row} + + justify-content:space-between; width: 100%; - height: 100%; + padding: 4rem; + + font-size: 6rem; + font-weight: 700; +`; + +const monthPicker = ({ flex }: Theme) => css` + ${flex.row} - gap: 5rem; + justify-content:space-around; + + width: 40rem; + padding-right: 4rem; + + font-size: 5rem; + line-height: 5rem; `; -const schedule = ({ colors }: Theme) => css` - padding: 5rem; - border: 1px solid ${colors.BLACK}; +const calendarGrid = css` + display: grid; + grid-template-columns: repeat(7, calc(100% / 7)); +`; + +const dayBar = ({ colors }: Theme, day: string) => css` + padding: 3rem; + border-top: 1px solid ${colors.GRAY_300}; + border-right: 1px solid ${colors.GRAY_300}; + + background: ${day === DAYS[0] || day === DAYS[6] ? colors.GRAY_100 : colors.WHITE}; - font-size: 4rem; - line-height: 8rem; + font-size: 3.5rem; + font-weight: 700; + text-align: right; `; -export { calendar, schedule }; +export { calendarHeader, calendarGrid, dayBar, monthPicker }; diff --git a/frontend/src/components/Calendar/Calendar.tsx b/frontend/src/components/Calendar/Calendar.tsx index 7a6c9e6e..1b2ba3c0 100644 --- a/frontend/src/components/Calendar/Calendar.tsx +++ b/frontend/src/components/Calendar/Calendar.tsx @@ -1,24 +1,84 @@ -import { Schedule } from '@/@types'; +import { useTheme } from '@emotion/react'; +import { useState } from 'react'; +import { AiOutlineLeft, AiOutlineRight } from 'react-icons/ai'; -import { calendar, schedule } from './Calendar.styles'; +import CalendarDate from '@/components/CalendarDate/CalendarDate'; -interface CalendarProps { - schedules: Schedule[]; -} +import { DAYS } from '@/constants'; + +import { + getBeforeYearMonth, + getCalendarMonth, + getNextYearMonth, + getThisMonth, + getThisYear, +} from '@/utils/date'; + +import Button from '../@common/Button/Button'; +import { calendarGrid, calendarHeader, dayBar, monthPicker } from './Calendar.styles'; -function Calendar({ schedules }: CalendarProps) { +function Calendar() { + const theme = useTheme(); + + const [calendarMonth, setCalendarMonth] = useState( + getCalendarMonth(getThisYear(), getThisMonth()) + ); + const [current, setCurrent] = useState({ + year: calendarMonth[15].year, + month: calendarMonth[15].month, + }); + + const handleClickBeforeMonthButton = () => { + const { year, month } = getBeforeYearMonth(current.year, current.month); + setCurrent({ year, month }); + setCalendarMonth(getCalendarMonth(year, month)); + }; + + const handleClickTodayButton = () => { + const year = getThisYear(); + const month = getThisMonth(); + setCurrent({ year, month }); + setCalendarMonth(getCalendarMonth(year, month)); + }; + + const handleClickNextMonthButton = () => { + const { year, month } = getNextYearMonth(current.year, current.month); + setCurrent({ year, month }); + setCalendarMonth(getCalendarMonth(year, month)); + }; return ( -
- {schedules.map(({ id, title, startDateTime, endDateTime, memo }) => { - return ( -
- 📅 {startDateTime.split('T').join(' ')} ~ {endDateTime.split('T').join(' ')} -

< {title} >

- {memo} -
- ); - })} -
+ <> +
+ + {current.year}년 {current.month}월 + +
+ + + +
+
+ +
+ {DAYS.map((day) => ( + + {day} + + ))} +
+
+ {calendarMonth.map((info) => { + const key = `${info.year}${info.month}${info.date}${info.day}`; + return ( + + ); + })} +
+ ); } diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index 65b8f430..a9015110 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -55,7 +55,7 @@ function CalendarPage() { return ( - + From 004da47ec2921a617badcae4a31bc4ec94c0b099 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 19 Jul 2022 14:15:12 +0900 Subject: [PATCH 0179/1011] =?UTF-8?q?style:=20=EB=8B=AC=EB=A0=A5=20?= =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Calendar/Calendar.styles.ts | 33 ++++++++++++++++--- frontend/src/components/Calendar/Calendar.tsx | 29 +++++++++++----- .../CalendarDate/CalendarDate.style.ts | 2 +- .../components/CalendarDate/CalendarDate.tsx | 8 ++--- 4 files changed, 53 insertions(+), 19 deletions(-) diff --git a/frontend/src/components/Calendar/Calendar.styles.ts b/frontend/src/components/Calendar/Calendar.styles.ts index 57f332eb..d3486957 100644 --- a/frontend/src/components/Calendar/Calendar.styles.ts +++ b/frontend/src/components/Calendar/Calendar.styles.ts @@ -2,13 +2,19 @@ import { css, Theme } from '@emotion/react'; import { DAYS } from '@/constants'; +const calendar = css` + height: 95vh; + margin: 3rem; +`; + const calendarHeader = ({ flex }: Theme) => css` ${flex.row} justify-content:space-between; width: 100%; - padding: 4rem; + height: 5vh; + padding: 3rem; font-size: 6rem; font-weight: 700; @@ -18,17 +24,34 @@ const monthPicker = ({ flex }: Theme) => css` ${flex.row} justify-content:space-around; + align-items: center; width: 40rem; - padding-right: 4rem; +`; + +const navButton = css` + background: transparent; font-size: 5rem; - line-height: 5rem; + line-height: 3rem; + font-weight: 700; + + &:hover { + transform: scale(1.1); + } +`; + +const navBarGrid = css` + display: grid; + grid-template-columns: repeat(7, calc(100% / 7)); + + height: 5vh; `; -const calendarGrid = css` +const calendarGrid = (rowNum: number) => css` display: grid; grid-template-columns: repeat(7, calc(100% / 7)); + grid-auto-rows: calc(85vh / ${rowNum}); `; const dayBar = ({ colors }: Theme, day: string) => css` @@ -43,4 +66,4 @@ const dayBar = ({ colors }: Theme, day: string) => css` text-align: right; `; -export { calendarHeader, calendarGrid, dayBar, monthPicker }; +export { calendar, calendarHeader, navBarGrid, calendarGrid, dayBar, monthPicker, navButton }; diff --git a/frontend/src/components/Calendar/Calendar.tsx b/frontend/src/components/Calendar/Calendar.tsx index 1b2ba3c0..1cf99bab 100644 --- a/frontend/src/components/Calendar/Calendar.tsx +++ b/frontend/src/components/Calendar/Calendar.tsx @@ -15,7 +15,15 @@ import { } from '@/utils/date'; import Button from '../@common/Button/Button'; -import { calendarGrid, calendarHeader, dayBar, monthPicker } from './Calendar.styles'; +import { + calendar, + calendarGrid, + calendarHeader, + dayBar, + monthPicker, + navBarGrid, + navButton, +} from './Calendar.styles'; function Calendar() { const theme = useTheme(); @@ -46,31 +54,36 @@ function Calendar() { setCurrent({ year, month }); setCalendarMonth(getCalendarMonth(year, month)); }; + + const rowNum = Math.ceil(calendarMonth.length / 7); + return ( - <> +
{current.year}년 {current.month}월
- - - +
-
+
{DAYS.map((day) => ( {day} ))}
-
+
{calendarMonth.map((info) => { const key = `${info.year}${info.month}${info.date}${info.day}`; return ( @@ -78,7 +91,7 @@ function Calendar() { ); })}
- +
); } diff --git a/frontend/src/components/CalendarDate/CalendarDate.style.ts b/frontend/src/components/CalendarDate/CalendarDate.style.ts index 2284d24d..5fe9c03d 100644 --- a/frontend/src/components/CalendarDate/CalendarDate.style.ts +++ b/frontend/src/components/CalendarDate/CalendarDate.style.ts @@ -9,7 +9,7 @@ const calendarDate = ({ colors }: Theme, day: number, isThisMonth: boolean) => c const dateBorder = ({ colors }: Theme) => css` position: relative; - height: 30rem; + height: 100%; padding: 1rem; border-top: 1px solid ${colors.GRAY_300}; border-right: 1px solid ${colors.GRAY_300}; diff --git a/frontend/src/components/CalendarDate/CalendarDate.tsx b/frontend/src/components/CalendarDate/CalendarDate.tsx index d80693aa..f2907592 100644 --- a/frontend/src/components/CalendarDate/CalendarDate.tsx +++ b/frontend/src/components/CalendarDate/CalendarDate.tsx @@ -13,11 +13,9 @@ function CalendarDate({ dateInfo, isThisMonth }: CalendarDateProps) { const theme = useTheme(); return ( -
-
-
- {dateInfo.date} -
+
+
+ {dateInfo.date}
); From 45c2bb3188d0f7d524abdc6507ed4afc580cc95b Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 19 Jul 2022 14:48:23 +0900 Subject: [PATCH 0180/1011] =?UTF-8?q?refactor:=20=EB=8B=AC=EB=A0=A5=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B0=9C=ED=96=89=20?= =?UTF-8?q?=EB=B0=8F=20=EC=9C=A0=ED=8B=B8=ED=95=A8=EC=88=98=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Calendar/Calendar.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Calendar/Calendar.tsx b/frontend/src/components/Calendar/Calendar.tsx index 1cf99bab..bd989da2 100644 --- a/frontend/src/components/Calendar/Calendar.tsx +++ b/frontend/src/components/Calendar/Calendar.tsx @@ -31,13 +31,15 @@ function Calendar() { const [calendarMonth, setCalendarMonth] = useState( getCalendarMonth(getThisYear(), getThisMonth()) ); + const [current, setCurrent] = useState({ - year: calendarMonth[15].year, - month: calendarMonth[15].month, + year: getThisYear(), + month: getThisMonth(), }); const handleClickBeforeMonthButton = () => { const { year, month } = getBeforeYearMonth(current.year, current.month); + setCurrent({ year, month }); setCalendarMonth(getCalendarMonth(year, month)); }; @@ -45,12 +47,14 @@ function Calendar() { const handleClickTodayButton = () => { const year = getThisYear(); const month = getThisMonth(); + setCurrent({ year, month }); setCalendarMonth(getCalendarMonth(year, month)); }; const handleClickNextMonthButton = () => { const { year, month } = getNextYearMonth(current.year, current.month); + setCurrent({ year, month }); setCalendarMonth(getCalendarMonth(year, month)); }; @@ -86,6 +90,7 @@ function Calendar() {
{calendarMonth.map((info) => { const key = `${info.year}${info.month}${info.date}${info.day}`; + return ( ); From f74914ec488ae731d1b17616bb86aefc924bf720 Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 19 Jul 2022 13:53:39 +0900 Subject: [PATCH 0181/1011] =?UTF-8?q?test:=20SchduleAcceptance=EC=99=80=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20Fix?= =?UTF-8?q?ture=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acceptance/ScheduleAcceptanceTest.java | 55 +++++-------------- .../fixture/CommonAcceptanceFixture.java | 18 ++++++ .../fixture/ScheduleAcceptanceFixture.java | 34 ++++++++++++ .../common/fixture/ScheduleFixture.java | 12 ++++ 4 files changed, 78 insertions(+), 41 deletions(-) create mode 100644 backend/src/test/java/com/allog/dallog/acceptance/fixture/CommonAcceptanceFixture.java create mode 100644 backend/src/test/java/com/allog/dallog/acceptance/fixture/ScheduleAcceptanceFixture.java create mode 100644 backend/src/test/java/com/allog/dallog/common/fixture/ScheduleFixture.java diff --git a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java index 2fe388bd..00ece966 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java @@ -1,13 +1,18 @@ package com.allog.dallog.acceptance; -import io.restassured.RestAssured; +import static com.allog.dallog.acceptance.fixture.ScheduleAcceptanceFixture.새로운_일정을_등록한다; +import static com.allog.dallog.acceptance.fixture.ScheduleAcceptanceFixture.월별_일정을_조회한다; +import static com.allog.dallog.common.fixture.ScheduleFixture.END_DATA_TIME; +import static com.allog.dallog.common.fixture.ScheduleFixture.MEMO; +import static com.allog.dallog.common.fixture.ScheduleFixture.MONTH; +import static com.allog.dallog.common.fixture.ScheduleFixture.START_DATA_TIME; +import static com.allog.dallog.common.fixture.ScheduleFixture.TITLE; +import static com.allog.dallog.common.fixture.ScheduleFixture.YEAR; + import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; -import java.util.HashMap; -import java.util.Map; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; @DisplayName("일정 관련 기능") class ScheduleAcceptanceTest extends AcceptanceTest { @@ -15,14 +20,8 @@ class ScheduleAcceptanceTest extends AcceptanceTest { @DisplayName("정상적인 일정정보를 등록하면 상태코드 201을 반환한다.") @Test void 정상적인_일정정보를_등록하면_상태코드_201을_반환한다() { - // given - String title = "알록달록 회의"; - String startDateTime = "2022-07-04T13:00"; - String endDateTime = "2022-07-05T07:00"; - String memo = "알록달록 회의가 있어요"; - - // when - ExtractableResponse response = 새로운_일정을_등록한다(title, startDateTime, endDateTime, memo); + // given & when + ExtractableResponse response = 새로운_일정을_등록한다(TITLE, START_DATA_TIME, END_DATA_TIME, MEMO); // then 상태코드_201이_반환된다(response); @@ -32,39 +31,13 @@ class ScheduleAcceptanceTest extends AcceptanceTest { @Test void 월별_일정정보를_조회하면_상태코드_200을_반환한다() { // given - int year = 2022; - int month = 7; - - 새로운_일정을_등록한다("알록달록 회의 1", "2022-07-04T13:00", "2022-07-05T07:00", "알록달록 회의 1이 있어요"); - 새로운_일정을_등록한다("알록달록 회의 2", "2022-08-04T13:00", "2022-08-05T07:00", "알록달록 회의 2이 있어요"); + 새로운_일정을_등록한다(TITLE, START_DATA_TIME, END_DATA_TIME, MEMO); + 새로운_일정을_등록한다(TITLE, START_DATA_TIME, END_DATA_TIME, MEMO); // when - ExtractableResponse response = 월별_일정을_조회한다(year, month); + ExtractableResponse response = 월별_일정을_조회한다(YEAR, MONTH); // then 상태코드_200이_반환된다(response); } - - private ExtractableResponse 새로운_일정을_등록한다(final String title, final String startDateTime, - final String endDateTime, final String memo) { - Map params = new HashMap<>(); - params.put("title", title); - params.put("startDateTime", startDateTime); - params.put("endDateTime", endDateTime); - params.put("memo", memo); - - return RestAssured.given().log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(params) - .when().post("/api/schedules") - .then().log().all() - .extract(); - } - - private ExtractableResponse 월별_일정을_조회한다(final int year, final int month) { - return RestAssured.given().log().all() - .when().get("/api/schedules?year={year}&month={month}", year, month) - .then().log().all() - .extract(); - } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixture/CommonAcceptanceFixture.java b/backend/src/test/java/com/allog/dallog/acceptance/fixture/CommonAcceptanceFixture.java new file mode 100644 index 00000000..ea0978d4 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixture/CommonAcceptanceFixture.java @@ -0,0 +1,18 @@ +package com.allog.dallog.acceptance.fixture; + +import static org.assertj.core.api.Assertions.assertThat; + +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.springframework.http.HttpStatus; + +public class CommonAcceptanceFixture { + + public static void 상태코드_200이_반환된다(final ExtractableResponse response) { + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); + } + + public static void 상태코드_201이_반환된다(final ExtractableResponse response) { + assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); + } +} diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixture/ScheduleAcceptanceFixture.java b/backend/src/test/java/com/allog/dallog/acceptance/fixture/ScheduleAcceptanceFixture.java new file mode 100644 index 00000000..498f895f --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixture/ScheduleAcceptanceFixture.java @@ -0,0 +1,34 @@ +package com.allog.dallog.acceptance.fixture; + +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import java.util.HashMap; +import java.util.Map; +import org.springframework.http.MediaType; + +public class ScheduleAcceptanceFixture { + + public static ExtractableResponse 새로운_일정을_등록한다(final String title, final String startDateTime, + final String endDateTime, final String memo) { + Map params = new HashMap<>(); + params.put("title", title); + params.put("startDateTime", startDateTime); + params.put("endDateTime", endDateTime); + params.put("memo", memo); + + return RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(params) + .when().post("/api/schedules") + .then().log().all() + .extract(); + } + + public static ExtractableResponse 월별_일정을_조회한다(final int year, final int month) { + return RestAssured.given().log().all() + .when().get("/api/schedules?year={year}&month={month}", year, month) + .then().log().all() + .extract(); + } +} diff --git a/backend/src/test/java/com/allog/dallog/common/fixture/ScheduleFixture.java b/backend/src/test/java/com/allog/dallog/common/fixture/ScheduleFixture.java new file mode 100644 index 00000000..3c3fb1d2 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/common/fixture/ScheduleFixture.java @@ -0,0 +1,12 @@ +package com.allog.dallog.common.fixture; + +public class ScheduleFixture { + + public static final String TITLE = "알록달록 회의"; + public static final String START_DATA_TIME = "2022-07-04T13:00"; + public static final String END_DATA_TIME = "2022-07-05T07:00"; + public static final String MEMO = "알록달록 회의가 있어요"; + + public static final int YEAR = 2022; + public static final int MONTH = 7; +} From 0217a41e2f5f0511c372dbd8e70d2b72d4fa2e73 Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 19 Jul 2022 14:49:12 +0900 Subject: [PATCH 0182/1011] =?UTF-8?q?test:=20Schdule=EA=B3=BC=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acceptance/ScheduleAcceptanceTest.java | 10 +-- .../common/fixture/ScheduleFixture.java | 9 +- .../domain/ScheduleRepositoryTest.java | 88 +++++++++---------- .../dallog/schedule/domain/ScheduleTest.java | 27 +++--- .../schedule/service/ScheduleServiceTest.java | 61 ++++++------- 5 files changed, 93 insertions(+), 102 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java index 00ece966..582b2461 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java @@ -2,10 +2,10 @@ import static com.allog.dallog.acceptance.fixture.ScheduleAcceptanceFixture.새로운_일정을_등록한다; import static com.allog.dallog.acceptance.fixture.ScheduleAcceptanceFixture.월별_일정을_조회한다; -import static com.allog.dallog.common.fixture.ScheduleFixture.END_DATA_TIME; +import static com.allog.dallog.common.fixture.ScheduleFixture.END_DATE_TIME; import static com.allog.dallog.common.fixture.ScheduleFixture.MEMO; import static com.allog.dallog.common.fixture.ScheduleFixture.MONTH; -import static com.allog.dallog.common.fixture.ScheduleFixture.START_DATA_TIME; +import static com.allog.dallog.common.fixture.ScheduleFixture.START_DATE_TIME; import static com.allog.dallog.common.fixture.ScheduleFixture.TITLE; import static com.allog.dallog.common.fixture.ScheduleFixture.YEAR; @@ -21,7 +21,7 @@ class ScheduleAcceptanceTest extends AcceptanceTest { @Test void 정상적인_일정정보를_등록하면_상태코드_201을_반환한다() { // given & when - ExtractableResponse response = 새로운_일정을_등록한다(TITLE, START_DATA_TIME, END_DATA_TIME, MEMO); + ExtractableResponse response = 새로운_일정을_등록한다(TITLE, START_DATE_TIME, END_DATE_TIME, MEMO); // then 상태코드_201이_반환된다(response); @@ -31,8 +31,8 @@ class ScheduleAcceptanceTest extends AcceptanceTest { @Test void 월별_일정정보를_조회하면_상태코드_200을_반환한다() { // given - 새로운_일정을_등록한다(TITLE, START_DATA_TIME, END_DATA_TIME, MEMO); - 새로운_일정을_등록한다(TITLE, START_DATA_TIME, END_DATA_TIME, MEMO); + 새로운_일정을_등록한다(TITLE, START_DATE_TIME, END_DATE_TIME, MEMO); + 새로운_일정을_등록한다(TITLE, START_DATE_TIME, END_DATE_TIME, MEMO); // when ExtractableResponse response = 월별_일정을_조회한다(YEAR, MONTH); diff --git a/backend/src/test/java/com/allog/dallog/common/fixture/ScheduleFixture.java b/backend/src/test/java/com/allog/dallog/common/fixture/ScheduleFixture.java index 3c3fb1d2..eb6683d4 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixture/ScheduleFixture.java +++ b/backend/src/test/java/com/allog/dallog/common/fixture/ScheduleFixture.java @@ -1,12 +1,17 @@ package com.allog.dallog.common.fixture; +import java.time.LocalDateTime; + public class ScheduleFixture { public static final String TITLE = "알록달록 회의"; - public static final String START_DATA_TIME = "2022-07-04T13:00"; - public static final String END_DATA_TIME = "2022-07-05T07:00"; + public static final String START_DATE_TIME = "2022-07-04T13:00"; + public static final String END_DATE_TIME = "2022-07-05T07:00"; public static final String MEMO = "알록달록 회의가 있어요"; + public static final LocalDateTime START_DATE = LocalDateTime.of(2022, 7, 1, 0, 0); + public static final LocalDateTime END_DATE = LocalDateTime.of(2022, 7, 31, 0, 0); + public static final int YEAR = 2022; public static final int MONTH = 7; } diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java index 0e4ac470..0f956c7c 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java @@ -1,5 +1,9 @@ package com.allog.dallog.schedule.domain; +import static com.allog.dallog.common.fixture.ScheduleFixture.END_DATE; +import static com.allog.dallog.common.fixture.ScheduleFixture.MEMO; +import static com.allog.dallog.common.fixture.ScheduleFixture.START_DATE; +import static com.allog.dallog.common.fixture.ScheduleFixture.TITLE; import static org.assertj.core.api.Assertions.assertThat; import java.time.LocalDateTime; @@ -19,19 +23,17 @@ class ScheduleRepositoryTest { @Test void 시작일시와_종료일시를_전달하면_그_사이에_해당하는_일정을_조회한다() { // given - Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 7, 15, 14, 20), - LocalDateTime.of(2022, 7, 15, 16, 20), "달록"); - Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), - LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + Schedule schedule1 = new Schedule(TITLE, LocalDateTime.of(2022, 7, 14, 14, 20), + LocalDateTime.of(2022, 7, 15, 16, 20), MEMO); + + Schedule schedule2 = new Schedule(TITLE, LocalDateTime.of(2022, 8, 15, 14, 20), + LocalDateTime.of(2022, 8, 15, 16, 20), MEMO); scheduleRepository.save(schedule1); scheduleRepository.save(schedule2); - LocalDateTime startDate = LocalDateTime.of(2022, 7, 1, 0, 0); - LocalDateTime endDate = LocalDateTime.of(2022, 7, 31, 0, 0); - // when - List schedules = scheduleRepository.findByBetween(startDate, endDate); + List schedules = scheduleRepository.findByBetween(START_DATE, END_DATE); // then assertThat(schedules).hasSize(1); @@ -41,19 +43,17 @@ class ScheduleRepositoryTest { @Test void 시작일시와_종료일시를_전달할_때_일정의_시작날짜가_시작일시와_같으면_조회된다() { // given - Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 7, 1, 0, 0), - LocalDateTime.of(2022, 7, 15, 16, 20), "달록"); - Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), - LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + Schedule schedule1 = new Schedule(TITLE, LocalDateTime.of(2022, 7, 1, 0, 0), + LocalDateTime.of(2022, 7, 15, 16, 20), MEMO); + + Schedule schedule2 = new Schedule(TITLE, LocalDateTime.of(2022, 8, 15, 14, 20), + LocalDateTime.of(2022, 8, 15, 16, 20), MEMO); scheduleRepository.save(schedule1); scheduleRepository.save(schedule2); - LocalDateTime startDate = LocalDateTime.of(2022, 7, 1, 0, 0); - LocalDateTime endDate = LocalDateTime.of(2022, 7, 31, 0, 0); - // when - List schedules = scheduleRepository.findByBetween(startDate, endDate); + List schedules = scheduleRepository.findByBetween(START_DATE, END_DATE); // then assertThat(schedules).hasSize(1); @@ -63,19 +63,17 @@ class ScheduleRepositoryTest { @Test void 시작일시와_종료일시를_전달할_때_일정의_시작날짜가_종료일시와_같으면_조회된다() { // given - Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 7, 31, 0, 0), - LocalDateTime.of(2022, 8, 12, 13, 10), "달록"); - Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), - LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + Schedule schedule1 = new Schedule(TITLE, START_DATE, + LocalDateTime.of(2022, 8, 12, 13, 10), MEMO); + + Schedule schedule2 = new Schedule(TITLE, LocalDateTime.of(2022, 8, 15, 14, 20), + LocalDateTime.of(2022, 8, 15, 16, 20), MEMO); scheduleRepository.save(schedule1); scheduleRepository.save(schedule2); - LocalDateTime startDate = LocalDateTime.of(2022, 7, 1, 0, 0); - LocalDateTime endDate = LocalDateTime.of(2022, 7, 31, 0, 0); - // when - List schedules = scheduleRepository.findByBetween(startDate, endDate); + List schedules = scheduleRepository.findByBetween(START_DATE, END_DATE); // then assertThat(schedules).hasSize(1); @@ -85,19 +83,17 @@ class ScheduleRepositoryTest { @Test void 시작일시와_종료일시를_전달할_때_일정의_시작날짜가_종료일시_이후이면_조회되지_않는다() { // given - Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 7, 31, 0, 1), - LocalDateTime.of(2022, 8, 12, 13, 10), "달록"); - Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), - LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + Schedule schedule1 = new Schedule(TITLE, LocalDateTime.of(2022, 7, 31, 0, 1), + LocalDateTime.of(2022, 8, 12, 13, 10), MEMO); + + Schedule schedule2 = new Schedule(TITLE, LocalDateTime.of(2022, 8, 15, 14, 20), + LocalDateTime.of(2022, 8, 15, 16, 20), MEMO); scheduleRepository.save(schedule1); scheduleRepository.save(schedule2); - LocalDateTime startDate = LocalDateTime.of(2022, 7, 1, 0, 0); - LocalDateTime endDate = LocalDateTime.of(2022, 7, 31, 0, 0); - // when - List schedules = scheduleRepository.findByBetween(startDate, endDate); + List schedules = scheduleRepository.findByBetween(START_DATE, END_DATE); // then assertThat(schedules).hasSize(0); @@ -107,19 +103,17 @@ class ScheduleRepositoryTest { @Test void 시작일시와_종료일시를_전달할_때_일정의_종료날짜가_시작일시와_같으면_조회된다() { // given - Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 6, 12, 13, 40), - LocalDateTime.of(2022, 7, 1, 0, 0), "달록"); - Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), - LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + Schedule schedule1 = new Schedule(TITLE, LocalDateTime.of(2022, 6, 12, 13, 40), + START_DATE, MEMO); + + Schedule schedule2 = new Schedule(TITLE, LocalDateTime.of(2022, 8, 15, 14, 20), + LocalDateTime.of(2022, 8, 15, 16, 20), MEMO); scheduleRepository.save(schedule1); scheduleRepository.save(schedule2); - LocalDateTime startDate = LocalDateTime.of(2022, 7, 1, 0, 0); - LocalDateTime endDate = LocalDateTime.of(2022, 7, 31, 0, 0); - // when - List schedules = scheduleRepository.findByBetween(startDate, endDate); + List schedules = scheduleRepository.findByBetween(START_DATE, END_DATE); // then assertThat(schedules).hasSize(1); @@ -129,19 +123,17 @@ class ScheduleRepositoryTest { @Test void 시작일시와_종료일시를_전달할_때_일정의_종료날짜가_시작일시_이전이면_조회되지_않는다() { // given - Schedule schedule1 = new Schedule("알록1", LocalDateTime.of(2022, 6, 12, 13, 40), - LocalDateTime.of(2022, 6, 30, 23, 59), "달록"); - Schedule schedule2 = new Schedule("알록2", LocalDateTime.of(2022, 8, 15, 14, 20), - LocalDateTime.of(2022, 8, 15, 16, 20), "달록"); + Schedule schedule1 = new Schedule(TITLE, LocalDateTime.of(2022, 6, 12, 13, 40), + LocalDateTime.of(2022, 6, 30, 23, 59), MEMO); + + Schedule schedule2 = new Schedule(TITLE, LocalDateTime.of(2022, 8, 15, 14, 20), + LocalDateTime.of(2022, 8, 15, 16, 20), MEMO); scheduleRepository.save(schedule1); scheduleRepository.save(schedule2); - LocalDateTime startDate = LocalDateTime.of(2022, 7, 1, 0, 0); - LocalDateTime endDate = LocalDateTime.of(2022, 7, 31, 0, 0); - // when - List schedules = scheduleRepository.findByBetween(startDate, endDate); + List schedules = scheduleRepository.findByBetween(START_DATE, END_DATE); // then assertThat(schedules).hasSize(0); diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java index 42c95e53..8333cd98 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java @@ -1,5 +1,9 @@ package com.allog.dallog.schedule.domain; +import static com.allog.dallog.common.fixture.ScheduleFixture.END_DATE_TIME; +import static com.allog.dallog.common.fixture.ScheduleFixture.MEMO; +import static com.allog.dallog.common.fixture.ScheduleFixture.START_DATE_TIME; +import static com.allog.dallog.common.fixture.ScheduleFixture.TITLE; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -16,10 +20,10 @@ public class ScheduleTest { @Test void 일정을_생성한다() { // given - String title = "알록달록 회의"; - LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); - LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); - String memo = "알록달록 팀회의 - 선릉 큰 강의실"; + String title = TITLE; + LocalDateTime startDateTime = LocalDateTime.parse(START_DATE_TIME); + LocalDateTime endDateTime = LocalDateTime.parse(END_DATE_TIME); + String memo = MEMO; // when & then assertDoesNotThrow(() -> new Schedule(title, startDateTime, endDateTime, memo)); @@ -27,14 +31,13 @@ public class ScheduleTest { @DisplayName("일정 제목의 길이가 20을 초과하는 경우 예외를 던진다.") @ParameterizedTest - @ValueSource(strings = {"일이삼사오육칠팔구십일이삼사오육칠팔구십일", - "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 회의"}) + @ValueSource(strings = {"일이삼사오육칠팔구십일이삼사오육칠팔구십일", "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 회의"}) void 일정_제목의_길이가_20을_초과하는_경우_예외를_던진다(final String title) { //given String titleForSave = title; - LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); - LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); - String memo = "알록달록 팀회의 - 선릉 큰 강의실"; + LocalDateTime startDateTime = LocalDateTime.parse(START_DATE_TIME); + LocalDateTime endDateTime = LocalDateTime.parse(END_DATE_TIME); + String memo = MEMO; // when & then assertThatThrownBy(() -> new Schedule(titleForSave, startDateTime, endDateTime, memo)) @@ -45,9 +48,9 @@ public class ScheduleTest { @Test void 일정_메모의_길이가_255를_초과하는_경우_예외를_던진다() { // given - String title = "알록달록 회의"; - LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); - LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); + String title = TITLE; + LocalDateTime startDateTime = LocalDateTime.parse(START_DATE_TIME); + LocalDateTime endDateTime = LocalDateTime.parse(END_DATE_TIME); String memo = "1".repeat(256); // when & then diff --git a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java index 92351246..d63db571 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java @@ -1,8 +1,13 @@ package com.allog.dallog.schedule.service; +import static com.allog.dallog.common.fixture.ScheduleFixture.MEMO; +import static com.allog.dallog.common.fixture.ScheduleFixture.MONTH; +import static com.allog.dallog.common.fixture.ScheduleFixture.TITLE; +import static com.allog.dallog.common.fixture.ScheduleFixture.YEAR; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.allog.dallog.common.fixture.ScheduleFixture; import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; import com.allog.dallog.schedule.dto.response.ScheduleResponse; import com.allog.dallog.schedule.exception.InvalidScheduleException; @@ -21,20 +26,17 @@ class ScheduleServiceTest { @Autowired private ScheduleService scheduleService; + private final LocalDateTime START_DATA_TIME = LocalDateTime.parse(ScheduleFixture.START_DATE_TIME); + private final LocalDateTime END_DATA_TIME = LocalDateTime.parse(ScheduleFixture.END_DATE_TIME); + @DisplayName("새로운 일정을 생성한다.") @Test void 새로운_일정을_생성한다() { // given - String title = "알록달록 회의"; - LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); - LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); - String memo = "알록달록 팀회의 - 선릉 큰 강의실"; - - ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, startDateTime, endDateTime, - memo); + ScheduleCreateRequest request = new ScheduleCreateRequest(TITLE, START_DATA_TIME, END_DATA_TIME, MEMO); // when - Long id = scheduleService.save(scheduleCreateRequest); + Long id = scheduleService.save(request); // then assertThat(id).isNotNull(); @@ -45,15 +47,11 @@ class ScheduleServiceTest { void 새로운_일정을_생성_할_때_일정_제목의_길이가_20을_초과하는_경우_예외를_던진다() { // given String title = "일이삼사오육칠팔구십일이삼사오육칠팔구십일"; - LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); - LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); - String memo = "알록달록 팀회의 - 선릉 큰 강의실"; - ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, startDateTime, endDateTime, - memo); + ScheduleCreateRequest request = new ScheduleCreateRequest(title, START_DATA_TIME, END_DATA_TIME, MEMO); // when & then - assertThatThrownBy(() -> scheduleService.save(scheduleCreateRequest)). + assertThatThrownBy(() -> scheduleService.save(request)). isInstanceOf(InvalidScheduleException.class); } @@ -61,16 +59,12 @@ class ScheduleServiceTest { @Test void 새로운_일정을_생성_할_때_일정_메모의_길이가_255를_초과하는_경우_예외를_던진다() { // given - String title = "알록달록 회의"; - LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 5, 12, 30); - LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); String memo = "1".repeat(256); - ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, startDateTime, endDateTime, - memo); + ScheduleCreateRequest request = new ScheduleCreateRequest(TITLE, START_DATA_TIME, END_DATA_TIME, memo); // when & then - assertThatThrownBy(() -> scheduleService.save(scheduleCreateRequest)). + assertThatThrownBy(() -> scheduleService.save(request)). isInstanceOf(InvalidScheduleException.class); } @@ -78,16 +72,13 @@ class ScheduleServiceTest { @Test void 새로운_일정을_생성_할_때_종료일시가_시작일시_이전이라면_예외를_던진다() { // given - String title = "알록달록 회의"; LocalDateTime startDateTime = LocalDateTime.of(2022, 7, 7, 12, 30); LocalDateTime endDateTime = LocalDateTime.of(2022, 7, 6, 14, 30); - String memo = "1".repeat(256); - ScheduleCreateRequest scheduleCreateRequest = new ScheduleCreateRequest(title, startDateTime, endDateTime, - memo); + ScheduleCreateRequest request = new ScheduleCreateRequest(TITLE, startDateTime, endDateTime, MEMO); // when & then - assertThatThrownBy(() -> scheduleService.save(scheduleCreateRequest)). + assertThatThrownBy(() -> scheduleService.save(request)). isInstanceOf(InvalidScheduleException.class); } @@ -95,21 +86,21 @@ class ScheduleServiceTest { @Test void 연도와_월을_전달받아_해당_월에_해당하는_일정_목록을_가져온다() { // given - ScheduleCreateRequest scheduleCreateRequest1 = new ScheduleCreateRequest("알록달록 회의 1", - LocalDateTime.of(2022, 7, 5, 12, 30), LocalDateTime.of(2022, 7, 6, 14, 30), "알록달록 팀회의 - 선릉 큰 강의실"); + LocalDateTime startDateTime1 = LocalDateTime.of(2022, 7, 5, 12, 30); + LocalDateTime endDateTime1 = LocalDateTime.of(2022, 7, 6, 14, 30); + + ScheduleCreateRequest request1 = new ScheduleCreateRequest(TITLE, startDateTime1, endDateTime1, MEMO); - ScheduleCreateRequest scheduleCreateRequest2 = new ScheduleCreateRequest("알록달록 회의 2", - LocalDateTime.of(2022, 8, 5, 12, 30), LocalDateTime.of(2022, 8, 6, 14, 30), - "알록달록 팀회의 - 잠실 큰 강의실"); + LocalDateTime startDateTime2 = LocalDateTime.of(2022, 8, 5, 12, 30); + LocalDateTime endDateTime2 = LocalDateTime.of(2022, 8, 6, 14, 30); - scheduleService.save(scheduleCreateRequest1); - scheduleService.save(scheduleCreateRequest2); + ScheduleCreateRequest request2 = new ScheduleCreateRequest(TITLE, startDateTime2, endDateTime2, MEMO); - int year = 2022; - int month = 7; + scheduleService.save(request1); + scheduleService.save(request2); // when - List schedules = scheduleService.findByYearAndMonth(year, month); + List schedules = scheduleService.findByYearAndMonth(YEAR, MONTH); // then assertThat(schedules).hasSize(1); From ca4aa3145b7e694c923137fc81c0a0472167056e Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 19 Jul 2022 14:54:12 +0900 Subject: [PATCH 0183/1011] =?UTF-8?q?chore:=20test=20=ED=95=98=EC=9C=84?= =?UTF-8?q?=EC=9D=98=20fixture=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/acceptance/AuthAcceptanceTest.java | 2 +- .../dallog/acceptance/MemberAcceptanceTest.java | 4 ++-- .../dallog/acceptance/ScheduleAcceptanceTest.java | 12 ++++++------ .../allog/dallog/auth/service/AuthServiceTest.java | 4 ++-- .../dallog/{ => common}/config/TestConfig.java | 2 +- .../fixtures}/CategoryFixtures.java | 2 +- .../fixtures}/MemberFixtures.java | 2 +- .../fixtures}/OAuthMemberFixtures.java | 2 +- .../ScheduleFixtures.java} | 4 ++-- .../oauth/client/StubOAuthClient.java | 2 +- .../schedule/domain/ScheduleRepositoryTest.java | 8 ++++---- .../allog/dallog/schedule/domain/ScheduleTest.java | 8 ++++---- .../schedule/service/ScheduleServiceTest.java | 14 +++++++------- .../subscription/domain/SubscriptionTest.java | 4 ++-- 14 files changed, 35 insertions(+), 35 deletions(-) rename backend/src/test/java/com/allog/dallog/{ => common}/config/TestConfig.java (92%) rename backend/src/test/java/com/allog/dallog/{fixture => common/fixtures}/CategoryFixtures.java (83%) rename backend/src/test/java/com/allog/dallog/{fixture => common/fixtures}/MemberFixtures.java (91%) rename backend/src/test/java/com/allog/dallog/{fixture => common/fixtures}/OAuthMemberFixtures.java (91%) rename backend/src/test/java/com/allog/dallog/common/{fixture/ScheduleFixture.java => fixtures/ScheduleFixtures.java} (88%) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java index 8f9b944d..b96bf20d 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java @@ -5,7 +5,7 @@ import com.allog.dallog.auth.dto.TokenRequest; import com.allog.dallog.auth.dto.TokenResponse; -import com.allog.dallog.config.TestConfig; +import com.allog.dallog.common.config.TestConfig; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java index 931f2cd7..65faa5de 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -5,8 +5,8 @@ import com.allog.dallog.auth.dto.TokenRequest; import com.allog.dallog.auth.dto.TokenResponse; -import com.allog.dallog.config.TestConfig; -import com.allog.dallog.fixture.OAuthMemberFixtures; +import com.allog.dallog.common.config.TestConfig; +import com.allog.dallog.common.fixtures.OAuthMemberFixtures; import com.allog.dallog.member.dto.MemberResponse; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java index 582b2461..956dfc92 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java @@ -2,12 +2,12 @@ import static com.allog.dallog.acceptance.fixture.ScheduleAcceptanceFixture.새로운_일정을_등록한다; import static com.allog.dallog.acceptance.fixture.ScheduleAcceptanceFixture.월별_일정을_조회한다; -import static com.allog.dallog.common.fixture.ScheduleFixture.END_DATE_TIME; -import static com.allog.dallog.common.fixture.ScheduleFixture.MEMO; -import static com.allog.dallog.common.fixture.ScheduleFixture.MONTH; -import static com.allog.dallog.common.fixture.ScheduleFixture.START_DATE_TIME; -import static com.allog.dallog.common.fixture.ScheduleFixture.TITLE; -import static com.allog.dallog.common.fixture.ScheduleFixture.YEAR; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE_TIME; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.MONTH; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.START_DATE_TIME; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.TITLE; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.YEAR; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index 510c08ca..1773df39 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -3,8 +3,8 @@ import static org.assertj.core.api.Assertions.assertThat; import com.allog.dallog.auth.dto.TokenResponse; -import com.allog.dallog.config.TestConfig; -import com.allog.dallog.fixture.OAuthMemberFixtures; +import com.allog.dallog.common.config.TestConfig; +import com.allog.dallog.common.fixtures.OAuthMemberFixtures; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; import java.util.List; diff --git a/backend/src/test/java/com/allog/dallog/config/TestConfig.java b/backend/src/test/java/com/allog/dallog/common/config/TestConfig.java similarity index 92% rename from backend/src/test/java/com/allog/dallog/config/TestConfig.java rename to backend/src/test/java/com/allog/dallog/common/config/TestConfig.java index 0aebbe38..9cf8aae3 100644 --- a/backend/src/test/java/com/allog/dallog/config/TestConfig.java +++ b/backend/src/test/java/com/allog/dallog/common/config/TestConfig.java @@ -1,4 +1,4 @@ -package com.allog.dallog.config; +package com.allog.dallog.common.config; import com.allog.dallog.auth.support.OAuthClient; import com.allog.dallog.infrastructure.oauth.client.StubOAuthClient; diff --git a/backend/src/test/java/com/allog/dallog/fixture/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java similarity index 83% rename from backend/src/test/java/com/allog/dallog/fixture/CategoryFixtures.java rename to backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 0a7481a1..77f95f12 100644 --- a/backend/src/test/java/com/allog/dallog/fixture/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -1,4 +1,4 @@ -package com.allog.dallog.fixture; +package com.allog.dallog.common.fixtures; import com.allog.dallog.category.domain.Category; diff --git a/backend/src/test/java/com/allog/dallog/fixture/MemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java similarity index 91% rename from backend/src/test/java/com/allog/dallog/fixture/MemberFixtures.java rename to backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java index 59650b99..5c16b1fa 100644 --- a/backend/src/test/java/com/allog/dallog/fixture/MemberFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java @@ -1,4 +1,4 @@ -package com.allog.dallog.fixture; +package com.allog.dallog.common.fixtures; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.SocialType; diff --git a/backend/src/test/java/com/allog/dallog/fixture/OAuthMemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/OAuthMemberFixtures.java similarity index 91% rename from backend/src/test/java/com/allog/dallog/fixture/OAuthMemberFixtures.java rename to backend/src/test/java/com/allog/dallog/common/fixtures/OAuthMemberFixtures.java index cde3322d..bdc0ecb6 100644 --- a/backend/src/test/java/com/allog/dallog/fixture/OAuthMemberFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/OAuthMemberFixtures.java @@ -1,4 +1,4 @@ -package com.allog.dallog.fixture; +package com.allog.dallog.common.fixtures; import com.allog.dallog.auth.dto.OAuthMember; diff --git a/backend/src/test/java/com/allog/dallog/common/fixture/ScheduleFixture.java b/backend/src/test/java/com/allog/dallog/common/fixtures/ScheduleFixtures.java similarity index 88% rename from backend/src/test/java/com/allog/dallog/common/fixture/ScheduleFixture.java rename to backend/src/test/java/com/allog/dallog/common/fixtures/ScheduleFixtures.java index eb6683d4..e540abc6 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixture/ScheduleFixture.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/ScheduleFixtures.java @@ -1,8 +1,8 @@ -package com.allog.dallog.common.fixture; +package com.allog.dallog.common.fixtures; import java.time.LocalDateTime; -public class ScheduleFixture { +public class ScheduleFixtures { public static final String TITLE = "알록달록 회의"; public static final String START_DATE_TIME = "2022-07-04T13:00"; diff --git a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java index c841bf3b..2b4ef480 100644 --- a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java +++ b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java @@ -1,6 +1,6 @@ package com.allog.dallog.infrastructure.oauth.client; -import static com.allog.dallog.fixture.OAuthMemberFixtures.OAUTH_MEMBER; +import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_MEMBER; import com.allog.dallog.auth.dto.OAuthMember; import com.allog.dallog.auth.support.OAuthClient; diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java index 0f956c7c..05a9c6e5 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java @@ -1,9 +1,9 @@ package com.allog.dallog.schedule.domain; -import static com.allog.dallog.common.fixture.ScheduleFixture.END_DATE; -import static com.allog.dallog.common.fixture.ScheduleFixture.MEMO; -import static com.allog.dallog.common.fixture.ScheduleFixture.START_DATE; -import static com.allog.dallog.common.fixture.ScheduleFixture.TITLE; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.START_DATE; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.TITLE; import static org.assertj.core.api.Assertions.assertThat; import java.time.LocalDateTime; diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java index 8333cd98..cd7937d3 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java @@ -1,9 +1,9 @@ package com.allog.dallog.schedule.domain; -import static com.allog.dallog.common.fixture.ScheduleFixture.END_DATE_TIME; -import static com.allog.dallog.common.fixture.ScheduleFixture.MEMO; -import static com.allog.dallog.common.fixture.ScheduleFixture.START_DATE_TIME; -import static com.allog.dallog.common.fixture.ScheduleFixture.TITLE; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE_TIME; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.START_DATE_TIME; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.TITLE; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; diff --git a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java index d63db571..f634292b 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java @@ -1,13 +1,13 @@ package com.allog.dallog.schedule.service; -import static com.allog.dallog.common.fixture.ScheduleFixture.MEMO; -import static com.allog.dallog.common.fixture.ScheduleFixture.MONTH; -import static com.allog.dallog.common.fixture.ScheduleFixture.TITLE; -import static com.allog.dallog.common.fixture.ScheduleFixture.YEAR; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.MONTH; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.TITLE; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.YEAR; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.allog.dallog.common.fixture.ScheduleFixture; +import com.allog.dallog.common.fixtures.ScheduleFixtures; import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; import com.allog.dallog.schedule.dto.response.ScheduleResponse; import com.allog.dallog.schedule.exception.InvalidScheduleException; @@ -26,8 +26,8 @@ class ScheduleServiceTest { @Autowired private ScheduleService scheduleService; - private final LocalDateTime START_DATA_TIME = LocalDateTime.parse(ScheduleFixture.START_DATE_TIME); - private final LocalDateTime END_DATA_TIME = LocalDateTime.parse(ScheduleFixture.END_DATE_TIME); + private final LocalDateTime START_DATA_TIME = LocalDateTime.parse(ScheduleFixtures.START_DATE_TIME); + private final LocalDateTime END_DATA_TIME = LocalDateTime.parse(ScheduleFixtures.END_DATE_TIME); @DisplayName("새로운 일정을 생성한다.") @Test diff --git a/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java b/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java index 631ed3df..45207f6a 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java @@ -4,8 +4,8 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import com.allog.dallog.category.domain.Category; -import com.allog.dallog.fixture.CategoryFixtures; -import com.allog.dallog.fixture.MemberFixtures; +import com.allog.dallog.common.fixtures.CategoryFixtures; +import com.allog.dallog.common.fixtures.MemberFixtures; import com.allog.dallog.member.domain.Member; import com.allog.dallog.subscription.exception.InvalidSubscriptionException; import org.junit.jupiter.api.DisplayName; From ca5cf04ffa46f799960e57d39f2fa8f5221b128b Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 19 Jul 2022 17:11:33 +0900 Subject: [PATCH 0184/1011] =?UTF-8?q?test:=20=EC=9D=BC=EC=A0=95=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20fixture=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/member/domain/Member.java | 3 ++- .../acceptance/ScheduleAcceptanceTest.java | 11 ++++---- .../fixture/ScheduleAcceptanceFixture.java | 2 +- .../common/fixtures/ScheduleFixtures.java | 7 +++-- .../controller/ScheduleControllerTest.java | 26 ++++++++----------- .../dallog/schedule/domain/ScheduleTest.java | 12 ++++----- .../schedule/service/ScheduleServiceTest.java | 12 ++++----- 7 files changed, 36 insertions(+), 37 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/member/domain/Member.java b/backend/src/main/java/com/allog/dallog/member/domain/Member.java index 88c7c458..990c32f7 100644 --- a/backend/src/main/java/com/allog/dallog/member/domain/Member.java +++ b/backend/src/main/java/com/allog/dallog/member/domain/Member.java @@ -1,5 +1,6 @@ package com.allog.dallog.member.domain; +import com.allog.dallog.global.domain.BaseEntity; import com.allog.dallog.member.exception.InvalidMemberException; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -14,7 +15,7 @@ @Table(name = "members") @Entity -public class Member { +public class Member extends BaseEntity { private static final Pattern EMAIL_PATTERN = Pattern.compile("^[a-z0-9._-]+@[a-z]+[.]+[a-z]{2,3}$"); private static final int MAX_DISPLAY_NAME_LENGTH = 10; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java index 956dfc92..36ab9d82 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java @@ -2,10 +2,10 @@ import static com.allog.dallog.acceptance.fixture.ScheduleAcceptanceFixture.새로운_일정을_등록한다; import static com.allog.dallog.acceptance.fixture.ScheduleAcceptanceFixture.월별_일정을_조회한다; -import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE_TIME; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE_TIME_STRING; import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; import static com.allog.dallog.common.fixtures.ScheduleFixtures.MONTH; -import static com.allog.dallog.common.fixtures.ScheduleFixtures.START_DATE_TIME; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.START_DATE_TIME_STRING; import static com.allog.dallog.common.fixtures.ScheduleFixtures.TITLE; import static com.allog.dallog.common.fixtures.ScheduleFixtures.YEAR; @@ -21,7 +21,8 @@ class ScheduleAcceptanceTest extends AcceptanceTest { @Test void 정상적인_일정정보를_등록하면_상태코드_201을_반환한다() { // given & when - ExtractableResponse response = 새로운_일정을_등록한다(TITLE, START_DATE_TIME, END_DATE_TIME, MEMO); + ExtractableResponse response = 새로운_일정을_등록한다(TITLE, START_DATE_TIME_STRING, END_DATE_TIME_STRING, + MEMO); // then 상태코드_201이_반환된다(response); @@ -31,8 +32,8 @@ class ScheduleAcceptanceTest extends AcceptanceTest { @Test void 월별_일정정보를_조회하면_상태코드_200을_반환한다() { // given - 새로운_일정을_등록한다(TITLE, START_DATE_TIME, END_DATE_TIME, MEMO); - 새로운_일정을_등록한다(TITLE, START_DATE_TIME, END_DATE_TIME, MEMO); + 새로운_일정을_등록한다(TITLE, START_DATE_TIME_STRING, END_DATE_TIME_STRING, MEMO); + 새로운_일정을_등록한다(TITLE, START_DATE_TIME_STRING, END_DATE_TIME_STRING, MEMO); // when ExtractableResponse response = 월별_일정을_조회한다(YEAR, MONTH); diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixture/ScheduleAcceptanceFixture.java b/backend/src/test/java/com/allog/dallog/acceptance/fixture/ScheduleAcceptanceFixture.java index 498f895f..d5f51da4 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixture/ScheduleAcceptanceFixture.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixture/ScheduleAcceptanceFixture.java @@ -11,7 +11,7 @@ public class ScheduleAcceptanceFixture { public static ExtractableResponse 새로운_일정을_등록한다(final String title, final String startDateTime, final String endDateTime, final String memo) { - Map params = new HashMap<>(); + Map params = new HashMap<>(); params.put("title", title); params.put("startDateTime", startDateTime); params.put("endDateTime", endDateTime); diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/ScheduleFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/ScheduleFixtures.java index e540abc6..0ba7c9a8 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/ScheduleFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/ScheduleFixtures.java @@ -5,10 +5,13 @@ public class ScheduleFixtures { public static final String TITLE = "알록달록 회의"; - public static final String START_DATE_TIME = "2022-07-04T13:00"; - public static final String END_DATE_TIME = "2022-07-05T07:00"; + public static final LocalDateTime START_DATE_TIME = LocalDateTime.of(2022, 7, 15, 16, 0); + public static final LocalDateTime END_DATE_TIME = LocalDateTime.of(2022, 7, 16, 16, 0); public static final String MEMO = "알록달록 회의가 있어요"; + public static final String START_DATE_TIME_STRING = "2022-07-04T13:00"; + public static final String END_DATE_TIME_STRING = "2022-07-05T07:00"; + public static final LocalDateTime START_DATE = LocalDateTime.of(2022, 7, 1, 0, 0); public static final LocalDateTime END_DATE = LocalDateTime.of(2022, 7, 31, 0, 0); diff --git a/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java b/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java index f1585866..22f9e3b0 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java @@ -1,5 +1,11 @@ package com.allog.dallog.schedule.controller; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE_TIME; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.MONTH; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.START_DATE_TIME; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.TITLE; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.YEAR; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; @@ -17,10 +23,7 @@ import com.allog.dallog.schedule.dto.response.ScheduleResponse; import com.allog.dallog.schedule.service.ScheduleService; import com.fasterxml.jackson.databind.ObjectMapper; -import java.time.LocalDateTime; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -49,21 +52,15 @@ class ScheduleControllerTest { @Test void 일정_정보를_등록한다() throws Exception { // given - Map params = new HashMap<>(); - params.put("title", "알록"); - params.put("startDateTime", "2022-07-15T14:20"); - params.put("endDateTime", "2022-07-15T16:20"); - params.put("memo", "세모 회의실 6시 회의"); + ScheduleCreateRequest request = new ScheduleCreateRequest(TITLE, START_DATE_TIME, END_DATE_TIME, MEMO); - given(scheduleService.save(new ScheduleCreateRequest("알록", LocalDateTime.of(2022, 7, 15, 14, 20), - LocalDateTime.of(2022, 7, 15, 16, 20), "달록"))) - .willReturn(1L); + given(scheduleService.save(request)).willReturn(1L); // when & then mockMvc.perform(post("/api/schedules") .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) - .content(ObjectMapper.writeValueAsString(params))) + .content(ObjectMapper.writeValueAsString(request))) .andDo(print()) .andDo(document("schedule/save", preprocessRequest(prettyPrint()), @@ -76,9 +73,8 @@ class ScheduleControllerTest { @Test void 월별_일정_정보를_조회한다() throws Exception { //given - given(scheduleService.findByYearAndMonth(2022, 7)) - .willReturn(List.of(new ScheduleResponse(1L, "알록", LocalDateTime.of(2022, 7, 15, 14, 20), - LocalDateTime.of(2022, 7, 15, 16, 20), "달록"))); + given(scheduleService.findByYearAndMonth(YEAR, MONTH)) + .willReturn(List.of(new ScheduleResponse(1L, TITLE, START_DATE_TIME, END_DATE_TIME, MEMO))); // when & then mockMvc.perform(get("/api/schedules?year=2022&month=7") diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java index cd7937d3..fafdf91e 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java @@ -21,8 +21,8 @@ public class ScheduleTest { void 일정을_생성한다() { // given String title = TITLE; - LocalDateTime startDateTime = LocalDateTime.parse(START_DATE_TIME); - LocalDateTime endDateTime = LocalDateTime.parse(END_DATE_TIME); + LocalDateTime startDateTime = START_DATE_TIME; + LocalDateTime endDateTime = END_DATE_TIME; String memo = MEMO; // when & then @@ -35,8 +35,8 @@ public class ScheduleTest { void 일정_제목의_길이가_20을_초과하는_경우_예외를_던진다(final String title) { //given String titleForSave = title; - LocalDateTime startDateTime = LocalDateTime.parse(START_DATE_TIME); - LocalDateTime endDateTime = LocalDateTime.parse(END_DATE_TIME); + LocalDateTime startDateTime = START_DATE_TIME; + LocalDateTime endDateTime = END_DATE_TIME; String memo = MEMO; // when & then @@ -49,8 +49,8 @@ public class ScheduleTest { void 일정_메모의_길이가_255를_초과하는_경우_예외를_던진다() { // given String title = TITLE; - LocalDateTime startDateTime = LocalDateTime.parse(START_DATE_TIME); - LocalDateTime endDateTime = LocalDateTime.parse(END_DATE_TIME); + LocalDateTime startDateTime = START_DATE_TIME; + LocalDateTime endDateTime = END_DATE_TIME; String memo = "1".repeat(256); // when & then diff --git a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java index f634292b..86a89bb4 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java @@ -1,13 +1,14 @@ package com.allog.dallog.schedule.service; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE_TIME; import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; import static com.allog.dallog.common.fixtures.ScheduleFixtures.MONTH; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.START_DATE_TIME; import static com.allog.dallog.common.fixtures.ScheduleFixtures.TITLE; import static com.allog.dallog.common.fixtures.ScheduleFixtures.YEAR; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.allog.dallog.common.fixtures.ScheduleFixtures; import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; import com.allog.dallog.schedule.dto.response.ScheduleResponse; import com.allog.dallog.schedule.exception.InvalidScheduleException; @@ -26,14 +27,11 @@ class ScheduleServiceTest { @Autowired private ScheduleService scheduleService; - private final LocalDateTime START_DATA_TIME = LocalDateTime.parse(ScheduleFixtures.START_DATE_TIME); - private final LocalDateTime END_DATA_TIME = LocalDateTime.parse(ScheduleFixtures.END_DATE_TIME); - @DisplayName("새로운 일정을 생성한다.") @Test void 새로운_일정을_생성한다() { // given - ScheduleCreateRequest request = new ScheduleCreateRequest(TITLE, START_DATA_TIME, END_DATA_TIME, MEMO); + ScheduleCreateRequest request = new ScheduleCreateRequest(TITLE, START_DATE_TIME, END_DATE_TIME, MEMO); // when Long id = scheduleService.save(request); @@ -48,7 +46,7 @@ class ScheduleServiceTest { // given String title = "일이삼사오육칠팔구십일이삼사오육칠팔구십일"; - ScheduleCreateRequest request = new ScheduleCreateRequest(title, START_DATA_TIME, END_DATA_TIME, MEMO); + ScheduleCreateRequest request = new ScheduleCreateRequest(title, START_DATE_TIME, END_DATE_TIME, MEMO); // when & then assertThatThrownBy(() -> scheduleService.save(request)). @@ -61,7 +59,7 @@ class ScheduleServiceTest { // given String memo = "1".repeat(256); - ScheduleCreateRequest request = new ScheduleCreateRequest(TITLE, START_DATA_TIME, END_DATA_TIME, memo); + ScheduleCreateRequest request = new ScheduleCreateRequest(TITLE, START_DATE_TIME, END_DATE_TIME, memo); // when & then assertThatThrownBy(() -> scheduleService.save(request)). From 521a170091f63a625b985ad6b56553cd607eb89a Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 19 Jul 2022 17:49:13 +0900 Subject: [PATCH 0185/1011] =?UTF-8?q?test:=20ScheduleFixtures=EC=9D=98=20?= =?UTF-8?q?=EC=83=81=EC=88=98=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/fixtures/ScheduleFixtures.java | 4 ++-- .../domain/ScheduleRepositoryTest.java | 20 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/ScheduleFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/ScheduleFixtures.java index 0ba7c9a8..3aa2990f 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/ScheduleFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/ScheduleFixtures.java @@ -12,8 +12,8 @@ public class ScheduleFixtures { public static final String START_DATE_TIME_STRING = "2022-07-04T13:00"; public static final String END_DATE_TIME_STRING = "2022-07-05T07:00"; - public static final LocalDateTime START_DATE = LocalDateTime.of(2022, 7, 1, 0, 0); - public static final LocalDateTime END_DATE = LocalDateTime.of(2022, 7, 31, 0, 0); + public static final LocalDateTime START_DAY_OF_MONTH = LocalDateTime.of(2022, 7, 1, 0, 0); + public static final LocalDateTime END_DAY_OF_MONTH = LocalDateTime.of(2022, 7, 31, 0, 0); public static final int YEAR = 2022; public static final int MONTH = 7; diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java index 05a9c6e5..8a43d67b 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java @@ -1,8 +1,8 @@ package com.allog.dallog.schedule.domain; -import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DAY_OF_MONTH; import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; -import static com.allog.dallog.common.fixtures.ScheduleFixtures.START_DATE; +import static com.allog.dallog.common.fixtures.ScheduleFixtures.START_DAY_OF_MONTH; import static com.allog.dallog.common.fixtures.ScheduleFixtures.TITLE; import static org.assertj.core.api.Assertions.assertThat; @@ -33,7 +33,7 @@ class ScheduleRepositoryTest { scheduleRepository.save(schedule2); // when - List schedules = scheduleRepository.findByBetween(START_DATE, END_DATE); + List schedules = scheduleRepository.findByBetween(START_DAY_OF_MONTH, END_DAY_OF_MONTH); // then assertThat(schedules).hasSize(1); @@ -53,7 +53,7 @@ class ScheduleRepositoryTest { scheduleRepository.save(schedule2); // when - List schedules = scheduleRepository.findByBetween(START_DATE, END_DATE); + List schedules = scheduleRepository.findByBetween(START_DAY_OF_MONTH, END_DAY_OF_MONTH); // then assertThat(schedules).hasSize(1); @@ -63,7 +63,7 @@ class ScheduleRepositoryTest { @Test void 시작일시와_종료일시를_전달할_때_일정의_시작날짜가_종료일시와_같으면_조회된다() { // given - Schedule schedule1 = new Schedule(TITLE, START_DATE, + Schedule schedule1 = new Schedule(TITLE, START_DAY_OF_MONTH, LocalDateTime.of(2022, 8, 12, 13, 10), MEMO); Schedule schedule2 = new Schedule(TITLE, LocalDateTime.of(2022, 8, 15, 14, 20), @@ -73,7 +73,7 @@ class ScheduleRepositoryTest { scheduleRepository.save(schedule2); // when - List schedules = scheduleRepository.findByBetween(START_DATE, END_DATE); + List schedules = scheduleRepository.findByBetween(START_DAY_OF_MONTH, END_DAY_OF_MONTH); // then assertThat(schedules).hasSize(1); @@ -93,7 +93,7 @@ class ScheduleRepositoryTest { scheduleRepository.save(schedule2); // when - List schedules = scheduleRepository.findByBetween(START_DATE, END_DATE); + List schedules = scheduleRepository.findByBetween(START_DAY_OF_MONTH, END_DAY_OF_MONTH); // then assertThat(schedules).hasSize(0); @@ -104,7 +104,7 @@ class ScheduleRepositoryTest { void 시작일시와_종료일시를_전달할_때_일정의_종료날짜가_시작일시와_같으면_조회된다() { // given Schedule schedule1 = new Schedule(TITLE, LocalDateTime.of(2022, 6, 12, 13, 40), - START_DATE, MEMO); + START_DAY_OF_MONTH, MEMO); Schedule schedule2 = new Schedule(TITLE, LocalDateTime.of(2022, 8, 15, 14, 20), LocalDateTime.of(2022, 8, 15, 16, 20), MEMO); @@ -113,7 +113,7 @@ class ScheduleRepositoryTest { scheduleRepository.save(schedule2); // when - List schedules = scheduleRepository.findByBetween(START_DATE, END_DATE); + List schedules = scheduleRepository.findByBetween(START_DAY_OF_MONTH, END_DAY_OF_MONTH); // then assertThat(schedules).hasSize(1); @@ -133,7 +133,7 @@ class ScheduleRepositoryTest { scheduleRepository.save(schedule2); // when - List schedules = scheduleRepository.findByBetween(START_DATE, END_DATE); + List schedules = scheduleRepository.findByBetween(START_DAY_OF_MONTH, END_DAY_OF_MONTH); // then assertThat(schedules).hasSize(0); From edae880e757c8525891a7563f86ebf6474e3b84e Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 19 Jul 2022 17:59:23 +0900 Subject: [PATCH 0186/1011] =?UTF-8?q?test:=20=EC=9D=B8=EC=88=98=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EA=B4=80=EB=A0=A8=20fixture=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/acceptance/ScheduleAcceptanceTest.java | 4 ++-- .../CommonAcceptanceFixtures.java} | 4 ++-- .../ScheduleAcceptanceFixtures.java} | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) rename backend/src/test/java/com/allog/dallog/acceptance/{fixture/CommonAcceptanceFixture.java => fixtures/CommonAcceptanceFixtures.java} (87%) rename backend/src/test/java/com/allog/dallog/acceptance/{fixture/ScheduleAcceptanceFixture.java => fixtures/ScheduleAcceptanceFixtures.java} (93%) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java index 36ab9d82..73cddb2b 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java @@ -1,7 +1,7 @@ package com.allog.dallog.acceptance; -import static com.allog.dallog.acceptance.fixture.ScheduleAcceptanceFixture.새로운_일정을_등록한다; -import static com.allog.dallog.acceptance.fixture.ScheduleAcceptanceFixture.월별_일정을_조회한다; +import static com.allog.dallog.acceptance.fixtures.ScheduleAcceptanceFixtures.새로운_일정을_등록한다; +import static com.allog.dallog.acceptance.fixtures.ScheduleAcceptanceFixtures.월별_일정을_조회한다; import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE_TIME_STRING; import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; import static com.allog.dallog.common.fixtures.ScheduleFixtures.MONTH; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixture/CommonAcceptanceFixture.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CommonAcceptanceFixtures.java similarity index 87% rename from backend/src/test/java/com/allog/dallog/acceptance/fixture/CommonAcceptanceFixture.java rename to backend/src/test/java/com/allog/dallog/acceptance/fixtures/CommonAcceptanceFixtures.java index ea0978d4..111c5ce3 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixture/CommonAcceptanceFixture.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CommonAcceptanceFixtures.java @@ -1,4 +1,4 @@ -package com.allog.dallog.acceptance.fixture; +package com.allog.dallog.acceptance.fixtures; import static org.assertj.core.api.Assertions.assertThat; @@ -6,7 +6,7 @@ import io.restassured.response.Response; import org.springframework.http.HttpStatus; -public class CommonAcceptanceFixture { +public class CommonAcceptanceFixtures { public static void 상태코드_200이_반환된다(final ExtractableResponse response) { assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixture/ScheduleAcceptanceFixture.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/ScheduleAcceptanceFixtures.java similarity index 93% rename from backend/src/test/java/com/allog/dallog/acceptance/fixture/ScheduleAcceptanceFixture.java rename to backend/src/test/java/com/allog/dallog/acceptance/fixtures/ScheduleAcceptanceFixtures.java index d5f51da4..bb35a95c 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixture/ScheduleAcceptanceFixture.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/ScheduleAcceptanceFixtures.java @@ -1,4 +1,4 @@ -package com.allog.dallog.acceptance.fixture; +package com.allog.dallog.acceptance.fixtures; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; @@ -7,7 +7,7 @@ import java.util.Map; import org.springframework.http.MediaType; -public class ScheduleAcceptanceFixture { +public class ScheduleAcceptanceFixtures { public static ExtractableResponse 새로운_일정을_등록한다(final String title, final String startDateTime, final String endDateTime, final String memo) { From 26f67d46dca8648d1593cda03823202603d85f44 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Tue, 19 Jul 2022 10:00:19 +0900 Subject: [PATCH 0187/1011] =?UTF-8?q?feat:=20page=20index=201=EB=B6=80?= =?UTF-8?q?=ED=84=B0=20=EC=8B=9C=EC=9E=91=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/category/controller/CategoryController.java | 9 +++------ .../allog/dallog/category/service/CategoryService.java | 8 ++++---- .../com/allog/dallog/global/dto/FindByPageResponse.java | 4 +++- backend/src/main/resources/application.properties | 3 ++- .../dallog/category/service/CategoryServiceTest.java | 4 ++-- backend/src/test/resources/application.properties | 1 + 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index 20c44e47..e0d362af 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -6,13 +6,12 @@ import com.allog.dallog.global.dto.FindByPageResponse; import java.net.URI; import javax.validation.Valid; -import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/api/categories") @@ -32,9 +31,7 @@ public ResponseEntity save(@Valid @RequestBody final CategoryCreateRequest } @GetMapping - public ResponseEntity> findAll(@RequestParam final int page, - @RequestParam final int size) { - PageRequest pageRequest = PageRequest.of(page, size); - return ResponseEntity.ok(categoryService.findAll(pageRequest)); + public ResponseEntity> findAll(Pageable pageable) { + return ResponseEntity.ok(categoryService.findAll(pageable)); } } diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index a00c675e..1e6aa451 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -7,7 +7,7 @@ import com.allog.dallog.global.dto.FindByPageResponse; import java.util.List; import java.util.stream.Collectors; -import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,12 +27,12 @@ public Long save(final CategoryCreateRequest request) { return category.getId(); } - public FindByPageResponse findAll(final PageRequest request) { - List responses = categoryRepository.findSliceBy(request.previousOrFirst()) + public FindByPageResponse findAll(final Pageable pageable) { + List responses = categoryRepository.findSliceBy(pageable) .getContent() .stream() .map(CategoryResponse::new) .collect(Collectors.toList()); - return new FindByPageResponse<>(request.getPageNumber(), responses); + return new FindByPageResponse<>(pageable.getPageNumber(), responses); } } diff --git a/backend/src/main/java/com/allog/dallog/global/dto/FindByPageResponse.java b/backend/src/main/java/com/allog/dallog/global/dto/FindByPageResponse.java index 14df3bf0..d2e04848 100644 --- a/backend/src/main/java/com/allog/dallog/global/dto/FindByPageResponse.java +++ b/backend/src/main/java/com/allog/dallog/global/dto/FindByPageResponse.java @@ -4,6 +4,8 @@ public class FindByPageResponse extends ListResponse { + private static final int START_PAGE_INDEX = 1; + private int page; private FindByPageResponse() { @@ -12,7 +14,7 @@ private FindByPageResponse() { public FindByPageResponse(final int page, final List responses) { super(responses); - this.page = page; + this.page = page + START_PAGE_INDEX; } public int getPage() { diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 37537561..a2c0a2d4 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -3,10 +3,11 @@ spring.datasource.username=sa spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create +spring.data.web.pageable.one-indexed-parameters=true logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE oauth.google.redirect_uri=${GOOGLE_REDIRECT_URI} oauth.google.client_id=${GOOGLE_CLIENT_ID} oauth.google.client_secret=${GOOGLE_CLIENT_SECRET} oauth.google.token_uri=${GOOGLE_TOKEN_URI} security.jwt.token.secret-key=${JWT_SECRET_KEY} -security.jwt.token.expire-length=${JWT_EXPIRE_LENGTH} +security.jwt.token.expire-length=${JWT_EXPIRE_LENGTH} diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index b18a5e56..71dc3379 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -62,7 +62,7 @@ class CategoryServiceTest { categoryService.save(new CategoryCreateRequest("지원플랫폼 근로")); categoryService.save(new CategoryCreateRequest("파랑의 코틀린 스터디")); - int page = 2; + int page = 1; // page index 0부터 시작 int size = 2; PageRequest request = PageRequest.of(page, size); @@ -75,7 +75,7 @@ class CategoryServiceTest { .hasSize(size) .extracting(CategoryResponse::getName) .contains("알록달록 회의", "지원플랫폼 근로"); - assertThat(response.getPage()).isEqualTo(page); + assertThat(response.getPage()).isEqualTo(page + 1); // 반환 값은 page index 1부터 시작 }); } } diff --git a/backend/src/test/resources/application.properties b/backend/src/test/resources/application.properties index 264bcbae..91bb59ac 100644 --- a/backend/src/test/resources/application.properties +++ b/backend/src/test/resources/application.properties @@ -5,6 +5,7 @@ spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create-drop logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE spring.main.allow-bean-definition-overriding=true +spring.data.web.pageable.one-indexed-parameters=true oauth.google.redirect_uri=http://localhost:3000 oauth.google.client_id=hyeonic oauth.google.client_secret=123 From 30c6b1af1017559e1c9bdf26c7dc9e78bc51d40b Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Tue, 19 Jul 2022 15:55:02 +0900 Subject: [PATCH 0188/1011] =?UTF-8?q?refactor:=20=EA=B3=B5=ED=86=B5=20DTO?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CategoryController.java | 9 ++++--- .../dto/response/CategoriesResponse.java | 27 +++++++++++++++++++ .../category/service/CategoryService.java | 6 ++--- .../dallog/global/dto/FindByPageResponse.java | 23 ---------------- .../allog/dallog/global/dto/ListResponse.java | 19 ------------- .../controller/ScheduleController.java | 8 +++--- .../dto/response/SchedulesResponse.java | 19 +++++++++++++ .../acceptance/CategoryAcceptanceTest.java | 8 +++--- .../category/service/CategoryServiceTest.java | 7 +++-- 9 files changed, 65 insertions(+), 61 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java delete mode 100644 backend/src/main/java/com/allog/dallog/global/dto/FindByPageResponse.java delete mode 100644 backend/src/main/java/com/allog/dallog/global/dto/ListResponse.java create mode 100644 backend/src/main/java/com/allog/dallog/schedule/dto/response/SchedulesResponse.java diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index e0d362af..9f70c71e 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -1,10 +1,11 @@ package com.allog.dallog.category.controller; import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.dto.response.CategoriesResponse; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; -import com.allog.dallog.global.dto.FindByPageResponse; import java.net.URI; +import java.util.List; import javax.validation.Valid; import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; @@ -31,7 +32,9 @@ public ResponseEntity save(@Valid @RequestBody final CategoryCreateRequest } @GetMapping - public ResponseEntity> findAll(Pageable pageable) { - return ResponseEntity.ok(categoryService.findAll(pageable)); + public ResponseEntity findAll(Pageable pageable) { + int pageNumber = pageable.getPageNumber(); + List categoryResponses = categoryService.findAll(pageable); + return ResponseEntity.ok(new CategoriesResponse(pageNumber, categoryResponses)); } } diff --git a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java new file mode 100644 index 00000000..0d12efd8 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java @@ -0,0 +1,27 @@ +package com.allog.dallog.category.dto.response; + +import java.util.List; + +public class CategoriesResponse { + + private static final int START_PAGE_INDEX = 1; + + private int page; + private List data; + + public CategoriesResponse() { + } + + public CategoriesResponse(final int page, final List data) { + this.page = page + START_PAGE_INDEX; + this.data = data; + } + + public int getPage() { + return page; + } + + public List getData() { + return data; + } +} diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index 1e6aa451..04029bda 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -4,7 +4,6 @@ import com.allog.dallog.category.domain.CategoryRepository; import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; -import com.allog.dallog.global.dto.FindByPageResponse; import java.util.List; import java.util.stream.Collectors; import org.springframework.data.domain.Pageable; @@ -27,12 +26,11 @@ public Long save(final CategoryCreateRequest request) { return category.getId(); } - public FindByPageResponse findAll(final Pageable pageable) { - List responses = categoryRepository.findSliceBy(pageable) + public List findAll(final Pageable pageable) { + return categoryRepository.findSliceBy(pageable) .getContent() .stream() .map(CategoryResponse::new) .collect(Collectors.toList()); - return new FindByPageResponse<>(pageable.getPageNumber(), responses); } } diff --git a/backend/src/main/java/com/allog/dallog/global/dto/FindByPageResponse.java b/backend/src/main/java/com/allog/dallog/global/dto/FindByPageResponse.java deleted file mode 100644 index d2e04848..00000000 --- a/backend/src/main/java/com/allog/dallog/global/dto/FindByPageResponse.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.allog.dallog.global.dto; - -import java.util.List; - -public class FindByPageResponse extends ListResponse { - - private static final int START_PAGE_INDEX = 1; - - private int page; - - private FindByPageResponse() { - super(); - } - - public FindByPageResponse(final int page, final List responses) { - super(responses); - this.page = page + START_PAGE_INDEX; - } - - public int getPage() { - return page; - } -} diff --git a/backend/src/main/java/com/allog/dallog/global/dto/ListResponse.java b/backend/src/main/java/com/allog/dallog/global/dto/ListResponse.java deleted file mode 100644 index 8090f06c..00000000 --- a/backend/src/main/java/com/allog/dallog/global/dto/ListResponse.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.allog.dallog.global.dto; - -import java.util.List; - -public class ListResponse { - - private List data; - - protected ListResponse() { - } - - public ListResponse(List data) { - this.data = data; - } - - public List getData() { - return data; - } -} diff --git a/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java b/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java index 1221bae6..1af7d90e 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java +++ b/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java @@ -1,8 +1,8 @@ package com.allog.dallog.schedule.controller; -import com.allog.dallog.global.dto.ListResponse; import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; import com.allog.dallog.schedule.dto.response.ScheduleResponse; +import com.allog.dallog.schedule.dto.response.SchedulesResponse; import com.allog.dallog.schedule.service.ScheduleService; import java.net.URI; import java.util.List; @@ -32,9 +32,9 @@ public ResponseEntity save(@Valid @RequestBody final ScheduleCreateRequest } @GetMapping - public ResponseEntity> findByYearAndMonth(@RequestParam final int year, - @RequestParam final int month) { + public ResponseEntity findByYearAndMonth(@RequestParam final int year, + @RequestParam final int month) { List responses = scheduleService.findByYearAndMonth(year, month); - return ResponseEntity.ok(new ListResponse<>(responses)); + return ResponseEntity.ok(new SchedulesResponse(responses)); } } diff --git a/backend/src/main/java/com/allog/dallog/schedule/dto/response/SchedulesResponse.java b/backend/src/main/java/com/allog/dallog/schedule/dto/response/SchedulesResponse.java new file mode 100644 index 00000000..0fd669c7 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/schedule/dto/response/SchedulesResponse.java @@ -0,0 +1,19 @@ +package com.allog.dallog.schedule.dto.response; + +import java.util.List; + +public class SchedulesResponse { + + private List data; + + public SchedulesResponse() { + } + + public SchedulesResponse(final List data) { + this.data = data; + } + + public List getData() { + return data; + } +} diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 99a6b18e..ffb268cd 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -4,7 +4,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.category.dto.request.CategoryCreateRequest; -import com.allog.dallog.global.dto.FindByPageResponse; +import com.allog.dallog.category.dto.response.CategoriesResponse; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; @@ -41,13 +41,13 @@ public class CategoryAcceptanceTest extends AcceptanceTest { // when ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(page, size); - FindByPageResponse findByPageResponse = response.as(FindByPageResponse.class); + CategoriesResponse categoriesResponse = response.as(CategoriesResponse.class); // then assertAll(() -> { 상태코드_200이_반환된다(response); - assertThat(findByPageResponse.getPage()).isEqualTo(page); - assertThat(findByPageResponse.getData()).hasSize(3); + assertThat(categoriesResponse.getPage()).isEqualTo(page); + assertThat(categoriesResponse.getData()).hasSize(3); }); } diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 71dc3379..16a22458 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -7,7 +7,7 @@ import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.exception.InvalidCategoryException; -import com.allog.dallog.global.dto.FindByPageResponse; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -67,15 +67,14 @@ class CategoryServiceTest { PageRequest request = PageRequest.of(page, size); // when - FindByPageResponse response = categoryService.findAll(request); + List response = categoryService.findAll(request); // then assertAll(() -> { - assertThat(response.getData()) + assertThat(response) .hasSize(size) .extracting(CategoryResponse::getName) .contains("알록달록 회의", "지원플랫폼 근로"); - assertThat(response.getPage()).isEqualTo(page + 1); // 반환 값은 page index 1부터 시작 }); } } From cdacf496fe9a5b2f480e7f9cf30a51dd29aa93e2 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Tue, 19 Jul 2022 16:00:46 +0900 Subject: [PATCH 0189/1011] =?UTF-8?q?refactor:=20page=20index=200=EB=B6=80?= =?UTF-8?q?=ED=84=B0=20=EC=8B=9C=EC=9E=91=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/category/dto/response/CategoriesResponse.java | 4 +--- backend/src/main/resources/application.properties | 1 - .../com/allog/dallog/acceptance/CategoryAcceptanceTest.java | 2 +- .../allog/dallog/category/service/CategoryServiceTest.java | 2 +- backend/src/test/resources/application.properties | 1 - 5 files changed, 3 insertions(+), 7 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java index 0d12efd8..7755cb65 100644 --- a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java +++ b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java @@ -4,8 +4,6 @@ public class CategoriesResponse { - private static final int START_PAGE_INDEX = 1; - private int page; private List data; @@ -13,7 +11,7 @@ public CategoriesResponse() { } public CategoriesResponse(final int page, final List data) { - this.page = page + START_PAGE_INDEX; + this.page = page; this.data = data; } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index a2c0a2d4..b43ca088 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -3,7 +3,6 @@ spring.datasource.username=sa spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create -spring.data.web.pageable.one-indexed-parameters=true logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE oauth.google.redirect_uri=${GOOGLE_REDIRECT_URI} oauth.google.client_id=${GOOGLE_CLIENT_ID} diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index ffb268cd..fbe4e25b 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -36,7 +36,7 @@ public class CategoryAcceptanceTest extends AcceptanceTest { 새로운_카테고리를_등록한다("FE 공식일정"); 새로운_카테고리를_등록한다("알록달록 회의"); - int page = 1; + int page = 0; int size = 8; // when diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 16a22458..5159df3d 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -62,7 +62,7 @@ class CategoryServiceTest { categoryService.save(new CategoryCreateRequest("지원플랫폼 근로")); categoryService.save(new CategoryCreateRequest("파랑의 코틀린 스터디")); - int page = 1; // page index 0부터 시작 + int page = 1; int size = 2; PageRequest request = PageRequest.of(page, size); diff --git a/backend/src/test/resources/application.properties b/backend/src/test/resources/application.properties index 91bb59ac..264bcbae 100644 --- a/backend/src/test/resources/application.properties +++ b/backend/src/test/resources/application.properties @@ -5,7 +5,6 @@ spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create-drop logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE spring.main.allow-bean-definition-overriding=true -spring.data.web.pageable.one-indexed-parameters=true oauth.google.redirect_uri=http://localhost:3000 oauth.google.client_id=hyeonic oauth.google.client_secret=123 From b342f447ab0764782e0b0a003d89c71ce5ade252 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Tue, 19 Jul 2022 16:03:23 +0900 Subject: [PATCH 0190/1011] =?UTF-8?q?refactor:=20response=20DTO=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/dto/response/CategoriesResponse.java | 10 +++++----- .../schedule/dto/response/SchedulesResponse.java | 10 +++++----- .../dallog/acceptance/CategoryAcceptanceTest.java | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java index 7755cb65..dc85e725 100644 --- a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java +++ b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java @@ -5,21 +5,21 @@ public class CategoriesResponse { private int page; - private List data; + private List categories; public CategoriesResponse() { } - public CategoriesResponse(final int page, final List data) { + public CategoriesResponse(final int page, final List categories) { this.page = page; - this.data = data; + this.categories = categories; } public int getPage() { return page; } - public List getData() { - return data; + public List getCategories() { + return categories; } } diff --git a/backend/src/main/java/com/allog/dallog/schedule/dto/response/SchedulesResponse.java b/backend/src/main/java/com/allog/dallog/schedule/dto/response/SchedulesResponse.java index 0fd669c7..72c8dea2 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/dto/response/SchedulesResponse.java +++ b/backend/src/main/java/com/allog/dallog/schedule/dto/response/SchedulesResponse.java @@ -4,16 +4,16 @@ public class SchedulesResponse { - private List data; + private List schedules; public SchedulesResponse() { } - public SchedulesResponse(final List data) { - this.data = data; + public SchedulesResponse(final List schedules) { + this.schedules = schedules; } - public List getData() { - return data; + public List getSchedules() { + return schedules; } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index fbe4e25b..3ae59c90 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -47,7 +47,7 @@ public class CategoryAcceptanceTest extends AcceptanceTest { assertAll(() -> { 상태코드_200이_반환된다(response); assertThat(categoriesResponse.getPage()).isEqualTo(page); - assertThat(categoriesResponse.getData()).hasSize(3); + assertThat(categoriesResponse.getCategories()).hasSize(3); }); } From d61aefa6728320dc3a73dae160f7ee6f13fe346d Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 00:06:17 +0900 Subject: [PATCH 0191/1011] =?UTF-8?q?test:=20OAuth=20=EC=9D=B8=EC=A6=9D?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20Fixtures=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/acceptance/MemberAcceptanceTest.java | 5 +---- .../allog/dallog/common/fixtures/OAuthMemberFixtures.java | 2 ++ 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java index 65faa5de..687b1a88 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -25,10 +25,7 @@ public class MemberAcceptanceTest extends AcceptanceTest { @Test void 등록된_회원이_자신의_정보를_조회하면_상태코드_200_을_반환한다() { // given - String oauthProvider = "google"; - String code = "sddsfsg4wedfabladsgklvdskfngdakfjgnkd"; - - TokenResponse tokenResponse = 자체_토큰을_생성한다(oauthProvider, code); + TokenResponse tokenResponse = 자체_토큰을_생성한다(OAuthMemberFixtures.OAUTH_PROVIDER, OAuthMemberFixtures.CODE); // when ExtractableResponse response = 자신의_정보를_조회한다(tokenResponse); diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/OAuthMemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/OAuthMemberFixtures.java index bdc0ecb6..21c6c6a8 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/OAuthMemberFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/OAuthMemberFixtures.java @@ -4,6 +4,8 @@ public class OAuthMemberFixtures { + public static final String OAUTH_PROVIDER = "google"; + public static final String CODE = "authorization code"; public static final String EMAIL = "example@email.com"; From 6d2bfe522df993ae64bdf49cdadca46094f9b094 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 00:07:13 +0900 Subject: [PATCH 0192/1011] =?UTF-8?q?faet:=20Category=20=EB=B0=8F=20Subscr?= =?UTF-8?q?iption=20NoSuch=20=EC=98=88=EC=99=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/exception/NoSuchCategoryException.java | 12 ++++++++++++ .../exception/NosuchSubscriptionException.java | 12 ++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/category/exception/NoSuchCategoryException.java create mode 100644 backend/src/main/java/com/allog/dallog/subscription/exception/NosuchSubscriptionException.java diff --git a/backend/src/main/java/com/allog/dallog/category/exception/NoSuchCategoryException.java b/backend/src/main/java/com/allog/dallog/category/exception/NoSuchCategoryException.java new file mode 100644 index 00000000..0934bb6b --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/category/exception/NoSuchCategoryException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.category.exception; + +public class NoSuchCategoryException extends RuntimeException { + + public NoSuchCategoryException(final String message) { + super(message); + } + + public NoSuchCategoryException() { + this("존재하지 않는 카테고리입니다."); + } +} diff --git a/backend/src/main/java/com/allog/dallog/subscription/exception/NosuchSubscriptionException.java b/backend/src/main/java/com/allog/dallog/subscription/exception/NosuchSubscriptionException.java new file mode 100644 index 00000000..a07381b8 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/subscription/exception/NosuchSubscriptionException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.subscription.exception; + +public class NosuchSubscriptionException extends RuntimeException { + + public NosuchSubscriptionException(final String message) { + super(message); + } + + public NosuchSubscriptionException() { + this("존재하지 않는 구독 정보입니다."); + } +} From 2dbdce56daa227c1c13005fa9d72ea3bb725e01f Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 00:12:57 +0900 Subject: [PATCH 0193/1011] =?UTF-8?q?feat:=20Category=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/category/service/CategoryService.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index 04029bda..b6a8d8d9 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -4,6 +4,7 @@ import com.allog.dallog.category.domain.CategoryRepository; import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; +import com.allog.dallog.category.exception.NoSuchCategoryException; import java.util.List; import java.util.stream.Collectors; import org.springframework.data.domain.Pageable; @@ -33,4 +34,13 @@ public List findAll(final Pageable pageable) { .map(CategoryResponse::new) .collect(Collectors.toList()); } + + public CategoryResponse findById(final Long id) { + return new CategoryResponse(getCategory(id)); + } + + public Category getCategory(final Long id) { + return categoryRepository.findById(id) + .orElseThrow(NoSuchCategoryException::new); + } } From 9c3d94af7008a38927286b3cdff0a896c3ea8638 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 00:10:08 +0900 Subject: [PATCH 0194/1011] =?UTF-8?q?feat:=20category=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=EC=8B=9C=20=EB=A6=AC=EC=86=8C=EC=8A=A4=20=EA=B0=92=20?= =?UTF-8?q?=EC=A0=84=EB=8B=AC=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/category/controller/CategoryController.java | 5 +++-- .../dallog/category/dto/response/CategoryResponse.java | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index 9f70c71e..2c00fceb 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -26,9 +26,10 @@ public CategoryController(final CategoryService categoryService) { } @PostMapping - public ResponseEntity save(@Valid @RequestBody final CategoryCreateRequest request) { + public ResponseEntity save(@Valid @RequestBody final CategoryCreateRequest request) { Long id = categoryService.save(request); - return ResponseEntity.created(URI.create("/api/categories/" + id)).build(); + CategoryResponse categoryResponse = categoryService.findById(id); + return ResponseEntity.created(URI.create("/api/categories/" + id)).body(categoryResponse); } @GetMapping diff --git a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java index f8cf1b8c..cb0dbb18 100644 --- a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java +++ b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java @@ -5,9 +5,12 @@ public class CategoryResponse { - private final Long id; - private final String name; - private final LocalDateTime createdAt; + private Long id; + private String name; + private LocalDateTime createdAt; + + private CategoryResponse() { + } public CategoryResponse(final Category category) { this(category.getId(), category.getName(), category.getCreatedAt()); From 2b4a192b407f1d4ccd6ecb5e0612ed0131d1869a Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 00:10:51 +0900 Subject: [PATCH 0195/1011] =?UTF-8?q?feat:=20subscription=20=EC=A1=B0?= =?UTF-8?q?=EC=9E=91=EC=9D=84=20=EC=9C=84=ED=95=9C=20Repository,=20Service?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/member/service/MemberService.java | 8 ++-- .../request/SubscriptionCreateRequest.java | 17 +++++++ .../dto/response/SubscriptionResponse.java | 36 +++++++++++++++ .../repository/SubscriptionRepository.java | 7 +++ .../service/SubscriptionService.java | 45 +++++++++++++++++++ 5 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/subscription/dto/request/SubscriptionCreateRequest.java create mode 100644 backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionResponse.java create mode 100644 backend/src/main/java/com/allog/dallog/subscription/repository/SubscriptionRepository.java create mode 100644 backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java diff --git a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java index 441d5194..7965897f 100644 --- a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java +++ b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java @@ -23,10 +23,12 @@ public Member save(final Member member) { } public MemberResponse findById(final Long id) { - Member member = memberRepository.findById(id) - .orElseThrow(NoSuchMemberException::new); + return new MemberResponse(getMember(id)); + } - return new MemberResponse(member); + public Member getMember(final Long id) { + return memberRepository.findById(id) + .orElseThrow(NoSuchMemberException::new); } public Member findByEmail(final String email) { diff --git a/backend/src/main/java/com/allog/dallog/subscription/dto/request/SubscriptionCreateRequest.java b/backend/src/main/java/com/allog/dallog/subscription/dto/request/SubscriptionCreateRequest.java new file mode 100644 index 00000000..316d8b3e --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/subscription/dto/request/SubscriptionCreateRequest.java @@ -0,0 +1,17 @@ +package com.allog.dallog.subscription.dto.request; + +public class SubscriptionCreateRequest { + + private String color; + + private SubscriptionCreateRequest() { + } + + public SubscriptionCreateRequest(final String color) { + this.color = color; + } + + public String getColor() { + return color; + } +} diff --git a/backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionResponse.java b/backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionResponse.java new file mode 100644 index 00000000..0c67b43d --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionResponse.java @@ -0,0 +1,36 @@ +package com.allog.dallog.subscription.dto.response; + +import com.allog.dallog.category.dto.response.CategoryResponse; +import com.allog.dallog.subscription.domain.Subscription; + +public class SubscriptionResponse { + + private Long id; + private CategoryResponse category; + private String color; + + private SubscriptionResponse() { + } + + public SubscriptionResponse(final Subscription subscription) { + this(subscription.getId(), new CategoryResponse(subscription.getCategory()), subscription.getColor()); + } + + public SubscriptionResponse(final Long id, final CategoryResponse category, final String color) { + this.id = id; + this.category = category; + this.color = color; + } + + public Long getId() { + return id; + } + + public CategoryResponse getCategory() { + return category; + } + + public String getColor() { + return color; + } +} diff --git a/backend/src/main/java/com/allog/dallog/subscription/repository/SubscriptionRepository.java b/backend/src/main/java/com/allog/dallog/subscription/repository/SubscriptionRepository.java new file mode 100644 index 00000000..4c554597 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/subscription/repository/SubscriptionRepository.java @@ -0,0 +1,7 @@ +package com.allog.dallog.subscription.repository; + +import com.allog.dallog.subscription.domain.Subscription; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface SubscriptionRepository extends JpaRepository { +} diff --git a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java b/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java new file mode 100644 index 00000000..c7a02b0a --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java @@ -0,0 +1,45 @@ +package com.allog.dallog.subscription.service; + +import com.allog.dallog.category.domain.Category; +import com.allog.dallog.category.service.CategoryService; +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.service.MemberService; +import com.allog.dallog.subscription.domain.Subscription; +import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; +import com.allog.dallog.subscription.dto.response.SubscriptionResponse; +import com.allog.dallog.subscription.exception.NosuchSubscriptionException; +import com.allog.dallog.subscription.repository.SubscriptionRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Transactional(readOnly = true) +@Service +public class SubscriptionService { + + private final SubscriptionRepository subscriptionRepository; + private final MemberService memberService; + private final CategoryService categoryService; + + public SubscriptionService(final SubscriptionRepository subscriptionRepository, final MemberService memberService, + final CategoryService categoryService) { + this.subscriptionRepository = subscriptionRepository; + this.memberService = memberService; + this.categoryService = categoryService; + } + + @Transactional + public Long save(final Long memberId, final Long categoryId, final SubscriptionCreateRequest request) { + Member member = memberService.getMember(memberId); + Category category = categoryService.getCategory(categoryId); + + Subscription subscription = subscriptionRepository.save(new Subscription(member, category, request.getColor())); + return subscription.getId(); + } + + public SubscriptionResponse findById(final Long id) { + Subscription subscription = subscriptionRepository.findById(id) + .orElseThrow(NosuchSubscriptionException::new); + + return new SubscriptionResponse(subscription); + } +} From 5bdf699c1d51ee26ab14b0b9c9501146e3fe2b6b Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 00:11:16 +0900 Subject: [PATCH 0196/1011] =?UTF-8?q?test:=20subscription=20=EC=9D=B8?= =?UTF-8?q?=EC=88=98=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SubscriptionController.java | 33 +++++++++ .../SubscriptionAcceptanceTest.java | 71 +++++++++++++++++++ .../common/fixtures/SubscriptionFixtures.java | 6 ++ 3 files changed, 110 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java create mode 100644 backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java create mode 100644 backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java diff --git a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java new file mode 100644 index 00000000..97d28eeb --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java @@ -0,0 +1,33 @@ +package com.allog.dallog.subscription.controller; + +import com.allog.dallog.auth.dto.LoginMember; +import com.allog.dallog.auth.support.AuthenticationPrincipal; +import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; +import com.allog.dallog.subscription.dto.response.SubscriptionResponse; +import com.allog.dallog.subscription.service.SubscriptionService; +import java.net.URI; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class SubscriptionController { + + private final SubscriptionService subscriptionService; + + public SubscriptionController(final SubscriptionService subscriptionService) { + this.subscriptionService = subscriptionService; + } + + @PostMapping("/api/members/me/categories/{categoryId}/subscriptions") + public ResponseEntity save(@AuthenticationPrincipal final LoginMember loginMember, + @PathVariable final Long categoryId, + @RequestBody final SubscriptionCreateRequest request) { + Long id = subscriptionService.save(loginMember.getId(), categoryId, request); + SubscriptionResponse subscriptionResponse = subscriptionService.findById(id); + return ResponseEntity.created( + URI.create("/api/members/me/" + categoryId + "/subscriptions/" + id)).body(subscriptionResponse); + } +} diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java new file mode 100644 index 00000000..6e6baf68 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java @@ -0,0 +1,71 @@ +package com.allog.dallog.acceptance; + +import com.allog.dallog.auth.dto.TokenRequest; +import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.dto.response.CategoryResponse; +import com.allog.dallog.common.config.TestConfig; +import com.allog.dallog.common.fixtures.OAuthMemberFixtures; +import com.allog.dallog.fixture.SubscriptionFixtures; +import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +@DisplayName("구독 관련 기능") +@Import(TestConfig.class) +public class SubscriptionAcceptanceTest extends AcceptanceTest { + + @DisplayName("인증된 회원이 카테고리를 구독하면 201을 반환한다.") + @Test + void 인증된_회원이_카테고리를_구독하면_201을_반환한다() { + // given + TokenResponse tokenResponse = 자체_토큰을_생성한다(OAuthMemberFixtures.OAUTH_PROVIDER, OAuthMemberFixtures.CODE); + CategoryResponse categoryResponse = 새로운_카테고리를_등록한다("BE 공식일정"); + + // when + ExtractableResponse response = 카테고리를_구독한다(tokenResponse, categoryResponse); + + // then + 상태코드_201이_반환된다(response); + } + + private TokenResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { + return RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(new TokenRequest(code)) + .when().post("/api/auth/{oauthProvider}/token", oauthProvider) + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract() + .as(TokenResponse.class); + } + + private CategoryResponse 새로운_카테고리를_등록한다(final String name) { + CategoryCreateRequest request = new CategoryCreateRequest(name); + return RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(request) + .when().post("/api/categories") + .then().log().all() + .extract() + .as(CategoryResponse.class); + } + + private ExtractableResponse 카테고리를_구독한다(final TokenResponse tokenResponse, + final CategoryResponse categoryResponse) { + return RestAssured.given().log().all() + .auth().oauth2(tokenResponse.getAccessToken()) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(new SubscriptionCreateRequest(SubscriptionFixtures.COLOR)) + .when().post("/api/members/me/categories/{categoryId}/subscriptions", categoryResponse.getId()) + .then().log().all() + .statusCode(HttpStatus.CREATED.value()) + .extract(); + } +} diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java new file mode 100644 index 00000000..ba5bdfb0 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java @@ -0,0 +1,6 @@ +package com.allog.dallog.fixture; + +public class SubscriptionFixtures { + + public static final String COLOR = "#ffffff"; +} From 52176a8b9f75a443826aff4544da37ad6f3ac074 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 00:45:35 +0900 Subject: [PATCH 0197/1011] =?UTF-8?q?test:=20SubscriptionService=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/service/CategoryServiceTest.java | 2 - .../service/SubscriptionServiceTest.java | 92 +++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 5159df3d..52b0d0b1 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -15,10 +15,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.PageRequest; -import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.annotation.Transactional; -@ActiveProfiles("test") @Transactional @SpringBootTest class CategoryServiceTest { diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java new file mode 100644 index 00000000..c70de74f --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -0,0 +1,92 @@ +package com.allog.dallog.subscription.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertAll; + +import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.service.CategoryService; +import com.allog.dallog.common.fixtures.MemberFixtures; +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.service.MemberService; +import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; +import com.allog.dallog.subscription.dto.response.SubscriptionResponse; +import com.allog.dallog.subscription.exception.InvalidSubscriptionException; +import com.allog.dallog.subscription.exception.NosuchSubscriptionException; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +@SpringBootTest +class SubscriptionServiceTest { + + @Autowired + private MemberService memberService; + + @Autowired + private CategoryService categoryService; + + @Autowired + private SubscriptionService subscriptionService; + + @DisplayName("새로운 구독을 생성한다.") + @Test + void 새로운_구독을_생성한다() { + // given + Member member = memberService.save(MemberFixtures.MEMBER); + Long categoryId = categoryService.save(new CategoryCreateRequest("BE 일정")); + String color = "#ffffff"; + + // when + Long id = subscriptionService.save(member.getId(), categoryId, new SubscriptionCreateRequest(color)); + + // then + assertThat(id).isNotNull(); + } + + @DisplayName("색 정보 형식이 잘못된 경우 예외를 던진다.") + @ParameterizedTest + @ValueSource(strings = {"#111", "#1111", "#11111", "123456", "#**1234", "##12345", "334172#"}) + void 색_정보_형식이_잘못된_경우_예외를_던진다(final String color) { + // given + Member member = memberService.save(MemberFixtures.MEMBER); + Long categoryId = categoryService.save(new CategoryCreateRequest("BE 일정")); + + // when & then + assertThatThrownBy(() -> subscriptionService.save(member.getId(), categoryId, + new SubscriptionCreateRequest(color))).isInstanceOf(InvalidSubscriptionException.class); + } + + @DisplayName("구독 id를 기반으로 단건 조회한다.") + @Test + void 구독_id를_기반으로_단건_조회한다() { + // given + Member member = memberService.save(MemberFixtures.MEMBER); + Long categoryId = categoryService.save(new CategoryCreateRequest("BE 일정")); + String color = "#ffffff"; + Long id = subscriptionService.save(member.getId(), categoryId, new SubscriptionCreateRequest(color)); + + // when + SubscriptionResponse subscriptionResponse = subscriptionService.findById(id); + + // then + assertAll(() -> { + assertThat(subscriptionResponse.getId()).isEqualTo(id); + assertThat(subscriptionResponse.getCategory().getId()).isEqualTo(categoryId); + assertThat(subscriptionResponse.getColor()).isEqualTo(color); + }); + } + + @DisplayName("존재하지 않는 구독 정보인 경우 예외를 던진다.") + @Test + void 존재하지_않는_구독_정보인_경우_예외를_던진다() { + // given & when & then + assertThatThrownBy(() -> subscriptionService.findById(0L)) + .isInstanceOf(NosuchSubscriptionException.class); + } +} From 7ff376ef4d22e221a6152392328d9963ab932d33 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 10:27:00 +0900 Subject: [PATCH 0198/1011] =?UTF-8?q?chore:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/NoSuchSubscriptionException.java | 12 ++++++++++++ .../exception/NosuchSubscriptionException.java | 12 ------------ .../subscription/service/SubscriptionService.java | 4 ++-- .../service/SubscriptionServiceTest.java | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/subscription/exception/NoSuchSubscriptionException.java delete mode 100644 backend/src/main/java/com/allog/dallog/subscription/exception/NosuchSubscriptionException.java diff --git a/backend/src/main/java/com/allog/dallog/subscription/exception/NoSuchSubscriptionException.java b/backend/src/main/java/com/allog/dallog/subscription/exception/NoSuchSubscriptionException.java new file mode 100644 index 00000000..1fcc1b85 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/subscription/exception/NoSuchSubscriptionException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.subscription.exception; + +public class NoSuchSubscriptionException extends RuntimeException { + + public NoSuchSubscriptionException(final String message) { + super(message); + } + + public NoSuchSubscriptionException() { + this("존재하지 않는 구독 정보입니다."); + } +} diff --git a/backend/src/main/java/com/allog/dallog/subscription/exception/NosuchSubscriptionException.java b/backend/src/main/java/com/allog/dallog/subscription/exception/NosuchSubscriptionException.java deleted file mode 100644 index a07381b8..00000000 --- a/backend/src/main/java/com/allog/dallog/subscription/exception/NosuchSubscriptionException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.allog.dallog.subscription.exception; - -public class NosuchSubscriptionException extends RuntimeException { - - public NosuchSubscriptionException(final String message) { - super(message); - } - - public NosuchSubscriptionException() { - this("존재하지 않는 구독 정보입니다."); - } -} diff --git a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java b/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java index c7a02b0a..90dcaf1e 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java +++ b/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java @@ -7,7 +7,7 @@ import com.allog.dallog.subscription.domain.Subscription; import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; import com.allog.dallog.subscription.dto.response.SubscriptionResponse; -import com.allog.dallog.subscription.exception.NosuchSubscriptionException; +import com.allog.dallog.subscription.exception.NoSuchSubscriptionException; import com.allog.dallog.subscription.repository.SubscriptionRepository; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -38,7 +38,7 @@ public Long save(final Long memberId, final Long categoryId, final SubscriptionC public SubscriptionResponse findById(final Long id) { Subscription subscription = subscriptionRepository.findById(id) - .orElseThrow(NosuchSubscriptionException::new); + .orElseThrow(NoSuchSubscriptionException::new); return new SubscriptionResponse(subscription); } diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java index c70de74f..1248e5f9 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -12,7 +12,7 @@ import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; import com.allog.dallog.subscription.dto.response.SubscriptionResponse; import com.allog.dallog.subscription.exception.InvalidSubscriptionException; -import com.allog.dallog.subscription.exception.NosuchSubscriptionException; +import com.allog.dallog.subscription.exception.NoSuchSubscriptionException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -87,6 +87,6 @@ class SubscriptionServiceTest { void 존재하지_않는_구독_정보인_경우_예외를_던진다() { // given & when & then assertThatThrownBy(() -> subscriptionService.findById(0L)) - .isInstanceOf(NosuchSubscriptionException.class); + .isInstanceOf(NoSuchSubscriptionException.class); } } From 2c63fb2fd8cd5993c1692a077cc8a5840bf80dda Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 10:41:32 +0900 Subject: [PATCH 0199/1011] =?UTF-8?q?chore:=20Category=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=A1=9C=EC=A7=81=20=EC=A1=B0=ED=9A=8C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/controller/CategoryController.java | 5 ++--- .../category/service/CategoryService.java | 4 ++-- .../category/service/CategoryServiceTest.java | 4 ++-- .../service/SubscriptionServiceTest.java | 17 ++++++++++------- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index 2c00fceb..1a9ee089 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -27,9 +27,8 @@ public CategoryController(final CategoryService categoryService) { @PostMapping public ResponseEntity save(@Valid @RequestBody final CategoryCreateRequest request) { - Long id = categoryService.save(request); - CategoryResponse categoryResponse = categoryService.findById(id); - return ResponseEntity.created(URI.create("/api/categories/" + id)).body(categoryResponse); + CategoryResponse categoryResponse = categoryService.save(request); + return ResponseEntity.created(URI.create("/api/categories/" + categoryResponse.getId())).body(categoryResponse); } @GetMapping diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index b6a8d8d9..305dc92a 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -22,9 +22,9 @@ public CategoryService(final CategoryRepository categoryRepository) { } @Transactional - public Long save(final CategoryCreateRequest request) { + public CategoryResponse save(final CategoryCreateRequest request) { Category category = categoryRepository.save(request.toEntity()); - return category.getId(); + return new CategoryResponse(category); } public List findAll(final Pageable pageable) { diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 52b0d0b1..bc52061f 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -32,10 +32,10 @@ class CategoryServiceTest { CategoryCreateRequest request = new CategoryCreateRequest(name); // when - Long id = categoryService.save(request); + CategoryResponse response = categoryService.save(request); // then - assertThat(id).isNotNull(); + assertThat(response.getName()).isEqualTo(name); } @DisplayName("새로운 카테고리를 생성 할 떄 이름이 공백이거나 길이가 20을 초과하는 경우 예외를 던진다.") diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java index 1248e5f9..c6d9b64f 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; import com.allog.dallog.common.fixtures.MemberFixtures; import com.allog.dallog.member.domain.Member; @@ -39,11 +40,12 @@ class SubscriptionServiceTest { void 새로운_구독을_생성한다() { // given Member member = memberService.save(MemberFixtures.MEMBER); - Long categoryId = categoryService.save(new CategoryCreateRequest("BE 일정")); + CategoryResponse categoryResponse = categoryService.save(new CategoryCreateRequest("BE 일정")); String color = "#ffffff"; // when - Long id = subscriptionService.save(member.getId(), categoryId, new SubscriptionCreateRequest(color)); + Long id = subscriptionService.save(member.getId(), categoryResponse.getId(), + new SubscriptionCreateRequest(color)); // then assertThat(id).isNotNull(); @@ -55,10 +57,10 @@ class SubscriptionServiceTest { void 색_정보_형식이_잘못된_경우_예외를_던진다(final String color) { // given Member member = memberService.save(MemberFixtures.MEMBER); - Long categoryId = categoryService.save(new CategoryCreateRequest("BE 일정")); + CategoryResponse categoryResponse = categoryService.save(new CategoryCreateRequest("BE 일정")); // when & then - assertThatThrownBy(() -> subscriptionService.save(member.getId(), categoryId, + assertThatThrownBy(() -> subscriptionService.save(member.getId(), categoryResponse.getId(), new SubscriptionCreateRequest(color))).isInstanceOf(InvalidSubscriptionException.class); } @@ -67,9 +69,10 @@ class SubscriptionServiceTest { void 구독_id를_기반으로_단건_조회한다() { // given Member member = memberService.save(MemberFixtures.MEMBER); - Long categoryId = categoryService.save(new CategoryCreateRequest("BE 일정")); + CategoryResponse categoryResponse = categoryService.save(new CategoryCreateRequest("BE 일정")); String color = "#ffffff"; - Long id = subscriptionService.save(member.getId(), categoryId, new SubscriptionCreateRequest(color)); + Long id = subscriptionService.save(member.getId(), categoryResponse.getId(), + new SubscriptionCreateRequest(color)); // when SubscriptionResponse subscriptionResponse = subscriptionService.findById(id); @@ -77,7 +80,7 @@ class SubscriptionServiceTest { // then assertAll(() -> { assertThat(subscriptionResponse.getId()).isEqualTo(id); - assertThat(subscriptionResponse.getCategory().getId()).isEqualTo(categoryId); + assertThat(subscriptionResponse.getCategory().getId()).isEqualTo(categoryResponse.getId()); assertThat(subscriptionResponse.getColor()).isEqualTo(color); }); } From 94a105983fc442478d6e08cd906a694dce3b563c Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 10:47:09 +0900 Subject: [PATCH 0200/1011] =?UTF-8?q?chore:=20Subscription=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=20=EC=A1=B0=ED=9A=8C=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SubscriptionController.java | 7 ++++--- .../subscription/service/SubscriptionService.java | 6 ++++-- .../service/SubscriptionServiceTest.java | 15 ++++++++------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java index 97d28eeb..f0f27f73 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java +++ b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java @@ -25,9 +25,10 @@ public SubscriptionController(final SubscriptionService subscriptionService) { public ResponseEntity save(@AuthenticationPrincipal final LoginMember loginMember, @PathVariable final Long categoryId, @RequestBody final SubscriptionCreateRequest request) { - Long id = subscriptionService.save(loginMember.getId(), categoryId, request); - SubscriptionResponse subscriptionResponse = subscriptionService.findById(id); + SubscriptionResponse response = subscriptionService.save(loginMember.getId(), categoryId, request); + SubscriptionResponse subscriptionResponse = subscriptionService.findById(response.getId()); return ResponseEntity.created( - URI.create("/api/members/me/" + categoryId + "/subscriptions/" + id)).body(subscriptionResponse); + URI.create("/api/members/me/" + categoryId + "/subscriptions/" + response.getId())) + .body(subscriptionResponse); } } diff --git a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java b/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java index 90dcaf1e..0d834b79 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java +++ b/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java @@ -28,12 +28,14 @@ public SubscriptionService(final SubscriptionRepository subscriptionRepository, } @Transactional - public Long save(final Long memberId, final Long categoryId, final SubscriptionCreateRequest request) { + public SubscriptionResponse save(final Long memberId, final Long categoryId, + final SubscriptionCreateRequest request) { Member member = memberService.getMember(memberId); Category category = categoryService.getCategory(categoryId); Subscription subscription = subscriptionRepository.save(new Subscription(member, category, request.getColor())); - return subscription.getId(); + + return new SubscriptionResponse(subscription); } public SubscriptionResponse findById(final Long id) { diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java index c6d9b64f..3f3ad087 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -44,11 +44,12 @@ class SubscriptionServiceTest { String color = "#ffffff"; // when - Long id = subscriptionService.save(member.getId(), categoryResponse.getId(), + SubscriptionResponse response = subscriptionService.save(member.getId(), categoryResponse.getId(), new SubscriptionCreateRequest(color)); // then - assertThat(id).isNotNull(); + assertThat(response.getCategory().getName()).isEqualTo("BE 일정"); + assertThat(response.getColor()).isEqualTo(color); } @DisplayName("색 정보 형식이 잘못된 경우 예외를 던진다.") @@ -71,17 +72,17 @@ class SubscriptionServiceTest { Member member = memberService.save(MemberFixtures.MEMBER); CategoryResponse categoryResponse = categoryService.save(new CategoryCreateRequest("BE 일정")); String color = "#ffffff"; - Long id = subscriptionService.save(member.getId(), categoryResponse.getId(), + SubscriptionResponse subscriptionResponse = subscriptionService.save(member.getId(), categoryResponse.getId(), new SubscriptionCreateRequest(color)); // when - SubscriptionResponse subscriptionResponse = subscriptionService.findById(id); + SubscriptionResponse foundResponse = subscriptionService.findById(subscriptionResponse.getId()); // then assertAll(() -> { - assertThat(subscriptionResponse.getId()).isEqualTo(id); - assertThat(subscriptionResponse.getCategory().getId()).isEqualTo(categoryResponse.getId()); - assertThat(subscriptionResponse.getColor()).isEqualTo(color); + assertThat(foundResponse.getId()).isEqualTo(subscriptionResponse.getId()); + assertThat(foundResponse.getCategory().getId()).isEqualTo(categoryResponse.getId()); + assertThat(foundResponse.getColor()).isEqualTo(color); }); } From a5894b8ce9b5c58fa65c1b3cfc71c15368260f07 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 10:49:31 +0900 Subject: [PATCH 0201/1011] =?UTF-8?q?fix:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EB=B3=80=EC=88=98=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subscription/controller/SubscriptionController.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java index f0f27f73..56a4d338 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java +++ b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java @@ -26,9 +26,7 @@ public ResponseEntity save(@AuthenticationPrincipal final @PathVariable final Long categoryId, @RequestBody final SubscriptionCreateRequest request) { SubscriptionResponse response = subscriptionService.save(loginMember.getId(), categoryId, request); - SubscriptionResponse subscriptionResponse = subscriptionService.findById(response.getId()); return ResponseEntity.created( - URI.create("/api/members/me/" + categoryId + "/subscriptions/" + response.getId())) - .body(subscriptionResponse); + URI.create("/api/members/me/" + categoryId + "/subscriptions/" + response.getId())).body(response); } } From e392f780e2824355606daffea84b6a603b9ba7f2 Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 19 Jul 2022 15:13:02 +0900 Subject: [PATCH 0202/1011] =?UTF-8?q?feat:=20OAuthUriResponse=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Endpoint 워딩을 Uri 로 통일하여 변경 --- .../auth/controller/AuthController.java | 8 +++-- .../dallog/auth/dto/OAuthUriResponse.java | 18 +++++++++++ .../dallog/auth/service/AuthService.java | 10 +++--- .../{OAuthEndpoint.java => OAuthUri.java} | 2 +- .../GoogleOAuthUri.java} | 10 +++--- .../dallog/acceptance/AuthAcceptanceTest.java | 31 +++++++++++++++++-- 6 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/auth/dto/OAuthUriResponse.java rename backend/src/main/java/com/allog/dallog/auth/support/{OAuthEndpoint.java => OAuthUri.java} (72%) rename backend/src/main/java/com/allog/dallog/infrastructure/oauth/{endpoint/GoogleOAuthEndpoint.java => uri/GoogleOAuthUri.java} (71%) diff --git a/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java b/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java index 42516873..1e204643 100644 --- a/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java +++ b/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java @@ -1,5 +1,6 @@ package com.allog.dallog.auth.controller; +import com.allog.dallog.auth.dto.OAuthUriResponse; import com.allog.dallog.auth.dto.TokenRequest; import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.auth.service.AuthService; @@ -21,9 +22,10 @@ public AuthController(final AuthService authService) { this.authService = authService; } - @GetMapping("/{oauthProvider}/link") - public ResponseEntity generateLink(@PathVariable final String oauthProvider) { - return ResponseEntity.ok(authService.generateGoogleLink()); + @GetMapping("/{oauthProvider}/oauth-uri") + public ResponseEntity generateLink(@PathVariable final String oauthProvider) { + OAuthUriResponse oAuthUriResponse = new OAuthUriResponse(authService.generateGoogleLink()); + return ResponseEntity.ok(oAuthUriResponse); } @PostMapping("/{oauthProvider}/token") diff --git a/backend/src/main/java/com/allog/dallog/auth/dto/OAuthUriResponse.java b/backend/src/main/java/com/allog/dallog/auth/dto/OAuthUriResponse.java new file mode 100644 index 00000000..c318507e --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/dto/OAuthUriResponse.java @@ -0,0 +1,18 @@ +package com.allog.dallog.auth.dto; + +// OAuth 인증 URI(소셜 로그인 링크)를 전달하는 DTO +public class OAuthUriResponse { + + private String oAuthUri; + + private OAuthUriResponse() { + } + + public OAuthUriResponse(final String oAuthUri) { + this.oAuthUri = oAuthUri; + } + + public String getoAuthUri() { + return oAuthUri; + } +} diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index 0967961b..358325d8 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -4,7 +4,7 @@ import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.auth.support.JwtTokenProvider; import com.allog.dallog.auth.support.OAuthClient; -import com.allog.dallog.auth.support.OAuthEndpoint; +import com.allog.dallog.auth.support.OAuthUri; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.SocialType; import com.allog.dallog.member.service.MemberService; @@ -15,21 +15,21 @@ @Service public class AuthService { - private final OAuthEndpoint oAuthEndpoint; + private final OAuthUri oAuthUri; private final OAuthClient oAuthClient; private final MemberService memberService; private final JwtTokenProvider jwtTokenProvider; - public AuthService(final OAuthEndpoint oAuthEndpoint, final OAuthClient oAuthClient, + public AuthService(final OAuthUri oAuthUri, final OAuthClient oAuthClient, final MemberService memberService, final JwtTokenProvider jwtTokenProvider) { - this.oAuthEndpoint = oAuthEndpoint; + this.oAuthUri = oAuthUri; this.oAuthClient = oAuthClient; this.memberService = memberService; this.jwtTokenProvider = jwtTokenProvider; } public String generateGoogleLink() { - return oAuthEndpoint.generate(); + return oAuthUri.generate(); } @Transactional diff --git a/backend/src/main/java/com/allog/dallog/auth/support/OAuthEndpoint.java b/backend/src/main/java/com/allog/dallog/auth/support/OAuthUri.java similarity index 72% rename from backend/src/main/java/com/allog/dallog/auth/support/OAuthEndpoint.java rename to backend/src/main/java/com/allog/dallog/auth/support/OAuthUri.java index cc24bc08..769c99d8 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/OAuthEndpoint.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/OAuthUri.java @@ -1,7 +1,7 @@ package com.allog.dallog.auth.support; @FunctionalInterface -public interface OAuthEndpoint { +public interface OAuthUri { String generate(); } diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/GoogleOAuthEndpoint.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java similarity index 71% rename from backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/GoogleOAuthEndpoint.java rename to backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java index 32ed4491..5748d04c 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/endpoint/GoogleOAuthEndpoint.java +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java @@ -1,12 +1,12 @@ -package com.allog.dallog.infrastructure.oauth.endpoint; +package com.allog.dallog.infrastructure.oauth.uri; -import com.allog.dallog.auth.support.OAuthEndpoint; +import com.allog.dallog.auth.support.OAuthUri; import java.util.List; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component -public class GoogleOAuthEndpoint implements OAuthEndpoint { +public class GoogleOAuthUri implements OAuthUri { private static final String GOOGLE_OAUTH_END_POINT = "https://accounts.google.com/o/oauth2/v2/auth"; private static final List SCOPES = List.of("https://www.googleapis.com/auth/userinfo.profile", @@ -15,8 +15,8 @@ public class GoogleOAuthEndpoint implements OAuthEndpoint { private final String googleRedirectUri; private final String googleClientId; - public GoogleOAuthEndpoint(@Value("${oauth.google.redirect_uri}") final String googleRedirectUri, - @Value("${oauth.google.client_id}") final String googleClientId) { + public GoogleOAuthUri(@Value("${oauth.google.redirect_uri}") final String googleRedirectUri, + @Value("${oauth.google.client_id}") final String googleClientId) { this.googleRedirectUri = googleRedirectUri; this.googleClientId = googleClientId; } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java index b96bf20d..715de9a8 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java @@ -3,6 +3,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; +import com.allog.dallog.auth.dto.OAuthUriResponse; import com.allog.dallog.auth.dto.TokenRequest; import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.common.config.TestConfig; @@ -19,15 +20,32 @@ @Import(TestConfig.class) public class AuthAcceptanceTest extends AcceptanceTest { + @DisplayName("구글 OAuth 인증 URI를 생성하여 반환한다.") + @Test + void 구글_OAuth_인증_URI를_생성하여_반환한다() { + // given + String oAuthProvider = "google"; + + // when + ExtractableResponse response = OAuth_인증_URI를_생성한다(oAuthProvider); + OAuthUriResponse oAuthUriResponse = response.as(OAuthUriResponse.class); + + // then + assertAll(() -> { + 상태코드_200이_반환된다(response); + assertThat(oAuthUriResponse.getoAuthUri()).contains("https://"); + }); + } + @DisplayName("최초 사용자거나 기존에 존재하는 회원인 경우 200을 발급한다.") @Test void 최초_사용자거나_기존에_존재하는_회원인_경우_200을_발급한다() { // given - String oauthProvider = "google"; + String oAuthProvider = "google"; String code = "sddsfsg4wedfabladsgklvdskfngdakfjgnkd"; // when - ExtractableResponse response = 자체_토큰을_생성한다(oauthProvider, code); + ExtractableResponse response = 자체_토큰을_생성한다(oAuthProvider, code); TokenResponse tokenResponse = response.as(TokenResponse.class); // then @@ -37,6 +55,15 @@ public class AuthAcceptanceTest extends AcceptanceTest { }); } + private ExtractableResponse OAuth_인증_URI를_생성한다(final String oauthProvider) { + return RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when().get("/api/auth/{oauthProvider}/oauth-uri", oauthProvider) + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract(); + } + private ExtractableResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { return RestAssured.given().log().all() .contentType(MediaType.APPLICATION_JSON_VALUE) From 0fdad6752eeeee6ba9231e43c89eccaafa4ca405 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Mon, 18 Jul 2022 21:42:37 +0900 Subject: [PATCH 0203/1011] =?UTF-8?q?refactor:=20path=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.tsx | 4 ++-- frontend/src/constants/index.ts | 4 ++-- frontend/src/pages/CalendarPage/CalendarPage.tsx | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 8c44c85d..901afb2c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -11,8 +11,8 @@ function App() { return ( - } /> - } /> + } /> + } /> } /> } /> diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 6d424562..4d3a8fd6 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -15,10 +15,10 @@ const STORAGE_KEY = { }; const PATH = { - CALENDAR_PAGE: '/auth', + CALENDAR: '/', CATEGORY: '/category', - START_PAGE: '/start', PROFILE: '/profile', + START: '/start', }; const DAYS = ['일', '월', '화', '수', '목', '금', '토']; diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index a9015110..f1a46705 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -42,7 +42,7 @@ function CalendarPage() { const onSuccessAuth = (accessToken: string) => { localStorage.setItem(STORAGE_KEY.ACCESS_TOKEN, accessToken); - navigate(PATH.CALENDAR_PAGE); + navigate(PATH.CALENDAR); }; if (isLoading || schedulesGetResponse === undefined) { From 1235120d5bb0d5f41015a08a8ea6157dd020e252 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Tue, 19 Jul 2022 15:12:23 +0900 Subject: [PATCH 0204/1011] =?UTF-8?q?style:=20=EA=B5=AC=EA=B8=80=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=B2=84=ED=8A=BC=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LoginModal/LoginModal.styles.ts | 20 ++++++++++++++++--- .../src/components/LoginModal/LoginModal.tsx | 8 +++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/LoginModal/LoginModal.styles.ts b/frontend/src/components/LoginModal/LoginModal.styles.ts index b8e98eed..1124d855 100644 --- a/frontend/src/components/LoginModal/LoginModal.styles.ts +++ b/frontend/src/components/LoginModal/LoginModal.styles.ts @@ -23,10 +23,15 @@ const content = ({ flex }: Theme) => css` height: 100%; `; -const googleLoginButton = ({ colors }: Theme) => css` +const loginButton = ({ colors, flex }: Theme) => css` + ${flex.row} + + position: relative; + justify-content: flex-start; + width: 75rem; height: 15rem; - padding: 2rem; + padding: 4rem; border: 1px solid ${colors.GRAY_400}; border-radius: 8px; box-shadow: 2px 2px 2px ${colors.GRAY_400}; @@ -41,4 +46,13 @@ const googleLoginButton = ({ colors }: Theme) => css` } `; -export { content, googleLoginButton, loginModal, title }; +const loginText = css` + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + + width: 100%; +`; + +export { content, loginButton, loginModal, loginText, title }; diff --git a/frontend/src/components/LoginModal/LoginModal.tsx b/frontend/src/components/LoginModal/LoginModal.tsx index b4c8818f..3f9b94c0 100644 --- a/frontend/src/components/LoginModal/LoginModal.tsx +++ b/frontend/src/components/LoginModal/LoginModal.tsx @@ -1,4 +1,5 @@ import { useTheme } from '@emotion/react'; +import { FcGoogle } from 'react-icons/fc'; import { useQuery } from 'react-query'; import Button from '@/components/@common/Button/Button'; @@ -7,7 +8,7 @@ import { CACHE_KEY } from '@/constants'; import loginApi from '@/api/login'; -import { content, googleLoginButton, loginModal, title } from './LoginModal.styles'; +import { content, loginButton, loginModal, loginText, title } from './LoginModal.styles'; function LoginModal() { const theme = useTheme(); @@ -37,8 +38,9 @@ function LoginModal() {

로그인

-
From f646ee292daf40b295f33081279397bb2862306c Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 20 Jul 2022 08:50:03 +0900 Subject: [PATCH 0205/1011] =?UTF-8?q?chore:=20prettier=20import=20order?= =?UTF-8?q?=EC=97=90=20react-icons=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/.prettierrc.json | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json index 03007670..ea4f16de 100644 --- a/frontend/.prettierrc.json +++ b/frontend/.prettierrc.json @@ -17,6 +17,7 @@ "@/constants", "@/utils", "@/(api|mocks)/(.*)$", + "react-icons", "^[./]" ], "importOrderSeparation": true, From 4b9aa0a722c35d7ae6fe134cf8d020aaa61f0a5c Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 20 Jul 2022 08:53:37 +0900 Subject: [PATCH 0206/1011] =?UTF-8?q?feat:=20=EC=86=8C=EC=85=9C=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=B2=84=ED=8A=BC=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LoginModal/LoginModal.styles.ts | 59 +++++++++++++++---- .../src/components/LoginModal/LoginModal.tsx | 35 +++++++++-- frontend/src/styles/theme.ts | 2 + 3 files changed, 79 insertions(+), 17 deletions(-) diff --git a/frontend/src/components/LoginModal/LoginModal.styles.ts b/frontend/src/components/LoginModal/LoginModal.styles.ts index 1124d855..4bfa7059 100644 --- a/frontend/src/components/LoginModal/LoginModal.styles.ts +++ b/frontend/src/components/LoginModal/LoginModal.styles.ts @@ -3,8 +3,8 @@ import { css, Theme } from '@emotion/react'; const loginModal = ({ colors, flex }: Theme) => css` ${flex.column} - width: 120rem; - height: 160rem; + width: 105rem; + height: 140rem; padding: 12.5rem; border-radius: 12px; @@ -20,6 +20,8 @@ const title = ({ colors }: Theme) => css` const content = ({ flex }: Theme) => css` ${flex.column} + gap: 3rem; + height: 100%; `; @@ -32,27 +34,60 @@ const loginButton = ({ colors, flex }: Theme) => css` width: 75rem; height: 15rem; padding: 4rem; - border: 1px solid ${colors.GRAY_400}; border-radius: 8px; box-shadow: 2px 2px 2px ${colors.GRAY_400}; - background: ${colors.WHITE}; - font-size: 4rem; - color: ${colors.BLACK}8a; + font-weight: 500; + color: ${colors.WHITE}; &:hover { box-shadow: 3px 3px 3px ${colors.GRAY_500}; } `; -const loginText = css` - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); +const googleLoginButton = ({ colors, flex }: Theme) => css` + ${loginButton({ colors, flex })} + + border: 1px solid ${colors.GRAY_400}; + + background: ${colors.WHITE}; + + color: ${colors.BLACK}8a; +`; +const naverLoginButton = ({ colors, flex }: Theme) => css` + ${loginButton({ colors, flex })} + + background: ${colors.GREEN_500}; +`; + +const kakaoLoginButton = ({ colors, flex }: Theme) => css` + ${loginButton({ colors, flex })} + + background: ${colors.YELLOW_400}; + + color: ${colors.BLACK}8a; +`; + +const githubLoginButton = ({ colors, flex }: Theme) => css` + ${loginButton({ colors, flex })} + + background: ${colors.BLACK}; +`; + +const loginText = css` width: 100%; `; -export { content, loginButton, loginModal, loginText, title }; +export { + content, + githubLoginButton, + googleLoginButton, + kakaoLoginButton, + loginButton, + loginModal, + loginText, + naverLoginButton, + title, +}; diff --git a/frontend/src/components/LoginModal/LoginModal.tsx b/frontend/src/components/LoginModal/LoginModal.tsx index 3f9b94c0..9333507d 100644 --- a/frontend/src/components/LoginModal/LoginModal.tsx +++ b/frontend/src/components/LoginModal/LoginModal.tsx @@ -1,5 +1,4 @@ import { useTheme } from '@emotion/react'; -import { FcGoogle } from 'react-icons/fc'; import { useQuery } from 'react-query'; import Button from '@/components/@common/Button/Button'; @@ -8,7 +7,21 @@ import { CACHE_KEY } from '@/constants'; import loginApi from '@/api/login'; -import { content, loginButton, loginModal, loginText, title } from './LoginModal.styles'; +import { FaGithub } from 'react-icons/fa'; +import { FcGoogle } from 'react-icons/fc'; +import { RiKakaoTalkFill } from 'react-icons/ri'; +import { SiNaver } from 'react-icons/si'; + +import { + content, + githubLoginButton, + googleLoginButton, + kakaoLoginButton, + loginModal, + loginText, + naverLoginButton, + title, +} from './LoginModal.styles'; function LoginModal() { const theme = useTheme(); @@ -38,9 +51,21 @@ function LoginModal() {

로그인

- + + +
diff --git a/frontend/src/styles/theme.ts b/frontend/src/styles/theme.ts index ff561ed4..602524a0 100644 --- a/frontend/src/styles/theme.ts +++ b/frontend/src/styles/theme.ts @@ -1,7 +1,9 @@ import { css, Theme } from '@emotion/react'; const colors = { + YELLOW_400: '#fee500', YELLOW_500: '#FCC419', + GREEN_500: '#03c75a', WHITE: '#ffffff', GRAY_000: '#f8f9fa', GRAY_100: '#f1f3f5', From 54d58c4023615d5e155946613f1763948f8bf721 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 20 Jul 2022 08:57:14 +0900 Subject: [PATCH 0207/1011] =?UTF-8?q?chore:=20recoil=20=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/package.json | 3 ++- frontend/yarn.lock | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/frontend/package.json b/frontend/package.json index c47c3acc..0d9c9d2c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -22,7 +22,8 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-query": "^3.39.1", - "react-router-dom": "^6.3.0" + "react-router-dom": "^6.3.0", + "recoil": "^0.7.4" }, "devDependencies": { "@babel/core": "^7.18.6", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 469a6a70..6d07b0c5 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -6559,6 +6559,11 @@ graphql@^16.3.0: resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.5.0.tgz#41b5c1182eaac7f3d47164fb247f61e4dfb69c85" integrity sha512-qbHgh8Ix+j/qY+a/ZcJnFQ+j8ezakqPiHwPiZhV/3PgGlgf96QMBB5/f2rkiC9sgLoy/xvT6TSiaf2nTHJh5iA== +hamt_plus@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/hamt_plus/-/hamt_plus-1.0.2.tgz#e21c252968c7e33b20f6a1b094cd85787a265601" + integrity sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA== + handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -9786,6 +9791,13 @@ rechoir@^0.7.0: dependencies: resolve "^1.9.0" +recoil@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/recoil/-/recoil-0.7.4.tgz#d6508fa656d9c93e66fdf334e1f723a9e98801cf" + integrity sha512-sCXvQGMfSprkNU4ZRkJV4B0qFQSURJMgsICqY1952WRlg66NMwYqi6n67vhnhn0qw4zHU1gHXJuMvRDaiRNFZw== + dependencies: + hamt_plus "1.0.2" + redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" From 61ad9fc4353d749dd206dc1dc679625ea54c4135 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 20 Jul 2022 12:10:01 +0900 Subject: [PATCH 0208/1011] =?UTF-8?q?feat:=20oauth=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20=EC=A0=84=EC=97=AD=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=20=EC=83=81=ED=83=9C=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/.prettierrc.json | 1 + frontend/src/App.tsx | 6 ++--- frontend/src/atoms/index.ts | 14 +++++++++++ frontend/src/constants/index.ts | 9 ++++--- frontend/src/index.tsx | 15 ++++++----- .../src/pages/CalendarPage/CalendarPage.tsx | 21 ++-------------- frontend/src/pages/MainPage/MainPage.tsx | 25 +++++++++++++++++++ frontend/src/utils/index.ts | 12 ++++++++- 8 files changed, 70 insertions(+), 33 deletions(-) create mode 100644 frontend/src/atoms/index.ts create mode 100644 frontend/src/pages/MainPage/MainPage.tsx diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json index ea4f16de..597ae9eb 100644 --- a/frontend/.prettierrc.json +++ b/frontend/.prettierrc.json @@ -12,6 +12,7 @@ "importOrder": [ "@/hooks/(.*)$", "@/@types", + "@/atoms", "@/styles/(.*)$", "@/(components/@common/|components/|pages/)(.*)$", "@/constants", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 901afb2c..f046e5d6 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,9 +1,8 @@ import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'; -import CalendarPage from '@/pages/CalendarPage/CalendarPage'; import CategoryPage from '@/pages/CategoryPage/CategoryPage'; +import MainPage from '@/pages/MainPage/MainPage'; import MyPage from '@/pages/MyPage/MyPage'; -import StartPage from '@/pages/StartPage/StartPage'; import { PATH } from '@/constants'; @@ -11,9 +10,8 @@ function App() { return ( - } /> - } /> } /> + } /> } /> diff --git a/frontend/src/atoms/index.ts b/frontend/src/atoms/index.ts new file mode 100644 index 00000000..ef31392f --- /dev/null +++ b/frontend/src/atoms/index.ts @@ -0,0 +1,14 @@ +import { atom } from 'recoil'; + +import { ATOM_KEY } from '@/constants'; + +import { getAccessToken } from '@/utils'; + +const userState = atom({ + key: ATOM_KEY.USER, + default: { + accessToken: getAccessToken(), + }, +}); + +export { userState }; diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 4d3a8fd6..d8febc94 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -2,6 +2,10 @@ const API = { CATEGORY_GET_SIZE: 4, }; +const ATOM_KEY = { + USER: 'userState', +}; + const CACHE_KEY = { AUTH: 'auth', CATEGORIES: 'categories', @@ -15,12 +19,11 @@ const STORAGE_KEY = { }; const PATH = { - CALENDAR: '/', + MAIN: '/', CATEGORY: '/category', PROFILE: '/profile', - START: '/start', }; const DAYS = ['일', '월', '화', '수', '목', '금', '토']; -export { API, CACHE_KEY, DAYS, STORAGE_KEY, PATH }; +export { API, ATOM_KEY, CACHE_KEY, DAYS, STORAGE_KEY, PATH }; diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 9c3b79e3..207939ff 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -1,6 +1,7 @@ import { ThemeProvider } from '@emotion/react'; import ReactDOM from 'react-dom'; import { QueryClient, QueryClientProvider } from 'react-query'; +import { RecoilRoot } from 'recoil'; import GlobalStyle from '@/styles/GlobalStyle'; import theme from '@/styles/theme'; @@ -17,11 +18,13 @@ const queryClient = new QueryClient(); const rootElement = document.getElementById('root'); ReactDOM.render( - - - - - - , + + + + + + + + , rootElement ); diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index f1a46705..7822474c 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -1,6 +1,5 @@ import { AxiosError, AxiosResponse } from 'axios'; import { useQuery } from 'react-query'; -import { useNavigate } from 'react-router-dom'; import useModal from '@/hooks/useModal'; @@ -12,19 +11,11 @@ import PageLayout from '@/components/PageLayout/PageLayout'; import ScheduleAddButton from '@/components/ScheduleAddButton/ScheduleAddButton'; import ScheduleAddModal from '@/components/ScheduleAddModal/ScheduleAddModal'; -import { CACHE_KEY, PATH, STORAGE_KEY } from '@/constants'; +import { CACHE_KEY } from '@/constants'; -import loginApi from '@/api/login'; import scheduleApi from '@/api/schedule'; function CalendarPage() { - const navigate = useNavigate(); - - const { data: accessToken } = useQuery(CACHE_KEY.AUTH, loginApi.auth, { - retry: false, - onSuccess: (data) => onSuccessAuth(data), - }); - const { isLoading, error, @@ -32,19 +23,11 @@ function CalendarPage() { refetch: refetchSchedules, } = useQuery, AxiosError>( CACHE_KEY.SCHEDULES, - scheduleApi.get, - { - enabled: !!accessToken, - } + scheduleApi.get ); const { isOpen, openModal, closeModal } = useModal(); - const onSuccessAuth = (accessToken: string) => { - localStorage.setItem(STORAGE_KEY.ACCESS_TOKEN, accessToken); - navigate(PATH.CALENDAR); - }; - if (isLoading || schedulesGetResponse === undefined) { return <>Loading; } diff --git a/frontend/src/pages/MainPage/MainPage.tsx b/frontend/src/pages/MainPage/MainPage.tsx new file mode 100644 index 00000000..cbe4810c --- /dev/null +++ b/frontend/src/pages/MainPage/MainPage.tsx @@ -0,0 +1,25 @@ +import { useEffect } from 'react'; +import { useRecoilState } from 'recoil'; + +import { userState } from '@/atoms'; + +import CalendarPage from '@/pages/CalendarPage/CalendarPage'; +import StartPage from '@/pages/StartPage/StartPage'; + +import { getAccessToken } from '@/utils'; + +function MainPage() { + const [user, setUser] = useRecoilState(userState); + + useEffect(() => { + setUser({ ...user, accessToken: getAccessToken() }); + }, []); + + if (!user.accessToken) { + return ; + } + + return ; +} + +export default MainPage; diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts index ad49d2e4..f1bd5666 100644 --- a/frontend/src/utils/index.ts +++ b/frontend/src/utils/index.ts @@ -1,5 +1,7 @@ import { InputRef } from '@/@types'; +import { STORAGE_KEY } from '@/constants'; + const createPostBody = (inputRef: InputRef) => { const inputElements = Object.values(inputRef).map((el) => el.current); const isValidInputRefs = inputElements.every((el) => el instanceof HTMLInputElement); @@ -19,4 +21,12 @@ const createPostBody = (inputRef: InputRef) => { return body; }; -export { createPostBody }; +const getAccessToken = () => { + return localStorage.getItem(STORAGE_KEY.ACCESS_TOKEN); +}; + +const setAccessToken = (accessToken: string) => { + localStorage.setItem(STORAGE_KEY.ACCESS_TOKEN, accessToken); +}; + +export { createPostBody, getAccessToken, setAccessToken }; From 81499cda64ccd549d7be4b77b143e29788025671 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 20 Jul 2022 12:32:11 +0900 Subject: [PATCH 0209/1011] =?UTF-8?q?feat:=20oauth=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.tsx | 4 ++- frontend/src/constants/index.ts | 1 + frontend/src/pages/AuthPage/AuthPage.tsx | 31 ++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 frontend/src/pages/AuthPage/AuthPage.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f046e5d6..f8f3311a 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,5 +1,6 @@ import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'; +import AuthPage from '@/pages/AuthPage/AuthPage'; import CategoryPage from '@/pages/CategoryPage/CategoryPage'; import MainPage from '@/pages/MainPage/MainPage'; import MyPage from '@/pages/MyPage/MyPage'; @@ -10,8 +11,9 @@ function App() { return ( - } /> } /> + } /> + } /> } /> diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index d8febc94..e6d1c356 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -20,6 +20,7 @@ const STORAGE_KEY = { const PATH = { MAIN: '/', + AUTH: '/oauth', CATEGORY: '/category', PROFILE: '/profile', }; diff --git a/frontend/src/pages/AuthPage/AuthPage.tsx b/frontend/src/pages/AuthPage/AuthPage.tsx new file mode 100644 index 00000000..f70d2444 --- /dev/null +++ b/frontend/src/pages/AuthPage/AuthPage.tsx @@ -0,0 +1,31 @@ +import { useEffect } from 'react'; +import { useQuery } from 'react-query'; +import { useNavigate } from 'react-router-dom'; + +import { CACHE_KEY, PATH } from '@/constants'; + +import { setAccessToken } from '@/utils'; + +import loginApi from '@/api/login'; + +function AuthPage() { + const navigate = useNavigate(); + + useQuery(CACHE_KEY.AUTH, loginApi.auth, { + onError: () => onErrorAuth(), + onSuccess: (data) => onSuccessAuth(data), + }); + + const onErrorAuth = () => { + navigate(PATH.MAIN); + }; + + const onSuccessAuth = (accessToken: string) => { + setAccessToken(accessToken); + navigate(PATH.MAIN); + }; + + return
; +} + +export default AuthPage; From 352cbd3c03d28549eb1fa495099bb5fa824d4ac6 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 20 Jul 2022 12:35:34 +0900 Subject: [PATCH 0210/1011] =?UTF-8?q?fix:=20=EA=B5=AC=EA=B8=80=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20api=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/login.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/frontend/src/api/login.ts b/frontend/src/api/login.ts index e599d622..4f966902 100644 --- a/frontend/src/api/login.ts +++ b/frontend/src/api/login.ts @@ -1,21 +1,25 @@ import axios from 'axios'; const loginApi = { - baseUrl: 'http://09d2-218-39-176-142.ngrok.io/api/auth/google', - entryEndpoint: '/link', - tokenEndpoint: '/token', + baseUrl: 'http://3.38.116.83:8080', + endPoint: { + googleEntry: '/api/auth/google/oauth-uri', + googleToken: '/api/auth/google/token', + }, getUrl: async () => { - const { data } = await axios.get(`${loginApi.baseUrl}${loginApi.entryEndpoint}`); + const { data } = await axios.get(`${loginApi.baseUrl}${loginApi.endPoint.googleEntry}`); - return data.data; + return data.oAuthUri; }, auth: async () => { const code = new URLSearchParams(location.search).get('code'); - const { data } = await axios.post(`${loginApi.baseUrl}${loginApi.tokenEndpoint}`, { code }); + const { data } = await axios.post(`${loginApi.baseUrl}${loginApi.endPoint.googleToken}`, { + code, + }); - return data.data.accessToken; + return data.accessToken; }, }; From ea083d4728b099d1e00bae9e6d11e6d7f0bf1f41 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 20 Jul 2022 12:44:28 +0900 Subject: [PATCH 0211/1011] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=EC=9E=90=EC=9A=A9=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EC=97=90=20=EB=B9=84=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=EC=9D=98=20=EC=A0=91=EA=B7=BC=20?= =?UTF-8?q?=EC=A0=9C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.tsx | 7 +++++-- frontend/src/components/ProtectRoute/index.tsx | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 frontend/src/components/ProtectRoute/index.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f8f3311a..02a17a34 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,5 +1,6 @@ import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'; +import ProtectRoute from '@/components/ProtectRoute'; import AuthPage from '@/pages/AuthPage/AuthPage'; import CategoryPage from '@/pages/CategoryPage/CategoryPage'; import MainPage from '@/pages/MainPage/MainPage'; @@ -13,8 +14,10 @@ function App() { } /> } /> - } /> - } /> + }> + } /> + } /> +
); diff --git a/frontend/src/components/ProtectRoute/index.tsx b/frontend/src/components/ProtectRoute/index.tsx new file mode 100644 index 00000000..ffb9d6c9 --- /dev/null +++ b/frontend/src/components/ProtectRoute/index.tsx @@ -0,0 +1,18 @@ +import { Navigate, Outlet } from 'react-router-dom'; +import { useRecoilState } from 'recoil'; + +import { userState } from '@/atoms'; + +import { PATH } from '@/constants'; + +function ProtectRoute() { + const [user] = useRecoilState(userState); + + if (!user.accessToken) { + return ; + } + + return ; +} + +export default ProtectRoute; From 3e6aa4bbcf1f003cfb102151dd3cdabaf8cccb83 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 20 Jul 2022 13:09:14 +0900 Subject: [PATCH 0212/1011] =?UTF-8?q?style:=20prettier=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Calendar/Calendar.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Calendar/Calendar.tsx b/frontend/src/components/Calendar/Calendar.tsx index bd989da2..1a9ce958 100644 --- a/frontend/src/components/Calendar/Calendar.tsx +++ b/frontend/src/components/Calendar/Calendar.tsx @@ -1,6 +1,5 @@ import { useTheme } from '@emotion/react'; import { useState } from 'react'; -import { AiOutlineLeft, AiOutlineRight } from 'react-icons/ai'; import CalendarDate from '@/components/CalendarDate/CalendarDate'; @@ -14,6 +13,8 @@ import { getThisYear, } from '@/utils/date'; +import { AiOutlineLeft, AiOutlineRight } from 'react-icons/ai'; + import Button from '../@common/Button/Button'; import { calendar, From 638800cd7477abbe730c2a5b95256a31cd59db6a Mon Sep 17 00:00:00 2001 From: koo Date: Wed, 20 Jul 2022 12:41:21 +0900 Subject: [PATCH 0213/1011] =?UTF-8?q?test:=20Category=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20fixture=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/acceptance/AcceptanceTest.java | 13 ----- .../dallog/acceptance/AuthAcceptanceTest.java | 1 + .../acceptance/CategoryAcceptanceTest.java | 50 ++++++------------- .../acceptance/MemberAcceptanceTest.java | 1 + .../acceptance/ScheduleAcceptanceTest.java | 2 + .../SubscriptionAcceptanceTest.java | 2 + .../fixtures/CategoryAcceptanceFixtures.java | 28 +++++++++++ .../domain/CategoryRepositoryTest.java | 29 ++++++----- .../category/service/CategoryServiceTest.java | 14 +++--- .../common/fixtures/CategoryFixtures.java | 3 ++ 10 files changed, 74 insertions(+), 69 deletions(-) create mode 100644 backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java index f5876d0f..18061103 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java @@ -1,14 +1,9 @@ package com.allog.dallog.acceptance; -import static org.assertj.core.api.Assertions.assertThat; - import io.restassured.RestAssured; -import io.restassured.response.ExtractableResponse; -import io.restassured.response.Response; import org.junit.jupiter.api.BeforeEach; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; -import org.springframework.http.HttpStatus; import org.springframework.test.annotation.DirtiesContext; @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @@ -22,12 +17,4 @@ class AcceptanceTest { void setUp() { RestAssured.port = port; } - - protected void 상태코드_200이_반환된다(ExtractableResponse response) { - assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); - } - - protected void 상태코드_201이_반환된다(ExtractableResponse response) { - assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); - } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java index 715de9a8..9f012dca 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java @@ -1,5 +1,6 @@ package com.allog.dallog.acceptance; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 3ae59c90..b5d272a3 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -1,16 +1,20 @@ package com.allog.dallog.acceptance; +import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.새로운_카테고리를_등록한다; +import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.카테고리를_페이징을_통해_조회한다; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; +import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; -import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoriesResponse; -import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.http.MediaType; @DisplayName("카테고리 관련 기능") public class CategoryAcceptanceTest extends AcceptanceTest { @@ -18,11 +22,8 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @DisplayName("정상적인 카테고리 정보를 등록하면 상태코드 201을 반환한다.") @Test void 정상적인_카테고리_정보를_등록하면_상태코드_201을_반환한다() { - // given - String name = "BE 공식일정"; - - // when - ExtractableResponse response = 새로운_카테고리를_등록한다(name); + // given & when + ExtractableResponse response = 새로운_카테고리를_등록한다(CATEGORY_NAME); // then 상태코드_201이_반환된다(response); @@ -32,39 +33,20 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @Test void 카테고리를_등록하고_페이징을_통해_나누어_조회한다() { // given - 새로운_카테고리를_등록한다("BE 공식일정"); - 새로운_카테고리를_등록한다("FE 공식일정"); - 새로운_카테고리를_등록한다("알록달록 회의"); - - int page = 0; - int size = 8; + 새로운_카테고리를_등록한다(CATEGORY_NAME); + 새로운_카테고리를_등록한다(CATEGORY_NAME); + 새로운_카테고리를_등록한다(CATEGORY_NAME); + 새로운_카테고리를_등록한다(CATEGORY_NAME); // when - ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(page, size); + ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(PAGE_NUMBER, PAGE_SIZE); CategoriesResponse categoriesResponse = response.as(CategoriesResponse.class); // then assertAll(() -> { 상태코드_200이_반환된다(response); - assertThat(categoriesResponse.getPage()).isEqualTo(page); - assertThat(categoriesResponse.getCategories()).hasSize(3); + assertThat(categoriesResponse.getPage()).isEqualTo(PAGE_NUMBER); + assertThat(categoriesResponse.getCategories()).hasSize(PAGE_SIZE); }); } - - private ExtractableResponse 새로운_카테고리를_등록한다(final String name) { - CategoryCreateRequest request = new CategoryCreateRequest(name); - return RestAssured.given().log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(request) - .when().post("/api/categories") - .then().log().all() - .extract(); - } - - private ExtractableResponse 카테고리를_페이징을_통해_조회한다(final int page, final int size) { - return RestAssured.given().log().all() - .when().get("/api/categories?page={page}&size={size}", page, size) - .then().log().all() - .extract(); - } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java index 687b1a88..e13869d5 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -1,5 +1,6 @@ package com.allog.dallog.acceptance; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java index 73cddb2b..6d15a497 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/ScheduleAcceptanceTest.java @@ -1,5 +1,7 @@ package com.allog.dallog.acceptance; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; import static com.allog.dallog.acceptance.fixtures.ScheduleAcceptanceFixtures.새로운_일정을_등록한다; import static com.allog.dallog.acceptance.fixtures.ScheduleAcceptanceFixtures.월별_일정을_조회한다; import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE_TIME_STRING; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java index 6e6baf68..80c953bb 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java @@ -1,5 +1,7 @@ package com.allog.dallog.acceptance; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; + import com.allog.dallog.auth.dto.TokenRequest; import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.category.dto.request.CategoryCreateRequest; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java new file mode 100644 index 00000000..bd0073cc --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java @@ -0,0 +1,28 @@ +package com.allog.dallog.acceptance.fixtures; + +import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.springframework.http.MediaType; + +public class CategoryAcceptanceFixtures { + + public static ExtractableResponse 새로운_카테고리를_등록한다(final String name) { + CategoryCreateRequest request = new CategoryCreateRequest(name); + + return RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(request) + .when().post("/api/categories") + .then().log().all() + .extract(); + } + + public static ExtractableResponse 카테고리를_페이징을_통해_조회한다(final int page, final int size) { + return RestAssured.given().log().all() + .when().get("/api/categories?page={page}&size={size}", page, size) + .then().log().all() + .extract(); + } +} diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java index bd4abcc5..56a387c0 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java @@ -1,5 +1,7 @@ package com.allog.dallog.category.domain; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @@ -27,23 +29,22 @@ class CategoryRepositoryTest { categoryRepository.save(new Category("지원플랫폼 근로")); categoryRepository.save(new Category("파랑의 코틀린 스터디")); - int page = 1; - int size = 2; - PageRequest pageRequest = PageRequest.of(page, size); + PageRequest pageRequest = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); // when Slice categories = categoryRepository.findSliceBy(pageRequest); // then - assertAll( - () -> assertThat(categories.getContent()) - .hasSize(size) - .extracting(Category::getName) - .contains("알록달록 회의", "지원플랫폼 근로"), - () -> assertThat(categories.getContent().stream() - .map(Category::getCreatedAt) - .allMatch(Objects::nonNull)) - .isTrue() + assertAll(() -> { + assertThat(categories.getContent()) + .hasSize(PAGE_SIZE) + .extracting(Category::getName) + .contains("알록달록 회의", "지원플랫폼 근로"); + assertThat(categories.getContent().stream() + .map(Category::getCreatedAt) + .allMatch(Objects::nonNull)) + .isTrue(); + } ); } @@ -51,9 +52,7 @@ class CategoryRepositoryTest { @Test void 조회_시_데이터가_존재하지_않는_경우_빈_슬라이스가_반환된다() { // given - int page = 1; - int size = 2; - PageRequest pageRequest = PageRequest.of(page, size); + PageRequest pageRequest = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); // when Slice categories = categoryRepository.findSliceBy(pageRequest); diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index bc52061f..095d69e8 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -1,5 +1,8 @@ package com.allog.dallog.category.service; +import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; @@ -28,14 +31,13 @@ class CategoryServiceTest { @Test void 새로운_카테고리를_생성한다() { // given - String name = "BE 공식일정"; - CategoryCreateRequest request = new CategoryCreateRequest(name); + CategoryCreateRequest request = new CategoryCreateRequest(CATEGORY_NAME); // when CategoryResponse response = categoryService.save(request); // then - assertThat(response.getName()).isEqualTo(name); + assertThat(response.getName()).isEqualTo(CATEGORY_NAME); } @DisplayName("새로운 카테고리를 생성 할 떄 이름이 공백이거나 길이가 20을 초과하는 경우 예외를 던진다.") @@ -60,9 +62,7 @@ class CategoryServiceTest { categoryService.save(new CategoryCreateRequest("지원플랫폼 근로")); categoryService.save(new CategoryCreateRequest("파랑의 코틀린 스터디")); - int page = 1; - int size = 2; - PageRequest request = PageRequest.of(page, size); + PageRequest request = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); // when List response = categoryService.findAll(request); @@ -70,7 +70,7 @@ class CategoryServiceTest { // then assertAll(() -> { assertThat(response) - .hasSize(size) + .hasSize(PAGE_SIZE) .extracting(CategoryResponse::getName) .contains("알록달록 회의", "지원플랫폼 근로"); }); diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 77f95f12..1a116719 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -6,5 +6,8 @@ public class CategoryFixtures { public static final String CATEGORY_NAME = "달록"; + public static final int PAGE_NUMBER = 1; + public static final int PAGE_SIZE = 2; + public static final Category CATEGORY = new Category(CATEGORY_NAME); } From 1a34561b6ba87147e72cec9282a192f55b5b159c Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 12:57:18 +0900 Subject: [PATCH 0214/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=EC=97=90=20=EC=83=9D=EC=84=B1=ED=95=9C=20=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=20=EC=A0=95=EB=B3=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CategoryController.java | 7 ++-- .../dallog/category/domain/Category.java | 15 +++++++- .../dto/request/CategoryCreateRequest.java | 5 --- .../dto/response/CategoryResponse.java | 21 ++++++----- .../category/service/CategoryService.java | 11 ++++-- .../dallog/acceptance/AcceptanceTest.java | 3 ++ .../dallog/acceptance/AuthAcceptanceTest.java | 11 ------ .../acceptance/CategoryAcceptanceTest.java | 34 ++++++++++++------ .../acceptance/MemberAcceptanceTest.java | 18 +++------- .../SubscriptionAcceptanceTest.java | 33 +++-------------- .../domain/CategoryRepositoryTest.java | 19 +++++++--- .../dallog/category/domain/CategoryTest.java | 7 ++-- .../category/service/CategoryServiceTest.java | 35 +++++++++++-------- .../common/fixtures/CategoryFixtures.java | 4 ++- .../service/SubscriptionServiceTest.java | 6 ++-- 15 files changed, 120 insertions(+), 109 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index 1a9ee089..1f8c31ef 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -1,5 +1,7 @@ package com.allog.dallog.category.controller; +import com.allog.dallog.auth.dto.LoginMember; +import com.allog.dallog.auth.support.AuthenticationPrincipal; import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoriesResponse; import com.allog.dallog.category.dto.response.CategoryResponse; @@ -26,8 +28,9 @@ public CategoryController(final CategoryService categoryService) { } @PostMapping - public ResponseEntity save(@Valid @RequestBody final CategoryCreateRequest request) { - CategoryResponse categoryResponse = categoryService.save(request); + public ResponseEntity save(@AuthenticationPrincipal final LoginMember loginMember, + @Valid @RequestBody final CategoryCreateRequest request) { + CategoryResponse categoryResponse = categoryService.save(loginMember.getId(), request); return ResponseEntity.created(URI.create("/api/categories/" + categoryResponse.getId())).body(categoryResponse); } diff --git a/backend/src/main/java/com/allog/dallog/category/domain/Category.java b/backend/src/main/java/com/allog/dallog/category/domain/Category.java index 0915bb03..8e236b1d 100644 --- a/backend/src/main/java/com/allog/dallog/category/domain/Category.java +++ b/backend/src/main/java/com/allog/dallog/category/domain/Category.java @@ -2,11 +2,15 @@ import com.allog.dallog.category.exception.InvalidCategoryException; import com.allog.dallog.global.domain.BaseEntity; +import com.allog.dallog.member.domain.Member; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.Table; @Table(name = "categories") @@ -23,12 +27,17 @@ public class Category extends BaseEntity { @Column(name = "name", nullable = false) private String name; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "members_id", nullable = false) + private Member member; + protected Category() { } - public Category(final String name) { + public Category(final String name, final Member member) { validateNameLength(name); this.name = name; + this.member = member; } private void validateNameLength(final String name) { @@ -47,4 +56,8 @@ public Long getId() { public String getName() { return name; } + + public Member getMember() { + return member; + } } diff --git a/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java b/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java index 9efc5428..378c63fc 100644 --- a/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java +++ b/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java @@ -1,6 +1,5 @@ package com.allog.dallog.category.dto.request; -import com.allog.dallog.category.domain.Category; import javax.validation.constraints.NotBlank; public class CategoryCreateRequest { @@ -15,10 +14,6 @@ public CategoryCreateRequest(final String name) { this.name = name; } - public Category toEntity() { - return new Category(name); - } - public String getName() { return name; } diff --git a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java index cb0dbb18..a481cd8a 100644 --- a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java +++ b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java @@ -1,24 +1,25 @@ package com.allog.dallog.category.dto.response; import com.allog.dallog.category.domain.Category; +import com.allog.dallog.member.dto.MemberResponse; import java.time.LocalDateTime; public class CategoryResponse { - private Long id; - private String name; - private LocalDateTime createdAt; - - private CategoryResponse() { - } + private final Long id; + private final String name; + private final MemberResponse creator; + private final LocalDateTime createdAt; public CategoryResponse(final Category category) { - this(category.getId(), category.getName(), category.getCreatedAt()); + this(category.getId(), category.getName(), new MemberResponse(category.getMember()), category.getCreatedAt()); } - public CategoryResponse(final Long id, final String name, final LocalDateTime createdAt) { + public CategoryResponse(final Long id, final String name, final MemberResponse creator, + final LocalDateTime createdAt) { this.id = id; this.name = name; + this.creator = creator; this.createdAt = createdAt; } @@ -30,6 +31,10 @@ public String getName() { return name; } + public MemberResponse getCreator() { + return creator; + } + public LocalDateTime getCreatedAt() { return createdAt; } diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index 305dc92a..50b6ed2f 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -5,6 +5,8 @@ import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.exception.NoSuchCategoryException; +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.service.MemberService; import java.util.List; import java.util.stream.Collectors; import org.springframework.data.domain.Pageable; @@ -16,14 +18,17 @@ public class CategoryService { private final CategoryRepository categoryRepository; + private final MemberService memberService; - public CategoryService(final CategoryRepository categoryRepository) { + public CategoryService(final CategoryRepository categoryRepository, final MemberService memberService) { this.categoryRepository = categoryRepository; + this.memberService = memberService; } @Transactional - public CategoryResponse save(final CategoryCreateRequest request) { - Category category = categoryRepository.save(request.toEntity()); + public CategoryResponse save(final Long memberId, final CategoryCreateRequest request) { + Member member = memberService.getMember(memberId); + Category category = categoryRepository.save(new Category(request.getName(), member)); return new CategoryResponse(category); } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java index 18061103..995d318e 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java @@ -1,13 +1,16 @@ package com.allog.dallog.acceptance; +import com.allog.dallog.common.config.TestConfig; import io.restassured.RestAssured; import org.junit.jupiter.api.BeforeEach; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.context.annotation.Import; import org.springframework.test.annotation.DirtiesContext; @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@Import(TestConfig.class) class AcceptanceTest { @LocalServerPort diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java index 9f012dca..10ce0b3a 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java @@ -5,7 +5,6 @@ import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.auth.dto.OAuthUriResponse; -import com.allog.dallog.auth.dto.TokenRequest; import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.common.config.TestConfig; import io.restassured.RestAssured; @@ -64,14 +63,4 @@ public class AuthAcceptanceTest extends AcceptanceTest { .statusCode(HttpStatus.OK.value()) .extract(); } - - private ExtractableResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { - return RestAssured.given().log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(new TokenRequest(code)) - .when().post("/api/auth/{oauthProvider}/token", oauthProvider) - .then().log().all() - .statusCode(HttpStatus.OK.value()) - .extract(); - } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index b5d272a3..64976e5e 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -1,16 +1,16 @@ package com.allog.dallog.acceptance; -import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.새로운_카테고리를_등록한다; -import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.카테고리를_페이징을_통해_조회한다; -import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; -import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE; +import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; +import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; +import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.category.dto.response.CategoriesResponse; +import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.junit.jupiter.api.DisplayName; @@ -22,8 +22,12 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @DisplayName("정상적인 카테고리 정보를 등록하면 상태코드 201을 반환한다.") @Test void 정상적인_카테고리_정보를_등록하면_상태코드_201을_반환한다() { - // given & when - ExtractableResponse response = 새로운_카테고리를_등록한다(CATEGORY_NAME); + // given + ExtractableResponse tokenCreateResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); + TokenResponse tokenResponse = tokenCreateResponse.as(TokenResponse.class); + + // when + ExtractableResponse response = 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); // then 상태코드_201이_반환된다(response); @@ -33,11 +37,12 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @Test void 카테고리를_등록하고_페이징을_통해_나누어_조회한다() { // given - 새로운_카테고리를_등록한다(CATEGORY_NAME); - 새로운_카테고리를_등록한다(CATEGORY_NAME); - 새로운_카테고리를_등록한다(CATEGORY_NAME); - 새로운_카테고리를_등록한다(CATEGORY_NAME); - + ExtractableResponse tokenCreateResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); + TokenResponse tokenResponse = tokenCreateResponse.as(TokenResponse.class); + 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); + 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); + 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); + 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); // when ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(PAGE_NUMBER, PAGE_SIZE); CategoriesResponse categoriesResponse = response.as(CategoriesResponse.class); @@ -49,4 +54,11 @@ public class CategoryAcceptanceTest extends AcceptanceTest { assertThat(categoriesResponse.getCategories()).hasSize(PAGE_SIZE); }); } + + private ExtractableResponse 카테고리를_페이징을_통해_조회한다(final int page, final int size) { + return RestAssured.given().log().all() + .when().get("/api/categories?page={page}&size={size}", page, size) + .then().log().all() + .extract(); + } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java index e13869d5..a27e2c46 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -1,10 +1,10 @@ package com.allog.dallog.acceptance; -import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; +import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; +import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; -import com.allog.dallog.auth.dto.TokenRequest; import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.common.config.TestConfig; import com.allog.dallog.common.fixtures.OAuthMemberFixtures; @@ -26,7 +26,8 @@ public class MemberAcceptanceTest extends AcceptanceTest { @Test void 등록된_회원이_자신의_정보를_조회하면_상태코드_200_을_반환한다() { // given - TokenResponse tokenResponse = 자체_토큰을_생성한다(OAuthMemberFixtures.OAUTH_PROVIDER, OAuthMemberFixtures.CODE); + ExtractableResponse tokenCreateResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); + TokenResponse tokenResponse = tokenCreateResponse.as(TokenResponse.class); // when ExtractableResponse response = 자신의_정보를_조회한다(tokenResponse); @@ -41,17 +42,6 @@ public class MemberAcceptanceTest extends AcceptanceTest { }); } - private TokenResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { - return RestAssured.given().log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(new TokenRequest(code)) - .when().post("/api/auth/{oauthProvider}/token", oauthProvider) - .then().log().all() - .statusCode(HttpStatus.OK.value()) - .extract() - .as(TokenResponse.class); - } - private ExtractableResponse 자신의_정보를_조회한다(final TokenResponse tokenResponse) { return RestAssured.given().log().all() .auth().oauth2(tokenResponse.getAccessToken()) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java index 80c953bb..02d50be7 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java @@ -1,13 +1,11 @@ package com.allog.dallog.acceptance; -import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; +import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; +import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; -import com.allog.dallog.auth.dto.TokenRequest; import com.allog.dallog.auth.dto.TokenResponse; -import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.common.config.TestConfig; -import com.allog.dallog.common.fixtures.OAuthMemberFixtures; import com.allog.dallog.fixture.SubscriptionFixtures; import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; import io.restassured.RestAssured; @@ -27,8 +25,9 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { @Test void 인증된_회원이_카테고리를_구독하면_201을_반환한다() { // given - TokenResponse tokenResponse = 자체_토큰을_생성한다(OAuthMemberFixtures.OAUTH_PROVIDER, OAuthMemberFixtures.CODE); - CategoryResponse categoryResponse = 새로운_카테고리를_등록한다("BE 공식일정"); + ExtractableResponse tokenCreateResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); + TokenResponse tokenResponse = tokenCreateResponse.as(TokenResponse.class); + CategoryResponse categoryResponse = 새로운_카테고리를_등록한다(tokenResponse, "BE 공식일정").as(CategoryResponse.class); // when ExtractableResponse response = 카테고리를_구독한다(tokenResponse, categoryResponse); @@ -37,28 +36,6 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { 상태코드_201이_반환된다(response); } - private TokenResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { - return RestAssured.given().log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(new TokenRequest(code)) - .when().post("/api/auth/{oauthProvider}/token", oauthProvider) - .then().log().all() - .statusCode(HttpStatus.OK.value()) - .extract() - .as(TokenResponse.class); - } - - private CategoryResponse 새로운_카테고리를_등록한다(final String name) { - CategoryCreateRequest request = new CategoryCreateRequest(name); - return RestAssured.given().log().all() - .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(request) - .when().post("/api/categories") - .then().log().all() - .extract() - .as(CategoryResponse.class); - } - private ExtractableResponse 카테고리를_구독한다(final TokenResponse tokenResponse, final CategoryResponse categoryResponse) { return RestAssured.given().log().all() diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java index 56a387c0..230ff9bd 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java @@ -2,32 +2,41 @@ import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE; +import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; +import com.allog.dallog.global.config.JpaConfig; +import com.allog.dallog.member.domain.MemberRepository; import java.util.Objects; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Slice; @DataJpaTest +@Import(JpaConfig.class) class CategoryRepositoryTest { @Autowired private CategoryRepository categoryRepository; + @Autowired + private MemberRepository memberRepository; + @DisplayName("페이지와 사이즈를 받아 해당하는 구간의 카테고리를 조회한다.") @Test void 페이지와_사이즈를_받아_해당하는_구간의_카테고리를_조회한다() { // given - categoryRepository.save(new Category("BE 공식일정")); - categoryRepository.save(new Category("FE 공식일정")); - categoryRepository.save(new Category("알록달록 회의")); - categoryRepository.save(new Category("지원플랫폼 근로")); - categoryRepository.save(new Category("파랑의 코틀린 스터디")); + memberRepository.save(MEMBER); + categoryRepository.save(new Category("BE 공식일정", MEMBER)); + categoryRepository.save(new Category("FE 공식일정", MEMBER)); + categoryRepository.save(new Category("알록달록 회의", MEMBER)); + categoryRepository.save(new Category("지원플랫폼 근로", MEMBER)); + categoryRepository.save(new Category("파랑의 코틀린 스터디", MEMBER)); PageRequest pageRequest = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java index f6f78b68..9045507c 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java @@ -1,5 +1,6 @@ package com.allog.dallog.category.domain; +import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -18,7 +19,7 @@ class CategoryTest { String name = "BE 공식일정"; // when & then - assertDoesNotThrow(() -> new Category(name)); + assertDoesNotThrow(() -> new Category(name, MEMBER)); } @DisplayName("카테고리 이름이 공백인 경우 예외를 던진다.") @@ -28,7 +29,7 @@ class CategoryTest { String name = ""; // when & then - assertThatThrownBy(() -> new Category(name)) + assertThatThrownBy(() -> new Category(name, MEMBER)) .isInstanceOf(InvalidCategoryException.class); } @@ -38,7 +39,7 @@ class CategoryTest { "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 카테고리"}) void 카테고리_이름의_길이가_20을_초과하는_경우_예외를_던진다(final String name) { // given & when & then - assertThatThrownBy(() -> new Category(name)) + assertThatThrownBy(() -> new Category(name, MEMBER)) .isInstanceOf(InvalidCategoryException.class); } } diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 095d69e8..8496ed1a 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -3,13 +3,15 @@ import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE; +import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.exception.InvalidCategoryException; +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.domain.MemberRepository; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -27,14 +29,18 @@ class CategoryServiceTest { @Autowired private CategoryService categoryService; + @Autowired + private MemberRepository memberRepository; + @DisplayName("새로운 카테고리를 생성한다.") @Test void 새로운_카테고리를_생성한다() { // given CategoryCreateRequest request = new CategoryCreateRequest(CATEGORY_NAME); + Member member = memberRepository.save(MEMBER); // when - CategoryResponse response = categoryService.save(request); + CategoryResponse response = categoryService.save(member.getId(), request); // then assertThat(response.getName()).isEqualTo(CATEGORY_NAME); @@ -46,9 +52,10 @@ class CategoryServiceTest { void 새로운_카테고리를_생성_할_때_이름이_공백이거나_길이가_20을_초과하는_경우_예외를_던진다(final String name) { // given CategoryCreateRequest request = new CategoryCreateRequest(name); + Member member = memberRepository.save(MEMBER); // when & then - assertThatThrownBy(() -> categoryService.save(request)) + assertThatThrownBy(() -> categoryService.save(member.getId(), request)) .isInstanceOf(InvalidCategoryException.class); } @@ -56,11 +63,13 @@ class CategoryServiceTest { @Test void 페이지를_받아_해당하는_구간의_카테고리를_가져온다() { // given - categoryService.save(new CategoryCreateRequest("BE 공식일정")); - categoryService.save(new CategoryCreateRequest("FE 공식일정")); - categoryService.save(new CategoryCreateRequest("알록달록 회의")); - categoryService.save(new CategoryCreateRequest("지원플랫폼 근로")); - categoryService.save(new CategoryCreateRequest("파랑의 코틀린 스터디")); + Member member = memberRepository.save(MEMBER); + Long memberId = member.getId(); + categoryService.save(memberId, new CategoryCreateRequest("BE 공식일정")); + categoryService.save(memberId, new CategoryCreateRequest("FE 공식일정")); + categoryService.save(memberId, new CategoryCreateRequest("알록달록 회의")); + categoryService.save(memberId, new CategoryCreateRequest("지원플랫폼 근로")); + categoryService.save(memberId, new CategoryCreateRequest("파랑의 코틀린 스터디")); PageRequest request = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); @@ -68,11 +77,9 @@ class CategoryServiceTest { List response = categoryService.findAll(request); // then - assertAll(() -> { - assertThat(response) - .hasSize(PAGE_SIZE) - .extracting(CategoryResponse::getName) - .contains("알록달록 회의", "지원플랫폼 근로"); - }); + assertThat(response) + .hasSize(PAGE_SIZE) + .extracting(CategoryResponse::getName) + .contains("알록달록 회의", "지원플랫폼 근로"); } } diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 1a116719..46777e1f 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -1,5 +1,7 @@ package com.allog.dallog.common.fixtures; +import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; + import com.allog.dallog.category.domain.Category; public class CategoryFixtures { @@ -9,5 +11,5 @@ public class CategoryFixtures { public static final int PAGE_NUMBER = 1; public static final int PAGE_SIZE = 2; - public static final Category CATEGORY = new Category(CATEGORY_NAME); + public static final Category CATEGORY = new Category(CATEGORY_NAME, MEMBER); } diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java index 3f3ad087..39e7be07 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -40,7 +40,7 @@ class SubscriptionServiceTest { void 새로운_구독을_생성한다() { // given Member member = memberService.save(MemberFixtures.MEMBER); - CategoryResponse categoryResponse = categoryService.save(new CategoryCreateRequest("BE 일정")); + CategoryResponse categoryResponse = categoryService.save(member.getId(), new CategoryCreateRequest("BE 일정")); String color = "#ffffff"; // when @@ -58,7 +58,7 @@ class SubscriptionServiceTest { void 색_정보_형식이_잘못된_경우_예외를_던진다(final String color) { // given Member member = memberService.save(MemberFixtures.MEMBER); - CategoryResponse categoryResponse = categoryService.save(new CategoryCreateRequest("BE 일정")); + CategoryResponse categoryResponse = categoryService.save(member.getId(), new CategoryCreateRequest("BE 일정")); // when & then assertThatThrownBy(() -> subscriptionService.save(member.getId(), categoryResponse.getId(), @@ -70,7 +70,7 @@ class SubscriptionServiceTest { void 구독_id를_기반으로_단건_조회한다() { // given Member member = memberService.save(MemberFixtures.MEMBER); - CategoryResponse categoryResponse = categoryService.save(new CategoryCreateRequest("BE 일정")); + CategoryResponse categoryResponse = categoryService.save(member.getId(), new CategoryCreateRequest("BE 일정")); String color = "#ffffff"; SubscriptionResponse subscriptionResponse = subscriptionService.save(member.getId(), categoryResponse.getId(), new SubscriptionCreateRequest(color)); From 59efbccaf22e3f7dda1a36e2bab5cee686a143bc Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 13:19:33 +0900 Subject: [PATCH 0215/1011] =?UTF-8?q?test:=20=ED=94=BD=EC=8A=A4=EC=B2=98?= =?UTF-8?q?=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/acceptance/AuthAcceptanceTest.java | 1 + .../acceptance/CategoryAcceptanceTest.java | 5 +++++ .../acceptance/MemberAcceptanceTest.java | 2 ++ .../SubscriptionAcceptanceTest.java | 3 +++ .../fixtures/AuthAcceptanceFixtures.java | 21 +++++++++++++++++++ .../fixtures/CategoryAcceptanceFixtures.java | 5 +++-- .../service/SubscriptionServiceTest.java | 8 +++---- 7 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 backend/src/test/java/com/allog/dallog/acceptance/fixtures/AuthAcceptanceFixtures.java diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java index 10ce0b3a..c63c903f 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java @@ -1,5 +1,6 @@ package com.allog.dallog.acceptance; +import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.자체_토큰을_생성한다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 64976e5e..29641928 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -1,5 +1,9 @@ package com.allog.dallog.acceptance; +import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.자체_토큰을_생성한다; +import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.새로운_카테고리를_등록한다; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE; @@ -43,6 +47,7 @@ public class CategoryAcceptanceTest extends AcceptanceTest { 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); + // when ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(PAGE_NUMBER, PAGE_SIZE); CategoriesResponse categoriesResponse = response.as(CategoriesResponse.class); diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java index a27e2c46..41438e52 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -1,5 +1,7 @@ package com.allog.dallog.acceptance; +import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.자체_토큰을_생성한다; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; import static org.assertj.core.api.Assertions.assertThat; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java index 02d50be7..e99774d5 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java @@ -1,5 +1,8 @@ package com.allog.dallog.acceptance; +import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.자체_토큰을_생성한다; +import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.새로운_카테고리를_등록한다; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/AuthAcceptanceFixtures.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/AuthAcceptanceFixtures.java new file mode 100644 index 00000000..5f5c57f7 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/AuthAcceptanceFixtures.java @@ -0,0 +1,21 @@ +package com.allog.dallog.acceptance.fixtures; + +import com.allog.dallog.auth.dto.TokenRequest; +import io.restassured.RestAssured; +import io.restassured.response.ExtractableResponse; +import io.restassured.response.Response; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +public class AuthAcceptanceFixtures { + + public static ExtractableResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { + return RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(new TokenRequest(code)) + .when().post("/api/auth/{oauthProvider}/token", oauthProvider) + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract(); + } +} diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java index bd0073cc..5620bd09 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java @@ -1,5 +1,6 @@ package com.allog.dallog.acceptance.fixtures; +import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.category.dto.request.CategoryCreateRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; @@ -8,10 +9,10 @@ public class CategoryAcceptanceFixtures { - public static ExtractableResponse 새로운_카테고리를_등록한다(final String name) { + public static ExtractableResponse 새로운_카테고리를_등록한다(final TokenResponse tokenResponse, final String name) { CategoryCreateRequest request = new CategoryCreateRequest(name); - return RestAssured.given().log().all() + .auth().oauth2(tokenResponse.getAccessToken()) .contentType(MediaType.APPLICATION_JSON_VALUE) .body(request) .when().post("/api/categories") diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java index 39e7be07..0d43304a 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -1,5 +1,6 @@ package com.allog.dallog.subscription.service; +import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; @@ -7,7 +8,6 @@ import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; -import com.allog.dallog.common.fixtures.MemberFixtures; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.service.MemberService; import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; @@ -39,7 +39,7 @@ class SubscriptionServiceTest { @Test void 새로운_구독을_생성한다() { // given - Member member = memberService.save(MemberFixtures.MEMBER); + Member member = memberService.save(MEMBER); CategoryResponse categoryResponse = categoryService.save(member.getId(), new CategoryCreateRequest("BE 일정")); String color = "#ffffff"; @@ -57,7 +57,7 @@ class SubscriptionServiceTest { @ValueSource(strings = {"#111", "#1111", "#11111", "123456", "#**1234", "##12345", "334172#"}) void 색_정보_형식이_잘못된_경우_예외를_던진다(final String color) { // given - Member member = memberService.save(MemberFixtures.MEMBER); + Member member = memberService.save(MEMBER); CategoryResponse categoryResponse = categoryService.save(member.getId(), new CategoryCreateRequest("BE 일정")); // when & then @@ -69,7 +69,7 @@ class SubscriptionServiceTest { @Test void 구독_id를_기반으로_단건_조회한다() { // given - Member member = memberService.save(MemberFixtures.MEMBER); + Member member = memberService.save(MEMBER); CategoryResponse categoryResponse = categoryService.save(member.getId(), new CategoryCreateRequest("BE 일정")); String color = "#ffffff"; SubscriptionResponse subscriptionResponse = subscriptionService.save(member.getId(), categoryResponse.getId(), From 2ff2e5e5c7a95159419382bfadd0763ecc30482f Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 13:22:26 +0900 Subject: [PATCH 0216/1011] =?UTF-8?q?refactor(Member):=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EB=B0=98=ED=99=98=EA=B0=92=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/member/service/MemberService.java | 4 ++-- .../allog/dallog/member/service/MemberServiceTest.java | 5 +++-- .../subscription/service/SubscriptionServiceTest.java | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java index 7965897f..3420fd01 100644 --- a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java +++ b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java @@ -18,8 +18,8 @@ public MemberService(final MemberRepository memberRepository) { } @Transactional - public Member save(final Member member) { - return memberRepository.save(member); + public MemberResponse save(final Member member) { + return new MemberResponse(memberRepository.save(member)); } public MemberResponse findById(final Long id) { diff --git a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java b/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java index 4869bd35..03a73f73 100644 --- a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java @@ -4,6 +4,7 @@ import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.SocialType; +import com.allog.dallog.member.dto.MemberResponse; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -24,7 +25,7 @@ class MemberServiceTest { Member member = new Member("devhudi@gmail.com", "/image.png", "후디", SocialType.GOOGLE); // when - Member actual = memberService.save(member); + MemberResponse actual = memberService.save(member); // then assertThat(actual).isNotNull(); @@ -38,7 +39,7 @@ class MemberServiceTest { String profileImageUrl = "/image.png"; String displayName = "후디"; Member member = new Member(email, profileImageUrl, displayName, SocialType.GOOGLE); - Member savedMember = memberService.save(member); + MemberResponse savedMember = memberService.save(member); // when Member foundMember = memberService.findByEmail(email); diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java index 0d43304a..f1a0ceb2 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -8,7 +8,7 @@ import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; -import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.dto.MemberResponse; import com.allog.dallog.member.service.MemberService; import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; import com.allog.dallog.subscription.dto.response.SubscriptionResponse; @@ -39,7 +39,7 @@ class SubscriptionServiceTest { @Test void 새로운_구독을_생성한다() { // given - Member member = memberService.save(MEMBER); + MemberResponse member = memberService.save(MEMBER); CategoryResponse categoryResponse = categoryService.save(member.getId(), new CategoryCreateRequest("BE 일정")); String color = "#ffffff"; @@ -57,7 +57,7 @@ class SubscriptionServiceTest { @ValueSource(strings = {"#111", "#1111", "#11111", "123456", "#**1234", "##12345", "334172#"}) void 색_정보_형식이_잘못된_경우_예외를_던진다(final String color) { // given - Member member = memberService.save(MEMBER); + MemberResponse member = memberService.save(MEMBER); CategoryResponse categoryResponse = categoryService.save(member.getId(), new CategoryCreateRequest("BE 일정")); // when & then @@ -69,7 +69,7 @@ class SubscriptionServiceTest { @Test void 구독_id를_기반으로_단건_조회한다() { // given - Member member = memberService.save(MEMBER); + MemberResponse member = memberService.save(MEMBER); CategoryResponse categoryResponse = categoryService.save(member.getId(), new CategoryCreateRequest("BE 일정")); String color = "#ffffff"; SubscriptionResponse subscriptionResponse = subscriptionService.save(member.getId(), categoryResponse.getId(), From 744789bc68a64f40fe5bb89d7fe85b781dc13031 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 14:06:01 +0900 Subject: [PATCH 0217/1011] =?UTF-8?q?refactor(Category):=20response=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/dto/response/CategoryResponse.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java index a481cd8a..91a1abc8 100644 --- a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java +++ b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java @@ -6,10 +6,13 @@ public class CategoryResponse { - private final Long id; - private final String name; - private final MemberResponse creator; - private final LocalDateTime createdAt; + private Long id; + private String name; + private MemberResponse creator; + private LocalDateTime createdAt; + + private CategoryResponse() { + } public CategoryResponse(final Category category) { this(category.getId(), category.getName(), new MemberResponse(category.getMember()), category.getCreatedAt()); From d1678a2574b1abac5ae5cd66c1e610b60331744b Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 12:00:13 +0900 Subject: [PATCH 0218/1011] =?UTF-8?q?chore:=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20fixtures=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EB=A3=A8=ED=8A=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/common/fixtures/SubscriptionFixtures.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java index ba5bdfb0..87579251 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java @@ -1,4 +1,4 @@ -package com.allog.dallog.fixture; +package com.allog.dallog.common.fixtures; public class SubscriptionFixtures { From 0413c58586e3a0cc39a7d59ce26e3169f5250709 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 12:21:35 +0900 Subject: [PATCH 0219/1011] =?UTF-8?q?test:=20SubscriptionRepository=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/SubscriptionRepository.java | 3 + .../SubscriptionAcceptanceTest.java | 7 +- .../common/fixtures/CategoryFixtures.java | 8 +++ .../common/fixtures/SubscriptionFixtures.java | 4 +- .../SubscriptionRepositoryTest.java | 70 +++++++++++++++++++ 5 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java diff --git a/backend/src/main/java/com/allog/dallog/subscription/repository/SubscriptionRepository.java b/backend/src/main/java/com/allog/dallog/subscription/repository/SubscriptionRepository.java index 4c554597..0e65d2be 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/repository/SubscriptionRepository.java +++ b/backend/src/main/java/com/allog/dallog/subscription/repository/SubscriptionRepository.java @@ -1,7 +1,10 @@ package com.allog.dallog.subscription.repository; import com.allog.dallog.subscription.domain.Subscription; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; public interface SubscriptionRepository extends JpaRepository { + + List findByMemberId(final Long memberId); } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java index e99774d5..50a22cd5 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java @@ -9,7 +9,12 @@ import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.common.config.TestConfig; +<<<<<<< HEAD import com.allog.dallog.fixture.SubscriptionFixtures; +======= +import com.allog.dallog.common.fixtures.OAuthMemberFixtures; +import com.allog.dallog.common.fixtures.SubscriptionFixtures; +>>>>>>> e056d17 (test: SubscriptionRepository 검증 추가) import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; @@ -44,7 +49,7 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { return RestAssured.given().log().all() .auth().oauth2(tokenResponse.getAccessToken()) .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(new SubscriptionCreateRequest(SubscriptionFixtures.COLOR)) + .body(new SubscriptionCreateRequest(SubscriptionFixtures.COLOR_RED)) .when().post("/api/members/me/categories/{categoryId}/subscriptions", categoryResponse.getId()) .then().log().all() .statusCode(HttpStatus.CREATED.value()) diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 46777e1f..43a4560c 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -11,5 +11,13 @@ public class CategoryFixtures { public static final int PAGE_NUMBER = 1; public static final int PAGE_SIZE = 2; +<<<<<<< HEAD public static final Category CATEGORY = new Category(CATEGORY_NAME, MEMBER); +======= + public static final Category CATEGORY = new Category(CATEGORY_NAME); + + public static final Category CATEGORY_1 = new Category("BE 일정"); + public static final Category CATEGORY_2 = new Category("FE 일정"); + public static final Category CATEGORY_3 = new Category("공통 일정"); +>>>>>>> e056d17 (test: SubscriptionRepository 검증 추가) } diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java index 87579251..d91cdbe9 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java @@ -2,5 +2,7 @@ public class SubscriptionFixtures { - public static final String COLOR = "#ffffff"; + public static final String COLOR_RED = "#FF0000"; + public static final String COLOR_BLUE = "#0000FF"; + public static final String COLOR_YELLOW = "#FFFF00"; } diff --git a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java b/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java new file mode 100644 index 00000000..ca304e20 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java @@ -0,0 +1,70 @@ +package com.allog.dallog.subscription.repository; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.allog.dallog.category.domain.Category; +import com.allog.dallog.category.domain.CategoryRepository; +import com.allog.dallog.common.fixtures.CategoryFixtures; +import com.allog.dallog.common.fixtures.MemberFixtures; +import com.allog.dallog.common.fixtures.SubscriptionFixtures; +import com.allog.dallog.global.config.JpaConfig; +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.domain.MemberRepository; +import com.allog.dallog.subscription.domain.Subscription; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; + +@DataJpaTest +@Import(JpaConfig.class) +class SubscriptionRepositoryTest { + + @Autowired + private MemberRepository memberRepository; + + @Autowired + private CategoryRepository categoryRepository; + + @Autowired + private SubscriptionRepository subscriptionRepository; + + @DisplayName("회원 정보를 기반으로 구독 정보를 조회한다.") + @Test + void 회원_정보를_기반으로_구독_정보를_조회한다() { + // given + Member member = memberRepository.save(MemberFixtures.MEMBER); + Category category1 = categoryRepository.save(CategoryFixtures.CATEGORY_1); + Category category2 = categoryRepository.save(CategoryFixtures.CATEGORY_2); + Category category3 = categoryRepository.save(CategoryFixtures.CATEGORY_3); + + Subscription subscription1 = new Subscription(member, category1, SubscriptionFixtures.COLOR_RED); + Subscription subscription2 = new Subscription(member, category2, SubscriptionFixtures.COLOR_BLUE); + Subscription subscription3 = new Subscription(member, category3, SubscriptionFixtures.COLOR_YELLOW); + + subscriptionRepository.save(subscription1); + subscriptionRepository.save(subscription2); + subscriptionRepository.save(subscription3); + + // when + List subscriptions = subscriptionRepository.findByMemberId(member.getId()); + + // then + assertThat(subscriptions).hasSize(3); + } + + @DisplayName("회원의 구독 정보가 존재하지 않는 경우 빈 리스트가 조회된다.") + @Test + void 회원의_구독_정보가_존재하지_않는_경우_빈_리스트가_조회된다() { + // given + Member member = memberRepository.save(MemberFixtures.MEMBER); + + // when + List subscriptions = subscriptionRepository.findByMemberId(member.getId()); + + // then + assertThat(subscriptions).isEmpty(); + } +} From cb6dffd265d73294def84c97ee2527f44d786311 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 12:31:27 +0900 Subject: [PATCH 0220/1011] =?UTF-8?q?test:=20SubscriptionService=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/SubscriptionsResponse.java | 19 ++++++++++++ .../service/SubscriptionService.java | 13 +++++++++ .../SubscriptionAcceptanceTest.java | 5 ---- .../domain/CategoryRepositoryTest.java | 13 +++++---- .../common/fixtures/CategoryFixtures.java | 16 +++++----- .../common/fixtures/MemberFixtures.java | 1 + .../common/fixtures/SubscriptionFixtures.java | 6 ++++ .../SubscriptionRepositoryTest.java | 2 ++ .../service/SubscriptionServiceTest.java | 29 +++++++++++++++++++ 9 files changed, 86 insertions(+), 18 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionsResponse.java diff --git a/backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionsResponse.java b/backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionsResponse.java new file mode 100644 index 00000000..2878c8a8 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionsResponse.java @@ -0,0 +1,19 @@ +package com.allog.dallog.subscription.dto.response; + +import java.util.List; + +public class SubscriptionsResponse { + + private List subscriptions; + + private SubscriptionsResponse() { + } + + public SubscriptionsResponse(final List subscriptions) { + this.subscriptions = subscriptions; + } + + public List getSubscriptions() { + return subscriptions; + } +} diff --git a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java b/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java index 0d834b79..62ea0be2 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java +++ b/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java @@ -7,8 +7,11 @@ import com.allog.dallog.subscription.domain.Subscription; import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; import com.allog.dallog.subscription.dto.response.SubscriptionResponse; +import com.allog.dallog.subscription.dto.response.SubscriptionsResponse; import com.allog.dallog.subscription.exception.NoSuchSubscriptionException; import com.allog.dallog.subscription.repository.SubscriptionRepository; +import java.util.List; +import java.util.stream.Collectors; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -38,6 +41,16 @@ public SubscriptionResponse save(final Long memberId, final Long categoryId, return new SubscriptionResponse(subscription); } + public SubscriptionsResponse findAByMemberId(final Long memberId) { + List subscriptions = subscriptionRepository.findByMemberId(memberId); + + List subscriptionResponses = subscriptions.stream() + .map(SubscriptionResponse::new) + .collect(Collectors.toList()); + + return new SubscriptionsResponse(subscriptionResponses); + } + public SubscriptionResponse findById(final Long id) { Subscription subscription = subscriptionRepository.findById(id) .orElseThrow(NoSuchSubscriptionException::new); diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java index 50a22cd5..79d56de4 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java @@ -9,12 +9,7 @@ import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.common.config.TestConfig; -<<<<<<< HEAD -import com.allog.dallog.fixture.SubscriptionFixtures; -======= -import com.allog.dallog.common.fixtures.OAuthMemberFixtures; import com.allog.dallog.common.fixtures.SubscriptionFixtures; ->>>>>>> e056d17 (test: SubscriptionRepository 검증 추가) import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java index 230ff9bd..c0e03331 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java @@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.global.config.JpaConfig; +import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; import java.util.Objects; import org.junit.jupiter.api.DisplayName; @@ -31,12 +32,12 @@ class CategoryRepositoryTest { @Test void 페이지와_사이즈를_받아_해당하는_구간의_카테고리를_조회한다() { // given - memberRepository.save(MEMBER); - categoryRepository.save(new Category("BE 공식일정", MEMBER)); - categoryRepository.save(new Category("FE 공식일정", MEMBER)); - categoryRepository.save(new Category("알록달록 회의", MEMBER)); - categoryRepository.save(new Category("지원플랫폼 근로", MEMBER)); - categoryRepository.save(new Category("파랑의 코틀린 스터디", MEMBER)); + Member member = memberRepository.save(MEMBER); + categoryRepository.save(new Category("BE 공식일정", member)); + categoryRepository.save(new Category("FE 공식일정", member)); + categoryRepository.save(new Category("알록달록 회의", member)); + categoryRepository.save(new Category("지원플랫폼 근로", member)); + categoryRepository.save(new Category("파랑의 코틀린 스터디", member)); PageRequest pageRequest = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 43a4560c..3c755fc6 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -1,8 +1,10 @@ package com.allog.dallog.common.fixtures; +import static com.allog.dallog.common.fixtures.MemberFixtures.CREATOR; import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; import com.allog.dallog.category.domain.Category; +import com.allog.dallog.category.dto.request.CategoryCreateRequest; public class CategoryFixtures { @@ -11,13 +13,13 @@ public class CategoryFixtures { public static final int PAGE_NUMBER = 1; public static final int PAGE_SIZE = 2; -<<<<<<< HEAD public static final Category CATEGORY = new Category(CATEGORY_NAME, MEMBER); -======= - public static final Category CATEGORY = new Category(CATEGORY_NAME); - public static final Category CATEGORY_1 = new Category("BE 일정"); - public static final Category CATEGORY_2 = new Category("FE 일정"); - public static final Category CATEGORY_3 = new Category("공통 일정"); ->>>>>>> e056d17 (test: SubscriptionRepository 검증 추가) + public static final Category CATEGORY_1 = new Category("BE 일정", CREATOR); + public static final Category CATEGORY_2 = new Category("FE 일정", CREATOR); + public static final Category CATEGORY_3 = new Category("공통 일정", CREATOR); + + public static final CategoryCreateRequest CATEGORY_CREATE_REQUEST_1 = new CategoryCreateRequest("BE 일정"); + public static final CategoryCreateRequest CATEGORY_CREATE_REQUEST_2 = new CategoryCreateRequest("FE 일정"); + public static final CategoryCreateRequest CATEGORY_CREATE_REQUEST_3 = new CategoryCreateRequest("공통 일정"); } diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java index 5c16b1fa..9f1ce14b 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java @@ -10,4 +10,5 @@ public class MemberFixtures { public static final String DISPLAY_NAME = "example"; public static final Member MEMBER = new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE); + public static final Member CREATOR = new Member("creator@email.com", "/image.png", "creator", SocialType.GOOGLE); } diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java index d91cdbe9..658b254b 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java @@ -1,8 +1,14 @@ package com.allog.dallog.common.fixtures; +import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; + public class SubscriptionFixtures { public static final String COLOR_RED = "#FF0000"; public static final String COLOR_BLUE = "#0000FF"; public static final String COLOR_YELLOW = "#FFFF00"; + + public static final SubscriptionCreateRequest CREATE_REQUEST_RED = new SubscriptionCreateRequest(COLOR_RED); + public static final SubscriptionCreateRequest CREATE_REQUEST_BLUE = new SubscriptionCreateRequest(COLOR_BLUE); + public static final SubscriptionCreateRequest CREATE_REQUEST_YELLOW = new SubscriptionCreateRequest(COLOR_YELLOW); } diff --git a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java b/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java index ca304e20..67e02b4c 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java @@ -36,6 +36,8 @@ class SubscriptionRepositoryTest { void 회원_정보를_기반으로_구독_정보를_조회한다() { // given Member member = memberRepository.save(MemberFixtures.MEMBER); + + Member creator = memberRepository.save(MemberFixtures.CREATOR); Category category1 = categoryRepository.save(CategoryFixtures.CATEGORY_1); Category category2 = categoryRepository.save(CategoryFixtures.CATEGORY_2); Category category3 = categoryRepository.save(CategoryFixtures.CATEGORY_3); diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java index f1a0ceb2..92c92271 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -8,10 +8,14 @@ import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; +import com.allog.dallog.common.fixtures.CategoryFixtures; +import com.allog.dallog.common.fixtures.MemberFixtures; +import com.allog.dallog.common.fixtures.SubscriptionFixtures; import com.allog.dallog.member.dto.MemberResponse; import com.allog.dallog.member.service.MemberService; import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; import com.allog.dallog.subscription.dto.response.SubscriptionResponse; +import com.allog.dallog.subscription.dto.response.SubscriptionsResponse; import com.allog.dallog.subscription.exception.InvalidSubscriptionException; import com.allog.dallog.subscription.exception.NoSuchSubscriptionException; import org.junit.jupiter.api.DisplayName; @@ -93,4 +97,29 @@ class SubscriptionServiceTest { assertThatThrownBy(() -> subscriptionService.findById(0L)) .isInstanceOf(NoSuchSubscriptionException.class); } + + @DisplayName("회원 정보를 기반으로 구독 정보를 조회한다.") + @Test + void 회원_정보를_기반으로_구독_정보를_조회한다() { + // given + MemberResponse creator = memberService.save(MemberFixtures.CREATOR); + + CategoryResponse categoryResponse1 = categoryService.save(creator.getId(), + CategoryFixtures.CATEGORY_CREATE_REQUEST_1); + CategoryResponse categoryResponse2 = categoryService.save(creator.getId(), + CategoryFixtures.CATEGORY_CREATE_REQUEST_2); + CategoryResponse categoryResponse3 = categoryService.save(creator.getId(), + CategoryFixtures.CATEGORY_CREATE_REQUEST_3); + + subscriptionService.save(creator.getId(), categoryResponse1.getId(), SubscriptionFixtures.CREATE_REQUEST_RED); + subscriptionService.save(creator.getId(), categoryResponse2.getId(), SubscriptionFixtures.CREATE_REQUEST_BLUE); + subscriptionService.save(creator.getId(), categoryResponse3.getId(), + SubscriptionFixtures.CREATE_REQUEST_YELLOW); + + // when + SubscriptionsResponse subscriptionsResponse = subscriptionService.findAByMemberId(creator.getId()); + + // then + assertThat(subscriptionsResponse.getSubscriptions()).hasSize(3); + } } From a22a999e2f44212c84cfe3db07df671635859415 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 12:43:09 +0900 Subject: [PATCH 0221/1011] =?UTF-8?q?feat:=20SubscriptionController=20?= =?UTF-8?q?=EB=B0=8F=20=EC=9D=B8=EC=88=98=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SubscriptionController.java | 8 +++ .../SubscriptionAcceptanceTest.java | 65 +++++++++++++++++-- 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java index 56a4d338..c40db9b3 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java +++ b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java @@ -4,9 +4,11 @@ import com.allog.dallog.auth.support.AuthenticationPrincipal; import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; import com.allog.dallog.subscription.dto.response.SubscriptionResponse; +import com.allog.dallog.subscription.dto.response.SubscriptionsResponse; import com.allog.dallog.subscription.service.SubscriptionService; import java.net.URI; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -29,4 +31,10 @@ public ResponseEntity save(@AuthenticationPrincipal final return ResponseEntity.created( URI.create("/api/members/me/" + categoryId + "/subscriptions/" + response.getId())).body(response); } + + @GetMapping("/api/members/me/subscriptions") + public ResponseEntity findMe(@AuthenticationPrincipal final LoginMember loginMember) { + SubscriptionsResponse response = subscriptionService.findAByMemberId(loginMember.getId()); + return ResponseEntity.ok(response); + } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java index 79d56de4..11988355 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java @@ -1,16 +1,19 @@ package com.allog.dallog.acceptance; -import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.자체_토큰을_생성한다; -import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.새로운_카테고리를_등록한다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; +import com.allog.dallog.auth.dto.TokenRequest; import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.common.config.TestConfig; import com.allog.dallog.common.fixtures.SubscriptionFixtures; import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; +import com.allog.dallog.subscription.dto.response.SubscriptionsResponse; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; @@ -28,9 +31,8 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { @Test void 인증된_회원이_카테고리를_구독하면_201을_반환한다() { // given - ExtractableResponse tokenCreateResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); - TokenResponse tokenResponse = tokenCreateResponse.as(TokenResponse.class); - CategoryResponse categoryResponse = 새로운_카테고리를_등록한다(tokenResponse, "BE 공식일정").as(CategoryResponse.class); + TokenResponse tokenResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); + CategoryResponse categoryResponse = 새로운_카테고리를_등록한다(tokenResponse, "BE 공식일정"); // when ExtractableResponse response = 카테고리를_구독한다(tokenResponse, categoryResponse); @@ -39,6 +41,59 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { 상태코드_201이_반환된다(response); } + @DisplayName("인증된 회원이 구독 목록을 조회하면 200을 반환한다.") + @Test + void 인증된_회원이_구독_목록을_조회하면_200을_반환한다() { + // given + TokenResponse tokenResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); + CategoryResponse categoryResponse1 = 새로운_카테고리를_등록한다(tokenResponse, "BE 일정"); + CategoryResponse categoryResponse2 = 새로운_카테고리를_등록한다(tokenResponse, "FE 일정"); + CategoryResponse categoryResponse3 = 새로운_카테고리를_등록한다(tokenResponse, "공통 일정"); + + 카테고리를_구독한다(tokenResponse, categoryResponse1); + 카테고리를_구독한다(tokenResponse, categoryResponse2); + 카테고리를_구독한다(tokenResponse, categoryResponse3); + + // when + ExtractableResponse response = RestAssured.given().log().all() + .auth().oauth2(tokenResponse.getAccessToken()) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .when().get("/api/members/me/subscriptions") + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract(); + SubscriptionsResponse subscriptionsResponse = response.as(SubscriptionsResponse.class); + + // then + assertAll(() -> { + assertThat(response.statusCode()).isEqualTo(HttpStatus.OK.value()); + assertThat(subscriptionsResponse.getSubscriptions()).hasSize(3); + }); + } + + private TokenResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { + return RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(new TokenRequest(code)) + .when().post("/api/auth/{oauthProvider}/token", oauthProvider) + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract() + .as(TokenResponse.class); + } + + private CategoryResponse 새로운_카테고리를_등록한다(final TokenResponse tokenResponse, final String name) { + CategoryCreateRequest request = new CategoryCreateRequest(name); + return RestAssured.given().log().all() + .auth().oauth2(tokenResponse.getAccessToken()) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(request) + .when().post("/api/categories") + .then().log().all() + .extract() + .as(CategoryResponse.class); + } + private ExtractableResponse 카테고리를_구독한다(final TokenResponse tokenResponse, final CategoryResponse categoryResponse) { return RestAssured.given().log().all() From 7e854bf89638941f47215b4b9e67212795eda8eb Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 15:14:52 +0900 Subject: [PATCH 0222/1011] =?UTF-8?q?fix:=20SubscriptionService=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/SubscriptionController.java | 2 +- .../subscription/service/SubscriptionService.java | 2 +- .../subscription/service/SubscriptionServiceTest.java | 11 +++++------ 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java index c40db9b3..cdf70731 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java +++ b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java @@ -34,7 +34,7 @@ public ResponseEntity save(@AuthenticationPrincipal final @GetMapping("/api/members/me/subscriptions") public ResponseEntity findMe(@AuthenticationPrincipal final LoginMember loginMember) { - SubscriptionsResponse response = subscriptionService.findAByMemberId(loginMember.getId()); + SubscriptionsResponse response = subscriptionService.findByMemberId(loginMember.getId()); return ResponseEntity.ok(response); } } diff --git a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java b/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java index 62ea0be2..e58c5117 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java +++ b/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java @@ -41,7 +41,7 @@ public SubscriptionResponse save(final Long memberId, final Long categoryId, return new SubscriptionResponse(subscription); } - public SubscriptionsResponse findAByMemberId(final Long memberId) { + public SubscriptionsResponse findByMemberId(final Long memberId) { List subscriptions = subscriptionRepository.findByMemberId(memberId); List subscriptionResponses = subscriptions.stream() diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java index 92c92271..718d2d62 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -103,7 +103,6 @@ class SubscriptionServiceTest { void 회원_정보를_기반으로_구독_정보를_조회한다() { // given MemberResponse creator = memberService.save(MemberFixtures.CREATOR); - CategoryResponse categoryResponse1 = categoryService.save(creator.getId(), CategoryFixtures.CATEGORY_CREATE_REQUEST_1); CategoryResponse categoryResponse2 = categoryService.save(creator.getId(), @@ -111,13 +110,13 @@ class SubscriptionServiceTest { CategoryResponse categoryResponse3 = categoryService.save(creator.getId(), CategoryFixtures.CATEGORY_CREATE_REQUEST_3); - subscriptionService.save(creator.getId(), categoryResponse1.getId(), SubscriptionFixtures.CREATE_REQUEST_RED); - subscriptionService.save(creator.getId(), categoryResponse2.getId(), SubscriptionFixtures.CREATE_REQUEST_BLUE); - subscriptionService.save(creator.getId(), categoryResponse3.getId(), - SubscriptionFixtures.CREATE_REQUEST_YELLOW); + MemberResponse member = memberService.save(MEMBER); + subscriptionService.save(member.getId(), categoryResponse1.getId(), SubscriptionFixtures.CREATE_REQUEST_RED); + subscriptionService.save(member.getId(), categoryResponse2.getId(), SubscriptionFixtures.CREATE_REQUEST_BLUE); + subscriptionService.save(member.getId(), categoryResponse3.getId(), SubscriptionFixtures.CREATE_REQUEST_YELLOW); // when - SubscriptionsResponse subscriptionsResponse = subscriptionService.findAByMemberId(creator.getId()); + SubscriptionsResponse subscriptionsResponse = subscriptionService.findByMemberId(member.getId()); // then assertThat(subscriptionsResponse.getSubscriptions()).hasSize(3); From 22e09d46f0becf06cc49bd764effb6010ad105c0 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 15:20:15 +0900 Subject: [PATCH 0223/1011] =?UTF-8?q?chore:=20SubscriptionController=20?= =?UTF-8?q?=EC=9C=A0=EC=9D=98=EB=AF=B8=ED=95=9C=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=AA=85=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/subscription/controller/SubscriptionController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java index cdf70731..6d59c2bf 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java +++ b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java @@ -33,7 +33,8 @@ public ResponseEntity save(@AuthenticationPrincipal final } @GetMapping("/api/members/me/subscriptions") - public ResponseEntity findMe(@AuthenticationPrincipal final LoginMember loginMember) { + public ResponseEntity findMineSubscriptions( + @AuthenticationPrincipal final LoginMember loginMember) { SubscriptionsResponse response = subscriptionService.findByMemberId(loginMember.getId()); return ResponseEntity.ok(response); } From 29256a26a800c6f1a6b17e23b00fc013048f9c45 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 15:25:21 +0900 Subject: [PATCH 0224/1011] =?UTF-8?q?chore:=20fixtures=20static=20import?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acceptance/MemberAcceptanceTest.java | 10 +++--- .../SubscriptionAcceptanceTest.java | 4 +-- .../dallog/auth/service/AuthServiceTest.java | 7 ++-- .../subscription/domain/SubscriptionTest.java | 12 +++---- .../SubscriptionRepositoryTest.java | 29 ++++++++++------- .../service/SubscriptionServiceTest.java | 32 +++++++++++-------- 6 files changed, 53 insertions(+), 41 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java index 41438e52..7c1a4c7e 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -2,6 +2,9 @@ import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.자체_토큰을_생성한다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; +import static com.allog.dallog.common.fixtures.MemberFixtures.DISPLAY_NAME; +import static com.allog.dallog.common.fixtures.MemberFixtures.EMAIL; +import static com.allog.dallog.common.fixtures.MemberFixtures.PROFILE_IMAGE_URI; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; import static org.assertj.core.api.Assertions.assertThat; @@ -9,7 +12,6 @@ import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.common.config.TestConfig; -import com.allog.dallog.common.fixtures.OAuthMemberFixtures; import com.allog.dallog.member.dto.MemberResponse; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; @@ -38,9 +40,9 @@ public class MemberAcceptanceTest extends AcceptanceTest { // then assertAll(() -> { 상태코드_200이_반환된다(response); - assertThat(memberResponse.getEmail()).isEqualTo(OAuthMemberFixtures.EMAIL); - assertThat(memberResponse.getDisplayName()).isEqualTo(OAuthMemberFixtures.DISPLAY_NAME); - assertThat(memberResponse.getProfileImageUrl()).isEqualTo(OAuthMemberFixtures.PROFILE_IMAGE_URI); + assertThat(memberResponse.getEmail()).isEqualTo(EMAIL); + assertThat(memberResponse.getDisplayName()).isEqualTo(DISPLAY_NAME); + assertThat(memberResponse.getProfileImageUrl()).isEqualTo(PROFILE_IMAGE_URI); }); } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java index 11988355..2c759703 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java @@ -3,6 +3,7 @@ import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.COLOR_RED; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @@ -11,7 +12,6 @@ import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.common.config.TestConfig; -import com.allog.dallog.common.fixtures.SubscriptionFixtures; import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; import com.allog.dallog.subscription.dto.response.SubscriptionsResponse; import io.restassured.RestAssured; @@ -99,7 +99,7 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { return RestAssured.given().log().all() .auth().oauth2(tokenResponse.getAccessToken()) .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(new SubscriptionCreateRequest(SubscriptionFixtures.COLOR_RED)) + .body(new SubscriptionCreateRequest(COLOR_RED)) .when().post("/api/members/me/categories/{categoryId}/subscriptions", categoryResponse.getId()) .then().log().all() .statusCode(HttpStatus.CREATED.value()) diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index 1773df39..d462aa15 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -1,10 +1,11 @@ package com.allog.dallog.auth.service; +import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; +import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.EMAIL; import static org.assertj.core.api.Assertions.assertThat; import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.common.config.TestConfig; -import com.allog.dallog.common.fixtures.OAuthMemberFixtures; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; import java.util.List; @@ -49,11 +50,11 @@ class AuthServiceTest { @Test void Authorization_Code를_받으면_회원이_데이터베이스에_저장된다() { // given - String code = OAuthMemberFixtures.CODE; + String code = CODE; authService.generateTokenWithCode(code); // when - boolean actual = memberRepository.existsByEmail(OAuthMemberFixtures.EMAIL); + boolean actual = memberRepository.existsByEmail(EMAIL); // SutbOAuthClient가 반환하는 OAuthMember의 이메일 // then diff --git a/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java b/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java index 45207f6a..68db568e 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java @@ -1,11 +1,11 @@ package com.allog.dallog.subscription.domain; +import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY; +import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import com.allog.dallog.category.domain.Category; -import com.allog.dallog.common.fixtures.CategoryFixtures; -import com.allog.dallog.common.fixtures.MemberFixtures; import com.allog.dallog.member.domain.Member; import com.allog.dallog.subscription.exception.InvalidSubscriptionException; import org.junit.jupiter.api.DisplayName; @@ -19,8 +19,8 @@ class SubscriptionTest { @Test void 구독을_생성한다() { // given - Member member = MemberFixtures.MEMBER; - Category category = CategoryFixtures.CATEGORY; + Member member = MEMBER; + Category category = CATEGORY; String color = "#c9ad2e"; // when & then @@ -32,8 +32,8 @@ class SubscriptionTest { @ValueSource(strings = {"#111", "#1111", "#11111", "123456", "#**1234", "##12345", "334172#"}) void 색_정보_형식이_잘못된_경우_예외를_던진다(final String color) { // given - Member member = MemberFixtures.MEMBER; - Category category = CategoryFixtures.CATEGORY; + Member member = MEMBER; + Category category = CATEGORY; // when & then assertThatThrownBy(() -> new Subscription(member, category, color)) diff --git a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java b/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java index 67e02b4c..d88cba66 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java @@ -1,12 +1,17 @@ package com.allog.dallog.subscription.repository; +import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_1; +import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_2; +import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_3; +import static com.allog.dallog.common.fixtures.MemberFixtures.CREATOR; +import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.COLOR_BLUE; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.COLOR_RED; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.COLOR_YELLOW; import static org.assertj.core.api.Assertions.assertThat; import com.allog.dallog.category.domain.Category; import com.allog.dallog.category.domain.CategoryRepository; -import com.allog.dallog.common.fixtures.CategoryFixtures; -import com.allog.dallog.common.fixtures.MemberFixtures; -import com.allog.dallog.common.fixtures.SubscriptionFixtures; import com.allog.dallog.global.config.JpaConfig; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; @@ -35,16 +40,16 @@ class SubscriptionRepositoryTest { @Test void 회원_정보를_기반으로_구독_정보를_조회한다() { // given - Member member = memberRepository.save(MemberFixtures.MEMBER); + Member member = memberRepository.save(MEMBER); - Member creator = memberRepository.save(MemberFixtures.CREATOR); - Category category1 = categoryRepository.save(CategoryFixtures.CATEGORY_1); - Category category2 = categoryRepository.save(CategoryFixtures.CATEGORY_2); - Category category3 = categoryRepository.save(CategoryFixtures.CATEGORY_3); + Member creator = memberRepository.save(CREATOR); + Category category1 = categoryRepository.save(CATEGORY_1); + Category category2 = categoryRepository.save(CATEGORY_2); + Category category3 = categoryRepository.save(CATEGORY_3); - Subscription subscription1 = new Subscription(member, category1, SubscriptionFixtures.COLOR_RED); - Subscription subscription2 = new Subscription(member, category2, SubscriptionFixtures.COLOR_BLUE); - Subscription subscription3 = new Subscription(member, category3, SubscriptionFixtures.COLOR_YELLOW); + Subscription subscription1 = new Subscription(member, category1, COLOR_RED); + Subscription subscription2 = new Subscription(member, category2, COLOR_BLUE); + Subscription subscription3 = new Subscription(member, category3, COLOR_YELLOW); subscriptionRepository.save(subscription1); subscriptionRepository.save(subscription2); @@ -61,7 +66,7 @@ class SubscriptionRepositoryTest { @Test void 회원의_구독_정보가_존재하지_않는_경우_빈_리스트가_조회된다() { // given - Member member = memberRepository.save(MemberFixtures.MEMBER); + Member member = memberRepository.save(MEMBER); // when List subscriptions = subscriptionRepository.findByMemberId(member.getId()); diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java index 718d2d62..1bd5ebb2 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -1,6 +1,13 @@ package com.allog.dallog.subscription.service; + +import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_CREATE_REQUEST_1; +import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_CREATE_REQUEST_2; +import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_CREATE_REQUEST_3; import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.CREATE_REQUEST_BLUE; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.CREATE_REQUEST_RED; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.CREATE_REQUEST_YELLOW; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; @@ -8,9 +15,7 @@ import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; -import com.allog.dallog.common.fixtures.CategoryFixtures; import com.allog.dallog.common.fixtures.MemberFixtures; -import com.allog.dallog.common.fixtures.SubscriptionFixtures; import com.allog.dallog.member.dto.MemberResponse; import com.allog.dallog.member.service.MemberService; import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; @@ -18,13 +23,13 @@ import com.allog.dallog.subscription.dto.response.SubscriptionsResponse; import com.allog.dallog.subscription.exception.InvalidSubscriptionException; import com.allog.dallog.subscription.exception.NoSuchSubscriptionException; +import javax.transaction.Transactional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.transaction.annotation.Transactional; @Transactional @SpringBootTest @@ -52,8 +57,10 @@ class SubscriptionServiceTest { new SubscriptionCreateRequest(color)); // then - assertThat(response.getCategory().getName()).isEqualTo("BE 일정"); - assertThat(response.getColor()).isEqualTo(color); + assertAll(() -> { + assertThat(response.getCategory().getName()).isEqualTo("BE 일정"); + assertThat(response.getColor()).isEqualTo(color); + }); } @DisplayName("색 정보 형식이 잘못된 경우 예외를 던진다.") @@ -103,17 +110,14 @@ class SubscriptionServiceTest { void 회원_정보를_기반으로_구독_정보를_조회한다() { // given MemberResponse creator = memberService.save(MemberFixtures.CREATOR); - CategoryResponse categoryResponse1 = categoryService.save(creator.getId(), - CategoryFixtures.CATEGORY_CREATE_REQUEST_1); - CategoryResponse categoryResponse2 = categoryService.save(creator.getId(), - CategoryFixtures.CATEGORY_CREATE_REQUEST_2); - CategoryResponse categoryResponse3 = categoryService.save(creator.getId(), - CategoryFixtures.CATEGORY_CREATE_REQUEST_3); + CategoryResponse categoryResponse1 = categoryService.save(creator.getId(), CATEGORY_CREATE_REQUEST_1); + CategoryResponse categoryResponse2 = categoryService.save(creator.getId(), CATEGORY_CREATE_REQUEST_2); + CategoryResponse categoryResponse3 = categoryService.save(creator.getId(), CATEGORY_CREATE_REQUEST_3); MemberResponse member = memberService.save(MEMBER); - subscriptionService.save(member.getId(), categoryResponse1.getId(), SubscriptionFixtures.CREATE_REQUEST_RED); - subscriptionService.save(member.getId(), categoryResponse2.getId(), SubscriptionFixtures.CREATE_REQUEST_BLUE); - subscriptionService.save(member.getId(), categoryResponse3.getId(), SubscriptionFixtures.CREATE_REQUEST_YELLOW); + subscriptionService.save(member.getId(), categoryResponse1.getId(), CREATE_REQUEST_RED); + subscriptionService.save(member.getId(), categoryResponse2.getId(), CREATE_REQUEST_BLUE); + subscriptionService.save(member.getId(), categoryResponse3.getId(), CREATE_REQUEST_YELLOW); // when SubscriptionsResponse subscriptionsResponse = subscriptionService.findByMemberId(member.getId()); From 45342ca4a67343ecee519c819d500674767ba1dd Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 16:07:51 +0900 Subject: [PATCH 0225/1011] =?UTF-8?q?chore:=20SubscriptionController=20?= =?UTF-8?q?=EC=9C=A0=EC=9D=98=EB=AF=B8=ED=95=9C=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EB=AA=85=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/subscription/controller/SubscriptionController.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java index 6d59c2bf..2a7da232 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java +++ b/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java @@ -33,8 +33,7 @@ public ResponseEntity save(@AuthenticationPrincipal final } @GetMapping("/api/members/me/subscriptions") - public ResponseEntity findMineSubscriptions( - @AuthenticationPrincipal final LoginMember loginMember) { + public ResponseEntity findMine(@AuthenticationPrincipal final LoginMember loginMember) { SubscriptionsResponse response = subscriptionService.findByMemberId(loginMember.getId()); return ResponseEntity.ok(response); } From 1c236ed18a24e00086e3f29b457657e1de6581ac Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 20 Jul 2022 16:13:59 +0900 Subject: [PATCH 0226/1011] =?UTF-8?q?test:=20TokenResponse=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/acceptance/AuthAcceptanceTest.java | 12 +++++++++++- .../dallog/acceptance/CategoryAcceptanceTest.java | 6 ++---- .../dallog/acceptance/MemberAcceptanceTest.java | 3 +-- .../acceptance/fixtures/AuthAcceptanceFixtures.java | 8 ++++---- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java index c63c903f..9f012dca 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java @@ -1,11 +1,11 @@ package com.allog.dallog.acceptance; -import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.자체_토큰을_생성한다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.auth.dto.OAuthUriResponse; +import com.allog.dallog.auth.dto.TokenRequest; import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.common.config.TestConfig; import io.restassured.RestAssured; @@ -64,4 +64,14 @@ public class AuthAcceptanceTest extends AcceptanceTest { .statusCode(HttpStatus.OK.value()) .extract(); } + + private ExtractableResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { + return RestAssured.given().log().all() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(new TokenRequest(code)) + .when().post("/api/auth/{oauthProvider}/token", oauthProvider) + .then().log().all() + .statusCode(HttpStatus.OK.value()) + .extract(); + } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 29641928..7b55b5dc 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -27,8 +27,7 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @Test void 정상적인_카테고리_정보를_등록하면_상태코드_201을_반환한다() { // given - ExtractableResponse tokenCreateResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); - TokenResponse tokenResponse = tokenCreateResponse.as(TokenResponse.class); + TokenResponse tokenResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); // when ExtractableResponse response = 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); @@ -41,8 +40,7 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @Test void 카테고리를_등록하고_페이징을_통해_나누어_조회한다() { // given - ExtractableResponse tokenCreateResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); - TokenResponse tokenResponse = tokenCreateResponse.as(TokenResponse.class); + TokenResponse tokenResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java index 7c1a4c7e..f98e461a 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -30,8 +30,7 @@ public class MemberAcceptanceTest extends AcceptanceTest { @Test void 등록된_회원이_자신의_정보를_조회하면_상태코드_200_을_반환한다() { // given - ExtractableResponse tokenCreateResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); - TokenResponse tokenResponse = tokenCreateResponse.as(TokenResponse.class); + TokenResponse tokenResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); // when ExtractableResponse response = 자신의_정보를_조회한다(tokenResponse); diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/AuthAcceptanceFixtures.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/AuthAcceptanceFixtures.java index 5f5c57f7..88af3e84 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/AuthAcceptanceFixtures.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/AuthAcceptanceFixtures.java @@ -1,21 +1,21 @@ package com.allog.dallog.acceptance.fixtures; import com.allog.dallog.auth.dto.TokenRequest; +import com.allog.dallog.auth.dto.TokenResponse; import io.restassured.RestAssured; -import io.restassured.response.ExtractableResponse; -import io.restassured.response.Response; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; public class AuthAcceptanceFixtures { - public static ExtractableResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { + public static TokenResponse 자체_토큰을_생성한다(final String oauthProvider, final String code) { return RestAssured.given().log().all() .contentType(MediaType.APPLICATION_JSON_VALUE) .body(new TokenRequest(code)) .when().post("/api/auth/{oauthProvider}/token", oauthProvider) .then().log().all() .statusCode(HttpStatus.OK.value()) - .extract(); + .extract() + .as(TokenResponse.class); } } From 223a050bfa2624801060a82f5370057010c13094 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 15:27:53 +0900 Subject: [PATCH 0227/1011] =?UTF-8?q?test(Category):=20=EB=82=B4=EA=B0=80?= =?UTF-8?q?=20=EB=93=B1=EB=A1=9D=ED=95=9C=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=A1=B0=ED=9A=8C=20=EC=9D=B8=EC=88=98=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acceptance/CategoryAcceptanceTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 7b55b5dc..e2c9621b 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -64,4 +64,38 @@ public class CategoryAcceptanceTest extends AcceptanceTest { .then().log().all() .extract(); } + + @DisplayName("카테고리를 등록하고 내가 등록한 카테고리를 페이징을 통해 나누어 조회한다.") + @Test + void 카테고리를_등록하고_내가_등록한_카테고리를_페이징을_통해_나누어_조회한다() { + // given + ExtractableResponse tokenCreateResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); + TokenResponse tokenResponse = tokenCreateResponse.as(TokenResponse.class); + 새로운_카테고리를_등록한다(tokenResponse, "BE 공식일정"); + 새로운_카테고리를_등록한다(tokenResponse, "FE 공식일정"); + 새로운_카테고리를_등록한다(tokenResponse, "알록달록 회의"); + + int page = 0; + int size = 2; + + // when + ExtractableResponse response = 내가_등록한_카테고리를_페이징을_통해_조회한다(tokenResponse, page, size); + CategoriesResponse categoriesResponse = response.as(CategoriesResponse.class); + + // then + assertAll(() -> { + 상태코드_200이_반환된다(response); + assertThat(categoriesResponse.getPage()).isEqualTo(page); + assertThat(categoriesResponse.getCategories()).hasSize(3); + }); + } + + private ExtractableResponse 내가_등록한_카테고리를_페이징을_통해_조회한다(final TokenResponse tokenResponse, final int page, + final int size) { + return RestAssured.given().log().all() + .auth().oauth2(tokenResponse.getAccessToken()) + .when().get("/api/categories/me?page={page}&size={size}", page, size) + .then().log().all() + .extract(); + } } From c484054f614eeb3b8605a691465af662a008d07b Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 15:40:03 +0900 Subject: [PATCH 0228/1011] =?UTF-8?q?test(Category):=20=ED=8A=B9=EC=A0=95?= =?UTF-8?q?=20=EB=A9=A4=EB=B2=84=EA=B0=80=20=EB=A7=8C=EB=93=A0=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=EB=A5=BC=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=95=EC=9D=84=20=ED=86=B5=ED=95=B4=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=98=EB=8A=94=20Repository=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/domain/CategoryRepository.java | 2 ++ .../domain/CategoryRepositoryTest.java | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java b/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java index 175f4cf4..5edf4878 100644 --- a/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java +++ b/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java @@ -7,4 +7,6 @@ public interface CategoryRepository extends JpaRepository { Slice findSliceBy(final Pageable pageable); + + Slice findSliceByMemberId(final Pageable pageable, final Long memberId); } diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java index c0e03331..71b93260 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java @@ -9,6 +9,7 @@ import com.allog.dallog.global.config.JpaConfig; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; +import com.allog.dallog.member.domain.SocialType; import java.util.Objects; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -70,4 +71,37 @@ class CategoryRepositoryTest { // then assertThat(categories).hasSize(0); } + + @DisplayName("특정 멤버가 생성한 카테고리를 페이징을 통해 조회한다.") + @Test + void 특정_멤버가_생성한_카테고리를_페이징을_통해_조회한다() { + // given + Member member2 = new Member("a@eamil.com", "/image.png", "parang", SocialType.GOOGLE); + memberRepository.save(MEMBER); + memberRepository.save(member2); + categoryRepository.save(new Category("BE 공식일정", MEMBER)); + categoryRepository.save(new Category("FE 공식일정", MEMBER)); + categoryRepository.save(new Category("알록달록 회의", MEMBER)); + categoryRepository.save(new Category("지원플랫폼 근로", member2)); + categoryRepository.save(new Category("파랑의 코틀린 스터디", member2)); + + PageRequest pageRequest = PageRequest.of(0, 10); + + // when + Slice categories = categoryRepository.findSliceByMemberId(pageRequest, MEMBER.getId()); + + // then + assertAll(() -> { + assertThat(categories.getContent()) + .hasSize(3) + .extracting(Category::getName) + .containsExactlyInAnyOrder("BE 공식일정", "FE 공식일정", "알록달록 회의"); + assertThat(categories.getContent().stream() + .map(Category::getCreatedAt) + .allMatch(Objects::nonNull)) + .isTrue(); + } + ); + } + } From 1d94d154fe3f7e41438ce5aec3d6cee7952e2172 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 16:34:41 +0900 Subject: [PATCH 0229/1011] =?UTF-8?q?fix:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/acceptance/CategoryAcceptanceTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index e2c9621b..5bebd2de 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -69,8 +69,7 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @Test void 카테고리를_등록하고_내가_등록한_카테고리를_페이징을_통해_나누어_조회한다() { // given - ExtractableResponse tokenCreateResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); - TokenResponse tokenResponse = tokenCreateResponse.as(TokenResponse.class); + TokenResponse tokenResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); 새로운_카테고리를_등록한다(tokenResponse, "BE 공식일정"); 새로운_카테고리를_등록한다(tokenResponse, "FE 공식일정"); 새로운_카테고리를_등록한다(tokenResponse, "알록달록 회의"); From 1260e56a6dc78d9805f007fc72cd72fc312dee4d Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 16:39:07 +0900 Subject: [PATCH 0230/1011] =?UTF-8?q?test(Category):=20=ED=8A=B9=EC=A0=95?= =?UTF-8?q?=20=EB=A9=A4=EB=B2=84=EA=B0=80=20=EB=A7=8C=EB=93=A0=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=EB=A5=BC=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=95=EC=9D=84=20=ED=86=B5=ED=95=B4=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=98=EB=8A=94=20Service=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/service/CategoryService.java | 8 +++++++ .../category/service/CategoryServiceTest.java | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index 50b6ed2f..d3ab4a68 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -40,6 +40,14 @@ public List findAll(final Pageable pageable) { .collect(Collectors.toList()); } + public List findMine(final Long memberId, final Pageable pageable) { + return categoryRepository.findSliceByMemberId(pageable, memberId) + .getContent() + .stream() + .map(CategoryResponse::new) + .collect(Collectors.toList()); + } + public CategoryResponse findById(final Long id) { return new CategoryResponse(getCategory(id)); } diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 8496ed1a..f268a374 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -82,4 +82,28 @@ class CategoryServiceTest { .extracting(CategoryResponse::getName) .contains("알록달록 회의", "지원플랫폼 근로"); } + + @DisplayName("회원 id와 페이지를 기반으로 카테고리를 가져온다.") + @Test + void 회원_id와_페이지를_기반으로_카테고리를_가져온다() { + // given + Member member = memberRepository.save(MEMBER); + Long memberId = member.getId(); + categoryService.save(memberId, new CategoryCreateRequest("BE 공식일정")); + categoryService.save(memberId, new CategoryCreateRequest("FE 공식일정")); + categoryService.save(memberId, new CategoryCreateRequest("알록달록 회의")); + categoryService.save(memberId, new CategoryCreateRequest("지원플랫폼 근로")); + categoryService.save(memberId, new CategoryCreateRequest("파랑의 코틀린 스터디")); + + PageRequest request = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); + + // when + List response = categoryService.findMine(memberId, request); + + // then + assertThat(response) + .hasSize(PAGE_SIZE) + .extracting(CategoryResponse::getName) + .contains("알록달록 회의", "지원플랫폼 근로"); + } } From 2bb29532b19c269ca7c246f89facaf7bde46530b Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 16:44:12 +0900 Subject: [PATCH 0231/1011] =?UTF-8?q?test(Category):=20=ED=8A=B9=EC=A0=95?= =?UTF-8?q?=20=EB=A9=A4=EB=B2=84=EA=B0=80=20=EB=A7=8C=EB=93=A0=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=EB=A5=BC=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=95=EC=9D=84=20=ED=86=B5=ED=95=B4=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=ED=95=98=EB=8A=94=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/controller/CategoryController.java | 8 ++++++++ .../dallog/acceptance/CategoryAcceptanceTest.java | 11 +++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index 1f8c31ef..b520bf79 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -40,4 +40,12 @@ public ResponseEntity findAll(Pageable pageable) { List categoryResponses = categoryService.findAll(pageable); return ResponseEntity.ok(new CategoriesResponse(pageNumber, categoryResponses)); } + + @GetMapping("/me") + public ResponseEntity findMine(@AuthenticationPrincipal final LoginMember loginMember, + Pageable pageable) { + int pageNumber = pageable.getPageNumber(); + List categoryResponses = categoryService.findMine(loginMember.getId(), pageable); + return ResponseEntity.ok(new CategoriesResponse(pageNumber, categoryResponses)); + } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 5bebd2de..92bdb550 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -70,22 +70,21 @@ public class CategoryAcceptanceTest extends AcceptanceTest { void 카테고리를_등록하고_내가_등록한_카테고리를_페이징을_통해_나누어_조회한다() { // given TokenResponse tokenResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); - 새로운_카테고리를_등록한다(tokenResponse, "BE 공식일정"); - 새로운_카테고리를_등록한다(tokenResponse, "FE 공식일정"); - 새로운_카테고리를_등록한다(tokenResponse, "알록달록 회의"); + 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); + 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); + 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME); int page = 0; - int size = 2; // when - ExtractableResponse response = 내가_등록한_카테고리를_페이징을_통해_조회한다(tokenResponse, page, size); + ExtractableResponse response = 내가_등록한_카테고리를_페이징을_통해_조회한다(tokenResponse, page, PAGE_SIZE); CategoriesResponse categoriesResponse = response.as(CategoriesResponse.class); // then assertAll(() -> { 상태코드_200이_반환된다(response); assertThat(categoriesResponse.getPage()).isEqualTo(page); - assertThat(categoriesResponse.getCategories()).hasSize(3); + assertThat(categoriesResponse.getCategories()).hasSize(PAGE_SIZE); }); } From 6183e9b47daafadb17e0bae1b2a1f771376b5668 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 20 Jul 2022 13:21:52 +0900 Subject: [PATCH 0232/1011] =?UTF-8?q?feat:=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SubscribeButton.stories.tsx | 12 ++++++++++++ .../SubscribeButton/SubscribeButton.styles.ts | 16 ++++++++++++++++ .../SubscribeButton/SubscribeButton.tsx | 18 ++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 frontend/src/components/SubscribeButton/SubscribeButton.stories.tsx create mode 100644 frontend/src/components/SubscribeButton/SubscribeButton.styles.ts create mode 100644 frontend/src/components/SubscribeButton/SubscribeButton.tsx diff --git a/frontend/src/components/SubscribeButton/SubscribeButton.stories.tsx b/frontend/src/components/SubscribeButton/SubscribeButton.stories.tsx new file mode 100644 index 00000000..9d970d1f --- /dev/null +++ b/frontend/src/components/SubscribeButton/SubscribeButton.stories.tsx @@ -0,0 +1,12 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; + +import SubscribeButton from './SubscribeButton'; + +export default { + title: 'Components/SubscribeButton', + component: SubscribeButton, +} as ComponentMeta; + +const Template: ComponentStory = () => ; + +export const Primary = Template.bind({}); diff --git a/frontend/src/components/SubscribeButton/SubscribeButton.styles.ts b/frontend/src/components/SubscribeButton/SubscribeButton.styles.ts new file mode 100644 index 00000000..d88efcac --- /dev/null +++ b/frontend/src/components/SubscribeButton/SubscribeButton.styles.ts @@ -0,0 +1,16 @@ +import { css, Theme } from '@emotion/react'; + +const subscribeButton = ({ colors }: Theme, isSubscribe: boolean) => css` + width: 15rem; + height: 8rem; + border-radius: 3px; + + background-color: ${isSubscribe ? colors.GRAY_500 : colors.YELLOW_500}; + + font-size: 3.5rem; + font-weight: 700; + line-height: 3.5rem; + color: ${colors.WHITE}; +`; + +export { subscribeButton }; diff --git a/frontend/src/components/SubscribeButton/SubscribeButton.tsx b/frontend/src/components/SubscribeButton/SubscribeButton.tsx new file mode 100644 index 00000000..7a23883b --- /dev/null +++ b/frontend/src/components/SubscribeButton/SubscribeButton.tsx @@ -0,0 +1,18 @@ +import { useTheme } from '@emotion/react'; +import { useState } from 'react'; + +import Button from '@/components/@common/Button/Button'; + +import { subscribeButton } from './SubscribeButton.styles'; + +function SubscribeButton() { + const [isSubscribe, setSubscribe] = useState(false); + + const theme = useTheme(); + + return ( + + ); +} + +export default SubscribeButton; From d645b1205b0186c0f67489749dcb47d24e2d5759 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 20 Jul 2022 13:23:27 +0900 Subject: [PATCH 0233/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=EC=97=90=20=EA=B5=AC=EB=8F=85=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/CategoryItem/CategoryItem.styles.ts | 7 ++++++- frontend/src/components/CategoryItem/CategoryItem.tsx | 11 ++++++++--- .../components/CategoryList/CategoryList.styles.ts | 7 ++++++- frontend/src/components/CategoryList/CategoryList.tsx | 7 ++++--- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/CategoryItem/CategoryItem.styles.ts b/frontend/src/components/CategoryItem/CategoryItem.styles.ts index 576d3fdc..37a15b49 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.styles.ts +++ b/frontend/src/components/CategoryItem/CategoryItem.styles.ts @@ -11,4 +11,9 @@ const categoryItem = ({ colors, flex }: Theme) => css` font-size: 4rem; `; -export { categoryItem }; +const item = css` + flex: 1 1 0; + text-align: center; +`; + +export { categoryItem, item }; diff --git a/frontend/src/components/CategoryItem/CategoryItem.tsx b/frontend/src/components/CategoryItem/CategoryItem.tsx index c2eedc38..ae3904b7 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.tsx +++ b/frontend/src/components/CategoryItem/CategoryItem.tsx @@ -2,7 +2,9 @@ import { useTheme } from '@emotion/react'; import { CategoryType } from '@/@types/category'; -import { categoryItem } from './CategoryItem.styles'; +import SubscribeButton from '@/components/SubscribeButton/SubscribeButton'; + +import { categoryItem, item } from './CategoryItem.styles'; interface CategoryItemProps { category: CategoryType; @@ -13,8 +15,11 @@ function CategoryItem({ category }: CategoryItemProps) { return (
- {category.createdAt.split('T')[0]} - {category.name} + {category.createdAt.split('T')[0]} + {category.name} +
+ +
); } diff --git a/frontend/src/components/CategoryList/CategoryList.styles.ts b/frontend/src/components/CategoryList/CategoryList.styles.ts index 1f6570fb..861bc11c 100644 --- a/frontend/src/components/CategoryList/CategoryList.styles.ts +++ b/frontend/src/components/CategoryList/CategoryList.styles.ts @@ -22,4 +22,9 @@ const intersectTarget = css` height: 10rem; `; -export { categoryTable, categoryTableHeader, intersectTarget }; +const item = css` + flex: 1 1 0; + text-align: center; +`; + +export { categoryTable, categoryTableHeader, intersectTarget, item }; diff --git a/frontend/src/components/CategoryList/CategoryList.tsx b/frontend/src/components/CategoryList/CategoryList.tsx index bd2b1110..64c05358 100644 --- a/frontend/src/components/CategoryList/CategoryList.tsx +++ b/frontend/src/components/CategoryList/CategoryList.tsx @@ -7,7 +7,7 @@ import { CategoriesGetResponseType, CategoryType } from '@/@types/category'; import CategoryItem from '@/components/CategoryItem/CategoryItem'; -import { categoryTable, categoryTableHeader, intersectTarget } from './CategoryList.styles'; +import { categoryTable, categoryTableHeader, intersectTarget, item } from './CategoryList.styles'; interface CategoryListProps { categoryList: CategoryType[]; @@ -25,8 +25,9 @@ function CategoryList({ categoryList, getMoreCategories, hasNextPage }: Category return (
- 생성 날짜 - 카테고리 이름 + 생성 날짜 + 카테고리 이름 + 구독 상태
{categoryList.map((category) => ( From 892c1371e33f123030c100571a60c5dd7d0c6792 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 20 Jul 2022 15:21:31 +0900 Subject: [PATCH 0234/1011] =?UTF-8?q?feat:=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20api=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/@types/subscription.ts | 16 ++++++++++ frontend/src/api/subscription.ts | 25 +++++++++++++++ frontend/src/constants/index.ts | 1 + frontend/src/mocks/data.ts | 49 ++++++++++++++++++++++++++++- frontend/src/mocks/handlers.ts | 7 ++++- 5 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 frontend/src/@types/subscription.ts create mode 100644 frontend/src/api/subscription.ts diff --git a/frontend/src/@types/subscription.ts b/frontend/src/@types/subscription.ts new file mode 100644 index 00000000..03a767a5 --- /dev/null +++ b/frontend/src/@types/subscription.ts @@ -0,0 +1,16 @@ +interface SubscriptionType { + category: { + id: number; + name: string; + creator: { + displayName: string; + email: string; + id: number; + profileImageUri: string; + }; + createdAt: string; + }; + color: string; +} + +export { SubscriptionType }; diff --git a/frontend/src/api/subscription.ts b/frontend/src/api/subscription.ts new file mode 100644 index 00000000..d436b5e7 --- /dev/null +++ b/frontend/src/api/subscription.ts @@ -0,0 +1,25 @@ +import axios from 'axios'; + +import { SubscriptionType } from '@/@types/subscription'; + +const subscriptionApi = { + getEndpoint: '/api/members/me/subscriptions', + + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + + get: async (accessToken: string | null) => { + const response = await axios.get(subscriptionApi.getEndpoint, { + headers: { ...subscriptionApi.headers, Authorization: `Bearer ${accessToken}` }, + transformResponse: (res) => { + return JSON.parse(res).subscriptions; + }, + }); + + return response; + }, +}; + +export default subscriptionApi; diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index e6d1c356..788c048e 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -12,6 +12,7 @@ const CACHE_KEY = { ENTER: 'enter', SCHEDULES: 'schedules', PROFILE: 'profile', + SUBSCRIPTIONS: 'subscriptions', }; const STORAGE_KEY = { diff --git a/frontend/src/mocks/data.ts b/frontend/src/mocks/data.ts index d41f32bb..2c1176e7 100644 --- a/frontend/src/mocks/data.ts +++ b/frontend/src/mocks/data.ts @@ -125,4 +125,51 @@ const profileDB = { }, }; -export { scheduleDB, categoryDB, profileDB }; +const subscriptionDB = { + subscriptions: [ + { + category: { + id: 1, + name: 'BE 일정', + creator: { + id: 1, + email: 'example@email.com', + displayName: 'example', + profileImageUri: '/image.png', + }, + createdAt: '2022-07-19T16:42', + }, + color: '#ffffff', + }, + { + category: { + id: 2, + name: 'BE 일정', + creator: { + id: 1, + email: 'example@email.com', + displayName: 'example', + profileImageUri: '/image.png', + }, + createdAt: '2022-07-19T16:42', + }, + color: '#123423', + }, + { + category: { + id: 5, + name: '카테고리 5', + creator: { + id: 1, + email: 'example@email.com', + displayName: 'example', + profileImageUri: '/image.png', + }, + createdAt: '2022-07-19T16:42', + }, + color: '#876453', + }, + ], +}; + +export { scheduleDB, categoryDB, profileDB, subscriptionDB }; diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 77391c51..4fa424ae 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -6,8 +6,9 @@ import { CategoryType } from '@/@types/category'; import categoryApi from '@/api/category'; import profileApi from '@/api/profile'; import scheduleApi from '@/api/schedule'; +import subscriptionApi from '@/api/subscription'; -import { categoryDB, profileDB, scheduleDB } from './data'; +import { categoryDB, profileDB, scheduleDB, subscriptionDB } from './data'; const handlers = [ rest.get(categoryApi.endpoint, (req, res, ctx) => { @@ -48,6 +49,10 @@ const handlers = [ return res(ctx.status(201)); }), + + rest.get(subscriptionApi.getEndpoint, (req, res, ctx) => { + return res(ctx.status(200), ctx.json(subscriptionDB)); + }), ]; export { handlers }; From 0b94e96c6a32a657c59218dae2d3f52d0899f8b6 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 20 Jul 2022 15:22:39 +0900 Subject: [PATCH 0235/1011] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20import=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/CategoryPage/CategoryPage.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/pages/CategoryPage/CategoryPage.tsx b/frontend/src/pages/CategoryPage/CategoryPage.tsx index 67a98b6b..fd7684dc 100644 --- a/frontend/src/pages/CategoryPage/CategoryPage.tsx +++ b/frontend/src/pages/CategoryPage/CategoryPage.tsx @@ -1,4 +1,3 @@ -import { useTheme } from '@emotion/react'; import { AxiosError, AxiosResponse } from 'axios'; import { useInfiniteQuery } from 'react-query'; From bc519ed2f5954052cb391aa37e6706c8897e9c82 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 20 Jul 2022 15:23:53 +0900 Subject: [PATCH 0236/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=EC=97=90=EC=84=9C=20=EA=B5=AC?= =?UTF-8?q?=EB=8F=85=20=EC=83=81=ED=83=9C=20=ED=91=9C=ED=98=84=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/CategoryItem/CategoryItem.tsx | 5 +-- .../components/CategoryList/CategoryList.tsx | 31 ++++++++++++++++--- .../SubscribeButton.stories.tsx | 5 ++- .../SubscribeButton/SubscribeButton.tsx | 14 +++++++-- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/CategoryItem/CategoryItem.tsx b/frontend/src/components/CategoryItem/CategoryItem.tsx index ae3904b7..69e94495 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.tsx +++ b/frontend/src/components/CategoryItem/CategoryItem.tsx @@ -8,9 +8,10 @@ import { categoryItem, item } from './CategoryItem.styles'; interface CategoryItemProps { category: CategoryType; + isSubscribing: boolean; } -function CategoryItem({ category }: CategoryItemProps) { +function CategoryItem({ category, isSubscribing }: CategoryItemProps) { const theme = useTheme(); return ( @@ -18,7 +19,7 @@ function CategoryItem({ category }: CategoryItemProps) { {category.createdAt.split('T')[0]} {category.name}
- +
); diff --git a/frontend/src/components/CategoryList/CategoryList.tsx b/frontend/src/components/CategoryList/CategoryList.tsx index 64c05358..495bc40b 100644 --- a/frontend/src/components/CategoryList/CategoryList.tsx +++ b/frontend/src/components/CategoryList/CategoryList.tsx @@ -1,12 +1,20 @@ import { AxiosError, AxiosResponse } from 'axios'; -import { FetchNextPageOptions, InfiniteQueryObserverResult } from 'react-query'; +import { FetchNextPageOptions, InfiniteQueryObserverResult, useQuery } from 'react-query'; +import { useRecoilValue } from 'recoil'; import useIntersect from '@/hooks/useIntersect'; import { CategoriesGetResponseType, CategoryType } from '@/@types/category'; +import { SubscriptionType } from '@/@types/subscription'; + +import { userState } from '@/atoms'; import CategoryItem from '@/components/CategoryItem/CategoryItem'; +import { CACHE_KEY } from '@/constants'; + +import subscriptionApi from '@/api/subscription'; + import { categoryTable, categoryTableHeader, intersectTarget, item } from './CategoryList.styles'; interface CategoryListProps { @@ -18,10 +26,23 @@ interface CategoryListProps { } function CategoryList({ categoryList, getMoreCategories, hasNextPage }: CategoryListProps) { + const { accessToken } = useRecoilValue(userState); + + const { data: subscriptionsGetResponse } = useQuery< + AxiosResponse, + AxiosError + >(CACHE_KEY.SUBSCRIPTIONS, () => subscriptionApi.get(accessToken)); + const ref = useIntersect(() => { hasNextPage && getMoreCategories(); }); + if (subscriptionsGetResponse === undefined) { + return
; + } + + const subscriptions = subscriptionsGetResponse.data.map((el) => el.category.id); + return (
@@ -29,9 +50,11 @@ function CategoryList({ categoryList, getMoreCategories, hasNextPage }: Category 카테고리 이름 구독 상태
- {categoryList.map((category) => ( - - ))} + {categoryList.map((category) => { + const isSubscribing = subscriptions.includes(category.id); + + return ; + })}
); diff --git a/frontend/src/components/SubscribeButton/SubscribeButton.stories.tsx b/frontend/src/components/SubscribeButton/SubscribeButton.stories.tsx index 9d970d1f..2fc7f66f 100644 --- a/frontend/src/components/SubscribeButton/SubscribeButton.stories.tsx +++ b/frontend/src/components/SubscribeButton/SubscribeButton.stories.tsx @@ -7,6 +7,9 @@ export default { component: SubscribeButton, } as ComponentMeta; -const Template: ComponentStory = () => ; +const Template: ComponentStory = (args) => ; export const Primary = Template.bind({}); +Primary.args = { + isSubscribing: true, +}; diff --git a/frontend/src/components/SubscribeButton/SubscribeButton.tsx b/frontend/src/components/SubscribeButton/SubscribeButton.tsx index 7a23883b..fbb2fc4d 100644 --- a/frontend/src/components/SubscribeButton/SubscribeButton.tsx +++ b/frontend/src/components/SubscribeButton/SubscribeButton.tsx @@ -1,15 +1,23 @@ import { useTheme } from '@emotion/react'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import Button from '@/components/@common/Button/Button'; import { subscribeButton } from './SubscribeButton.styles'; -function SubscribeButton() { - const [isSubscribe, setSubscribe] = useState(false); +interface SubscribeButtonProps { + isSubscribing: boolean; +} + +function SubscribeButton({ isSubscribing }: SubscribeButtonProps) { + const [isSubscribe, setSubscribe] = useState(isSubscribing); const theme = useTheme(); + useEffect(() => { + setSubscribe(isSubscribing); + }, [isSubscribing]); + return ( ); From 3cc99177d5266d9c5bcf441f8bc9d636d4f8b888 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 20 Jul 2022 16:31:47 +0900 Subject: [PATCH 0237/1011] =?UTF-8?q?feat:=20=EA=B5=AC=EB=8F=85=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20api=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20mockData=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/subscription.ts | 13 +++++++++++++ frontend/src/mocks/data.ts | 4 ++-- frontend/src/mocks/handlers.ts | 22 ++++++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/frontend/src/api/subscription.ts b/frontend/src/api/subscription.ts index d436b5e7..befd9cab 100644 --- a/frontend/src/api/subscription.ts +++ b/frontend/src/api/subscription.ts @@ -4,6 +4,7 @@ import { SubscriptionType } from '@/@types/subscription'; const subscriptionApi = { getEndpoint: '/api/members/me/subscriptions', + postEndpoint: (categoryId: number) => `/api/members/me/categories/${categoryId}/subscriptions`, headers: { 'Content-Type': 'application/json', @@ -20,6 +21,18 @@ const subscriptionApi = { return response; }, + + post: async ( + accessToken: string | null, + categoryId: number, + body: Pick + ) => { + const response = await axios.post(subscriptionApi.postEndpoint(categoryId), body, { + headers: { ...subscriptionApi.headers, Authorization: `Bearer ${accessToken}` }, + }); + + return response; + }, }; export default subscriptionApi; diff --git a/frontend/src/mocks/data.ts b/frontend/src/mocks/data.ts index 2c1176e7..8953c7c9 100644 --- a/frontend/src/mocks/data.ts +++ b/frontend/src/mocks/data.ts @@ -130,7 +130,7 @@ const subscriptionDB = { { category: { id: 1, - name: 'BE 일정', + name: 'BE 공식일정', creator: { id: 1, email: 'example@email.com', @@ -144,7 +144,7 @@ const subscriptionDB = { { category: { id: 2, - name: 'BE 일정', + name: '알록달록 팀 회의', creator: { id: 1, email: 'example@email.com', diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 4fa424ae..5e857226 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -2,6 +2,7 @@ import { rest } from 'msw'; import { Schedule } from '@/@types'; import { CategoryType } from '@/@types/category'; +import { SubscriptionType } from '@/@types/subscription'; import categoryApi from '@/api/category'; import profileApi from '@/api/profile'; @@ -53,6 +54,27 @@ const handlers = [ rest.get(subscriptionApi.getEndpoint, (req, res, ctx) => { return res(ctx.status(200), ctx.json(subscriptionDB)); }), + + rest.post>( + `/api/members/me/categories/:id/subscriptions`, + (req, res, ctx) => { + const { id } = req.params; + const categoryId = parseInt(id as string); + const newSubscription = { + category: { + id: categoryDB.data[categoryId - 1].id, + name: categoryDB.data[categoryId - 1].name, + creator: profileDB.data, + createdAt: categoryDB.data[categoryId - 1].createdAt, + }, + color: req.body.color, + }; + + subscriptionDB.subscriptions.push(newSubscription); + + return res(ctx.status(201), ctx.json(newSubscription)); + } + ), ]; export { handlers }; From ebf37a9367b811e6a79e1e34406936dbc0d0d9e2 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 20 Jul 2022 16:52:44 +0900 Subject: [PATCH 0238/1011] =?UTF-8?q?feat:=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SubscribeButton/SubscribeButton.styles.ts | 4 ++-- .../components/SubscribeButton/SubscribeButton.tsx | 14 +++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/SubscribeButton/SubscribeButton.styles.ts b/frontend/src/components/SubscribeButton/SubscribeButton.styles.ts index d88efcac..d33b6460 100644 --- a/frontend/src/components/SubscribeButton/SubscribeButton.styles.ts +++ b/frontend/src/components/SubscribeButton/SubscribeButton.styles.ts @@ -1,11 +1,11 @@ import { css, Theme } from '@emotion/react'; -const subscribeButton = ({ colors }: Theme, isSubscribe: boolean) => css` +const subscribeButton = ({ colors }: Theme, isSubscribing: boolean) => css` width: 15rem; height: 8rem; border-radius: 3px; - background-color: ${isSubscribe ? colors.GRAY_500 : colors.YELLOW_500}; + background-color: ${isSubscribing ? colors.GRAY_500 : colors.YELLOW_500}; font-size: 3.5rem; font-weight: 700; diff --git a/frontend/src/components/SubscribeButton/SubscribeButton.tsx b/frontend/src/components/SubscribeButton/SubscribeButton.tsx index fbb2fc4d..e9f96b46 100644 --- a/frontend/src/components/SubscribeButton/SubscribeButton.tsx +++ b/frontend/src/components/SubscribeButton/SubscribeButton.tsx @@ -1,5 +1,4 @@ import { useTheme } from '@emotion/react'; -import { useEffect, useState } from 'react'; import Button from '@/components/@common/Button/Button'; @@ -7,19 +6,16 @@ import { subscribeButton } from './SubscribeButton.styles'; interface SubscribeButtonProps { isSubscribing: boolean; + handleClickSubscribeButton: () => void; } -function SubscribeButton({ isSubscribing }: SubscribeButtonProps) { - const [isSubscribe, setSubscribe] = useState(isSubscribing); - +function SubscribeButton({ isSubscribing, handleClickSubscribeButton }: SubscribeButtonProps) { const theme = useTheme(); - useEffect(() => { - setSubscribe(isSubscribing); - }, [isSubscribing]); - return ( - + ); } From fe3f9339b8947115c3582961aa505b4986273007 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 20 Jul 2022 16:53:24 +0900 Subject: [PATCH 0239/1011] =?UTF-8?q?feat:=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=EC=84=B1=EA=B3=B5=20=EC=8B=9C=20=EA=B5=AC=EB=8F=85=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EB=8B=A4=EC=8B=9C=20get=ED=95=98=EB=8F=84=EB=A1=9D?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/CategoryItem/CategoryItem.tsx | 39 ++++++++++++++++++- .../components/CategoryList/CategoryList.tsx | 11 +++++- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/CategoryItem/CategoryItem.tsx b/frontend/src/components/CategoryItem/CategoryItem.tsx index 69e94495..38494180 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.tsx +++ b/frontend/src/components/CategoryItem/CategoryItem.tsx @@ -1,25 +1,60 @@ import { useTheme } from '@emotion/react'; +import { AxiosError, AxiosResponse } from 'axios'; +import { QueryObserverResult, RefetchOptions, RefetchQueryFilters, useMutation } from 'react-query'; +import { useRecoilValue } from 'recoil'; import { CategoryType } from '@/@types/category'; +import { SubscriptionType } from '@/@types/subscription'; + +import { userState } from '@/atoms'; import SubscribeButton from '@/components/SubscribeButton/SubscribeButton'; +import subscriptionApi from '@/api/subscription'; + import { categoryItem, item } from './CategoryItem.styles'; interface CategoryItemProps { category: CategoryType; isSubscribing: boolean; + refetch: ( + options?: (RefetchOptions & RefetchQueryFilters) | undefined + ) => Promise, AxiosError>>; } -function CategoryItem({ category, isSubscribing }: CategoryItemProps) { +function CategoryItem({ category, isSubscribing, refetch }: CategoryItemProps) { const theme = useTheme(); + const { accessToken } = useRecoilValue(userState); + + const body = { + color: '#ffffff', + }; + + const { mutate } = useMutation< + AxiosResponse>, + AxiosError, + Pick, + unknown + >(() => subscriptionApi.post(accessToken, category.id, body), { + onSuccess: () => { + refetch(); + }, + }); + + const handleClickSubscribeButton = () => { + !isSubscribing && mutate(body); + }; + return (
{category.createdAt.split('T')[0]} {category.name}
- +
); diff --git a/frontend/src/components/CategoryList/CategoryList.tsx b/frontend/src/components/CategoryList/CategoryList.tsx index 495bc40b..6fdace10 100644 --- a/frontend/src/components/CategoryList/CategoryList.tsx +++ b/frontend/src/components/CategoryList/CategoryList.tsx @@ -28,7 +28,7 @@ interface CategoryListProps { function CategoryList({ categoryList, getMoreCategories, hasNextPage }: CategoryListProps) { const { accessToken } = useRecoilValue(userState); - const { data: subscriptionsGetResponse } = useQuery< + const { data: subscriptionsGetResponse, refetch: refetchSubscriptions } = useQuery< AxiosResponse, AxiosError >(CACHE_KEY.SUBSCRIPTIONS, () => subscriptionApi.get(accessToken)); @@ -53,7 +53,14 @@ function CategoryList({ categoryList, getMoreCategories, hasNextPage }: Category {categoryList.map((category) => { const isSubscribing = subscriptions.includes(category.id); - return ; + return ( + + ); })}
From 77b010be675967297cdb6627927399cc37007e27 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 20 Jul 2022 17:00:41 +0900 Subject: [PATCH 0240/1011] =?UTF-8?q?chore:=20storybook=20recoilRoot=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/.storybook/preview.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/frontend/.storybook/preview.js b/frontend/.storybook/preview.js index 4e9f7e43..88d5c9c6 100644 --- a/frontend/.storybook/preview.js +++ b/frontend/.storybook/preview.js @@ -1,5 +1,6 @@ import { ThemeProvider } from '@emotion/react'; import { QueryClient, QueryClientProvider } from 'react-query'; +import { RecoilRoot } from 'recoil'; import GlobalStyle from '@/styles/GlobalStyle'; import theme from '@/styles/theme'; @@ -18,11 +19,13 @@ export const parameters = { export const decorators = [ (Story) => ( - - - - - - + + + + + + + + ), ]; From 8335facaf1438de86443a720175c7c7d180672b5 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 16:59:14 +0900 Subject: [PATCH 0241/1011] =?UTF-8?q?refactor(Category):=20service=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=20=ED=83=80=EC=9E=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/controller/CategoryController.java | 11 +++-------- .../dallog/category/service/CategoryService.java | 11 +++++++---- .../dallog/category/service/CategoryServiceTest.java | 10 +++++----- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index b520bf79..cb844b31 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -7,7 +7,6 @@ import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; import java.net.URI; -import java.util.List; import javax.validation.Valid; import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; @@ -36,16 +35,12 @@ public ResponseEntity save(@AuthenticationPrincipal final Logi @GetMapping public ResponseEntity findAll(Pageable pageable) { - int pageNumber = pageable.getPageNumber(); - List categoryResponses = categoryService.findAll(pageable); - return ResponseEntity.ok(new CategoriesResponse(pageNumber, categoryResponses)); + return ResponseEntity.ok(categoryService.findAll(pageable)); } @GetMapping("/me") public ResponseEntity findMine(@AuthenticationPrincipal final LoginMember loginMember, - Pageable pageable) { - int pageNumber = pageable.getPageNumber(); - List categoryResponses = categoryService.findMine(loginMember.getId(), pageable); - return ResponseEntity.ok(new CategoriesResponse(pageNumber, categoryResponses)); + final Pageable pageable) { + return ResponseEntity.ok(categoryService.findMine(loginMember.getId(), pageable)); } } diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index d3ab4a68..37331a53 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -3,6 +3,7 @@ import com.allog.dallog.category.domain.Category; import com.allog.dallog.category.domain.CategoryRepository; import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.dto.response.CategoriesResponse; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.exception.NoSuchCategoryException; import com.allog.dallog.member.domain.Member; @@ -32,20 +33,22 @@ public CategoryResponse save(final Long memberId, final CategoryCreateRequest re return new CategoryResponse(category); } - public List findAll(final Pageable pageable) { - return categoryRepository.findSliceBy(pageable) + public CategoriesResponse findAll(final Pageable pageable) { + List categoryResponses = categoryRepository.findSliceBy(pageable) .getContent() .stream() .map(CategoryResponse::new) .collect(Collectors.toList()); + return new CategoriesResponse(pageable.getPageNumber(), categoryResponses); } - public List findMine(final Long memberId, final Pageable pageable) { - return categoryRepository.findSliceByMemberId(pageable, memberId) + public CategoriesResponse findMine(final Long memberId, final Pageable pageable) { + List categoryResponses = categoryRepository.findSliceByMemberId(pageable, memberId) .getContent() .stream() .map(CategoryResponse::new) .collect(Collectors.toList()); + return new CategoriesResponse(pageable.getPageNumber(), categoryResponses); } public CategoryResponse findById(final Long id) { diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index f268a374..e44beb05 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -8,11 +8,11 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.dto.response.CategoriesResponse; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.exception.InvalidCategoryException; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; -import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -74,10 +74,10 @@ class CategoryServiceTest { PageRequest request = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); // when - List response = categoryService.findAll(request); + CategoriesResponse response = categoryService.findAll(request); // then - assertThat(response) + assertThat(response.getCategories()) .hasSize(PAGE_SIZE) .extracting(CategoryResponse::getName) .contains("알록달록 회의", "지원플랫폼 근로"); @@ -98,10 +98,10 @@ class CategoryServiceTest { PageRequest request = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); // when - List response = categoryService.findMine(memberId, request); + CategoriesResponse response = categoryService.findMine(memberId, request); // then - assertThat(response) + assertThat(response.getCategories()) .hasSize(PAGE_SIZE) .extracting(CategoryResponse::getName) .contains("알록달록 회의", "지원플랫폼 근로"); From 9f53eaccb2b942215e7bde3e7f26cb661feceff5 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 17:02:09 +0900 Subject: [PATCH 0242/1011] =?UTF-8?q?refactor(Category):=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=8B=9C=EA=B7=B8=EB=8B=88=EC=B2=98=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/acceptance/CategoryAcceptanceTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 92bdb550..d6f0523f 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -77,7 +77,8 @@ public class CategoryAcceptanceTest extends AcceptanceTest { int page = 0; // when - ExtractableResponse response = 내가_등록한_카테고리를_페이징을_통해_조회한다(tokenResponse, page, PAGE_SIZE); + ExtractableResponse response + = 내가_등록한_카테고리를_페이징을_통해_조회한다(tokenResponse.getAccessToken(), page, PAGE_SIZE); CategoriesResponse categoriesResponse = response.as(CategoriesResponse.class); // then @@ -88,10 +89,10 @@ public class CategoryAcceptanceTest extends AcceptanceTest { }); } - private ExtractableResponse 내가_등록한_카테고리를_페이징을_통해_조회한다(final TokenResponse tokenResponse, final int page, + private ExtractableResponse 내가_등록한_카테고리를_페이징을_통해_조회한다(final String accessToken, final int page, final int size) { return RestAssured.given().log().all() - .auth().oauth2(tokenResponse.getAccessToken()) + .auth().oauth2(accessToken) .when().get("/api/categories/me?page={page}&size={size}", page, size) .then().log().all() .extract(); From e532d61ea3f8b974e8fd73c8b51122b9b118d8ce Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 20 Jul 2022 17:29:28 +0900 Subject: [PATCH 0243/1011] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EC=83=81=ED=83=9C=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EB=82=B4?= =?UTF-8?q?=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=20=EB=B0=94=20=EB=A9=94?= =?UTF-8?q?=EB=89=B4=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/NavBar/NavBar.styles.ts | 46 +++++++++++++++++-- frontend/src/components/NavBar/NavBar.tsx | 32 +++++++++++-- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/NavBar/NavBar.styles.ts b/frontend/src/components/NavBar/NavBar.styles.ts index 557c7339..2647e1f2 100644 --- a/frontend/src/components/NavBar/NavBar.styles.ts +++ b/frontend/src/components/NavBar/NavBar.styles.ts @@ -3,25 +3,65 @@ import { css, Theme } from '@emotion/react'; const navBar = ({ colors, flex }: Theme) => css` ${flex.row} + justify-content: space-between; position: fixed; top: 0; left: 0; width: 100%; height: 16rem; - padding: 2rem; + padding: 2rem 5rem; background: ${colors.WHITE}; box-shadow: 0 4px 4px rgba(0, 0, 0, 0.25); `; -const loginButton = ({ colors }: Theme) => css` +const menus = ({ flex }: Theme) => css` + ${flex.row} + + gap: 3rem; +`; + +const menu = ({ colors }: Theme) => css` + position: relative; + background: transparent; font-size: 5rem; font-weight: bold; color: ${colors.GRAY_700}; + + &:hover span { + visibility: visible; + } +`; + +const loginButton = ({ colors }: Theme) => css` + border-radius: 1rem; + + background: ${colors.YELLOW_500}; + padding: 2rem 4rem; + + font-size: 4rem; + color: ${colors.WHITE}; +`; + +const menuTitle = ({ colors }: Theme) => css` + visibility: hidden; + position: absolute; + top: 120%; + left: 50%; + transform: translateX(-50%); + + padding: 2rem 3rem; + + background: ${colors.GRAY_700}; + + font-size: 3rem; + font-weight: normal; + color: ${colors.WHITE}; + white-space: nowrap; `; -export { loginButton, navBar }; +export { loginButton, menu, menus, menuTitle, navBar }; diff --git a/frontend/src/components/NavBar/NavBar.tsx b/frontend/src/components/NavBar/NavBar.tsx index e72dd642..8567f87a 100644 --- a/frontend/src/components/NavBar/NavBar.tsx +++ b/frontend/src/components/NavBar/NavBar.tsx @@ -1,21 +1,45 @@ import { useTheme } from '@emotion/react'; +import { useRecoilState } from 'recoil'; + +import { userState } from '@/atoms'; import Button from '@/components/@common/Button/Button'; -import { loginButton, navBar } from './NavBar.styles'; +import { BiCategory } from 'react-icons/bi'; +import { FaUserCircle } from 'react-icons/fa'; + +import { loginButton, menu, menus, menuTitle, navBar } from './NavBar.styles'; interface NavBarProps { openLoginModal?: () => void; } function NavBar({ openLoginModal }: NavBarProps) { + const [user] = useRecoilState(userState); const theme = useTheme(); return (
- + +
+ {!user.accessToken && ( + + )} + {user.accessToken && ( + <> + + + + )} +
); } From 94b1307568c097360aee779e5c6df1dba1b57c9c Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 20 Jul 2022 17:34:10 +0900 Subject: [PATCH 0244/1011] =?UTF-8?q?feat:=20=EB=82=B4=EB=B9=84=EA=B2=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EB=B0=94=20=EB=A9=94=EB=89=B4=20=ED=81=B4?= =?UTF-8?q?=EB=A6=AD=20=EC=8B=9C=20=EB=8C=80=EC=9D=91=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/NavBar/NavBar.tsx | 24 ++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/NavBar/NavBar.tsx b/frontend/src/components/NavBar/NavBar.tsx index 8567f87a..c701e6f6 100644 --- a/frontend/src/components/NavBar/NavBar.tsx +++ b/frontend/src/components/NavBar/NavBar.tsx @@ -1,10 +1,13 @@ import { useTheme } from '@emotion/react'; +import { useNavigate } from 'react-router-dom'; import { useRecoilState } from 'recoil'; import { userState } from '@/atoms'; import Button from '@/components/@common/Button/Button'; +import { PATH } from '@/constants'; + import { BiCategory } from 'react-icons/bi'; import { FaUserCircle } from 'react-icons/fa'; @@ -17,10 +20,25 @@ interface NavBarProps { function NavBar({ openLoginModal }: NavBarProps) { const [user] = useRecoilState(userState); const theme = useTheme(); + const navigate = useNavigate(); + + const handleClickLogoButton = () => { + navigate(PATH.MAIN); + }; + + const handleClickCategoryMenuButton = () => { + navigate(PATH.CATEGORY); + }; + + const handleClickProfileMenuButton = () => { + navigate(PATH.PROFILE); + }; return (
- +
{!user.accessToken && ( - From 9acf7640cdd30ee8d2d5e8722783d96db5f6f29c Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 20 Jul 2022 19:42:13 +0900 Subject: [PATCH 0245/1011] =?UTF-8?q?refactor:=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.tsx | 11 +++++- .../src/components/PageLayout/PageLayout.tsx | 19 ----------- .../CalendarPage/CalendarPage.styles.ts} | 4 +-- .../src/pages/CalendarPage/CalendarPage.tsx | 7 ++-- .../pages/CategoryPage/CategoryPage.styles.ts | 1 + .../src/pages/CategoryPage/CategoryPage.tsx | 21 +++++------- frontend/src/pages/MainPage/MainPage.tsx | 9 +++-- frontend/src/pages/MyPage/MyPage.styles.ts | 2 ++ frontend/src/pages/MyPage/MyPage.tsx | 34 ++++++++----------- frontend/src/pages/StartPage/StartPage.tsx | 16 ++++----- frontend/src/styles/GlobalStyle.tsx | 2 ++ 11 files changed, 60 insertions(+), 66 deletions(-) delete mode 100644 frontend/src/components/PageLayout/PageLayout.tsx rename frontend/src/{components/PageLayout/PageLayout.styles.ts => pages/CalendarPage/CalendarPage.styles.ts} (61%) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 02a17a34..e94d782b 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,5 +1,8 @@ import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'; +import useModal from '@/hooks/useModal'; + +import NavBar from '@/components/NavBar/NavBar'; import ProtectRoute from '@/components/ProtectRoute'; import AuthPage from '@/pages/AuthPage/AuthPage'; import CategoryPage from '@/pages/CategoryPage/CategoryPage'; @@ -9,10 +12,16 @@ import MyPage from '@/pages/MyPage/MyPage'; import { PATH } from '@/constants'; function App() { + const { isOpen, openModal, closeModal } = useModal(); + return ( + - } /> + } + /> } /> }> } /> diff --git a/frontend/src/components/PageLayout/PageLayout.tsx b/frontend/src/components/PageLayout/PageLayout.tsx deleted file mode 100644 index a96a5487..00000000 --- a/frontend/src/components/PageLayout/PageLayout.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import NavBar from '@/components/NavBar/NavBar'; - -import { content } from './PageLayout.styles'; - -interface PageLayoutProps { - openLoginModal?: () => void; - children: JSX.Element | JSX.Element[]; -} - -function PageLayout({ openLoginModal, children }: PageLayoutProps) { - return ( - <> - -
{children}
- - ); -} - -export default PageLayout; diff --git a/frontend/src/components/PageLayout/PageLayout.styles.ts b/frontend/src/pages/CalendarPage/CalendarPage.styles.ts similarity index 61% rename from frontend/src/components/PageLayout/PageLayout.styles.ts rename to frontend/src/pages/CalendarPage/CalendarPage.styles.ts index e4c8334a..d52c7b07 100644 --- a/frontend/src/components/PageLayout/PageLayout.styles.ts +++ b/frontend/src/pages/CalendarPage/CalendarPage.styles.ts @@ -1,8 +1,8 @@ import { css } from '@emotion/react'; -const content = css` +const calendarPage = css` margin-top: 16rem; padding: 2rem; `; -export { content }; +export { calendarPage }; diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index 7822474c..630abd30 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -7,7 +7,6 @@ import { Schedule } from '@/@types'; import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; import Calendar from '@/components/Calendar/Calendar'; -import PageLayout from '@/components/PageLayout/PageLayout'; import ScheduleAddButton from '@/components/ScheduleAddButton/ScheduleAddButton'; import ScheduleAddModal from '@/components/ScheduleAddModal/ScheduleAddModal'; @@ -15,6 +14,8 @@ import { CACHE_KEY } from '@/constants'; import scheduleApi from '@/api/schedule'; +import { calendarPage } from './CalendarPage.styles'; + function CalendarPage() { const { isLoading, @@ -37,13 +38,13 @@ function CalendarPage() { } return ( - +
- +
); } diff --git a/frontend/src/pages/CategoryPage/CategoryPage.styles.ts b/frontend/src/pages/CategoryPage/CategoryPage.styles.ts index 361714a5..62dd9348 100644 --- a/frontend/src/pages/CategoryPage/CategoryPage.styles.ts +++ b/frontend/src/pages/CategoryPage/CategoryPage.styles.ts @@ -5,6 +5,7 @@ const categoryPage = ({ flex }: Theme) => css` align-items: center; + margin-top: 16rem; padding: 10rem 20rem; `; diff --git a/frontend/src/pages/CategoryPage/CategoryPage.tsx b/frontend/src/pages/CategoryPage/CategoryPage.tsx index fd7684dc..df7ee135 100644 --- a/frontend/src/pages/CategoryPage/CategoryPage.tsx +++ b/frontend/src/pages/CategoryPage/CategoryPage.tsx @@ -5,7 +5,6 @@ import { CategoriesGetResponseType } from '@/@types/category'; import FieldSet from '@/components/@common/FieldSet/FieldSet'; import CategoryList from '@/components/CategoryList/CategoryList'; -import PageLayout from '@/components/PageLayout/PageLayout'; import { API, CACHE_KEY } from '@/constants'; @@ -43,18 +42,16 @@ function CategoryPage() { const categoryList = categoriesGetResponse.pages.flatMap(({ data }) => data.data); return ( - -
-
-
-
- +
+
+
- + +
); } diff --git a/frontend/src/pages/MainPage/MainPage.tsx b/frontend/src/pages/MainPage/MainPage.tsx index cbe4810c..192a281b 100644 --- a/frontend/src/pages/MainPage/MainPage.tsx +++ b/frontend/src/pages/MainPage/MainPage.tsx @@ -8,7 +8,12 @@ import StartPage from '@/pages/StartPage/StartPage'; import { getAccessToken } from '@/utils'; -function MainPage() { +interface MainPageProps { + isLoginModalOpen: boolean; + closeLoginModal: () => void; +} + +function MainPage({ isLoginModalOpen, closeLoginModal }: MainPageProps) { const [user, setUser] = useRecoilState(userState); useEffect(() => { @@ -16,7 +21,7 @@ function MainPage() { }, []); if (!user.accessToken) { - return ; + return ; } return ; diff --git a/frontend/src/pages/MyPage/MyPage.styles.ts b/frontend/src/pages/MyPage/MyPage.styles.ts index 27078b68..9ff3d661 100644 --- a/frontend/src/pages/MyPage/MyPage.styles.ts +++ b/frontend/src/pages/MyPage/MyPage.styles.ts @@ -3,6 +3,8 @@ import { css, Theme } from '@emotion/react'; const myPage = ({ colors }: Theme) => css` width: 100vw; height: 100vh; + margin-top: 16rem; + padding: 2rem; background: ${colors.GRAY_100}; `; diff --git a/frontend/src/pages/MyPage/MyPage.tsx b/frontend/src/pages/MyPage/MyPage.tsx index f076720f..f059e027 100644 --- a/frontend/src/pages/MyPage/MyPage.tsx +++ b/frontend/src/pages/MyPage/MyPage.tsx @@ -3,8 +3,6 @@ import { useQuery } from 'react-query'; import { ProfileType } from '@/@types/profile'; -import PageLayout from '@/components/PageLayout/PageLayout'; - import { CACHE_KEY } from '@/constants'; import profileAPI from '@/api/profile'; @@ -40,25 +38,23 @@ function MyPage() { const { displayName, email, profileImageUri } = profileGetResponse.data; return ( - -
-
-
프로필
-
- 이름(닉네임) - {displayName} -
-
- 계정 - {email} -
-
- 프로필 사진 - 프로필 이미지 -
+
+
+
프로필
+
+ 이름(닉네임) + {displayName} +
+
+ 계정 + {email} +
+
+ 프로필 사진 + 프로필 이미지
- +
); } diff --git a/frontend/src/pages/StartPage/StartPage.tsx b/frontend/src/pages/StartPage/StartPage.tsx index f5da2a02..187d9739 100644 --- a/frontend/src/pages/StartPage/StartPage.tsx +++ b/frontend/src/pages/StartPage/StartPage.tsx @@ -1,18 +1,18 @@ -import useModal from '@/hooks/useModal'; - import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; import LoginModal from '@/components/LoginModal/LoginModal'; -import PageLayout from '@/components/PageLayout/PageLayout'; -function StartPage() { - const { isOpen, openModal, closeModal } = useModal(); +interface StartPageProps { + isLoginModalOpen: boolean; + closeLoginModal: () => void; +} +function StartPage({ isLoginModalOpen, closeLoginModal }: StartPageProps) { return ( - - + <> + - + ); } diff --git a/frontend/src/styles/GlobalStyle.tsx b/frontend/src/styles/GlobalStyle.tsx index 4805c3f5..a1c4a64e 100644 --- a/frontend/src/styles/GlobalStyle.tsx +++ b/frontend/src/styles/GlobalStyle.tsx @@ -15,6 +15,8 @@ const global = css` } body { + overflow: overlay; + font-family: 'Pretendard', sans-serif; font-size: 3rem; } From bcbb4278977de39b1270014efc58a760a482941b Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 20 Jul 2022 20:59:04 +0900 Subject: [PATCH 0246/1011] =?UTF-8?q?feat:=20=EB=82=B4=EB=B9=84=EA=B2=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EB=B0=94=EC=97=90=20=EB=8B=AC=EB=A0=A5=20?= =?UTF-8?q?=EB=A9=94=EB=89=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/NavBar/NavBar.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/NavBar/NavBar.tsx b/frontend/src/components/NavBar/NavBar.tsx index c701e6f6..01858036 100644 --- a/frontend/src/components/NavBar/NavBar.tsx +++ b/frontend/src/components/NavBar/NavBar.tsx @@ -10,6 +10,7 @@ import { PATH } from '@/constants'; import { BiCategory } from 'react-icons/bi'; import { FaUserCircle } from 'react-icons/fa'; +import { FiCalendar } from 'react-icons/fi'; import { loginButton, menu, menus, menuTitle, navBar } from './NavBar.styles'; @@ -22,7 +23,7 @@ function NavBar({ openLoginModal }: NavBarProps) { const theme = useTheme(); const navigate = useNavigate(); - const handleClickLogoButton = () => { + const handleClickMainButton = () => { navigate(PATH.MAIN); }; @@ -36,7 +37,7 @@ function NavBar({ openLoginModal }: NavBarProps) { return (
-
@@ -47,6 +48,10 @@ function NavBar({ openLoginModal }: NavBarProps) { )} {user.accessToken && ( <> +
- {!user.accessToken && ( + {!accessToken && ( )} - {user.accessToken && ( + {accessToken && ( <> +
+ + +
{!accessToken && ( +
+
+ 우아한테크코스 FE +
+ + +
+
+
+
+ ); +} + +export default SideBar; From b3710cc45b20a031983ee761741a38c01a6c5b1d Mon Sep 17 00:00:00 2001 From: hyeonic Date: Thu, 21 Jul 2022 16:16:40 +0900 Subject: [PATCH 0266/1011] =?UTF-8?q?feat:=20=EB=8D=B0=EB=AA=A8=EB=A5=BC?= =?UTF-8?q?=20=EC=9C=84=ED=95=9C=20=EC=B4=88=EA=B8=B0=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.properties | 3 +++ backend/src/main/resources/data.sql | 26 +++++++++++++++++++ .../src/test/resources/application.properties | 3 ++- 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/resources/data.sql diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index b43ca088..1da117aa 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1,8 +1,11 @@ +spring.sql.init.mode=always spring.datasource.url=jdbc:h2:~/dallog;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE spring.datasource.username=sa spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=create +spring.jpa.defer-datasource-initialization=true +spring.h2.console.enabled=true logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE oauth.google.redirect_uri=${GOOGLE_REDIRECT_URI} oauth.google.client_id=${GOOGLE_CLIENT_ID} diff --git a/backend/src/main/resources/data.sql b/backend/src/main/resources/data.sql new file mode 100644 index 00000000..6da3b17d --- /dev/null +++ b/backend/src/main/resources/data.sql @@ -0,0 +1,26 @@ +INSERT INTO members (email, profile_image_url, display_name, social_type, created_at, updated_at) +VALUES ('admin@email.com', + 'https://thumbs.dreamstime.com/b/admin-icon-trendy-design-style-isolated-white-background-vector-simple-modern-flat-symbol-web-site-mobile-logo-app-135742404.jpg', + '어드민', 'GOOGLE', NOW(), NOW()), + ('jhy979@gmail.com', + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPVpbRmWveF_TpvoZWK8sjdBuX5DU2A2lP29_iWzkMTg&s', + '귀요미 나인', 'GOOGLE', NOW(), NOW()), + ('508yeah@gmail.com', + 'https://file.namu.moe/file/8bc9e381797334eb33da66e3ba501be13bacd109d2d9b5f117ad0bb781574b9cb612e8226803fc6831128bc2945e5f7d2231ed68ff43ae17d3aeb6bb6947b668', + '티거', 'GOOGLE', NOW(), NOW()); + +INSERT INTO categories (name, members_id, created_at, updated_at) +VALUES ('공통 일정', 1, NOW(), NOW()), + ('BE 일정', 1, NOW(), NOW()), + ('FE 일정', 1, NOW(), NOW()), + ('안드로이드 일정', 1, NOW(), NOW()), + ('DevOps 일정', 1, NOW(), NOW()), + ('내 일정', 2, NOW(), NOW()), + ('내 일정', 3, NOW(), NOW()), + ('운동', 2, NOW(), NOW()); + +INSERT INTO subscriptions (members_id, categories_id, color, created_at, updated_at) +VALUES (2, 1, '#868e96', NOW(), NOW()), + (2, 3, '#ffdeeb', NOW(), NOW()), + (3, 1, '#d0bfff', NOW(), NOW()), + (3, 3, '#4263eb', NOW(), NOW()); diff --git a/backend/src/test/resources/application.properties b/backend/src/test/resources/application.properties index 264bcbae..b3dada05 100644 --- a/backend/src/test/resources/application.properties +++ b/backend/src/test/resources/application.properties @@ -1,8 +1,9 @@ +spring.sql.init.mode=NEVER spring.datasource.url=jdbc:h2:~/dallog;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE spring.datasource.username=sa spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true -spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.hibernate.ddl-auto=create logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE spring.main.allow-bean-definition-overriding=true oauth.google.redirect_uri=http://localhost:3000 From 1c3c5c9cc5305f7f0ae3e49f233dc6cb1762aad4 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Thu, 21 Jul 2022 16:30:06 +0900 Subject: [PATCH 0267/1011] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=EB=93=9C=20=EB=B0=94=20=EC=8A=A4=ED=86=A0=EB=A6=AC=EB=B6=81=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/SideBar/SideBar.stories.tsx | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 frontend/src/components/SideBar/SideBar.stories.tsx diff --git a/frontend/src/components/SideBar/SideBar.stories.tsx b/frontend/src/components/SideBar/SideBar.stories.tsx deleted file mode 100644 index 8ae375c0..00000000 --- a/frontend/src/components/SideBar/SideBar.stories.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; - -import SideBar from './SideBar'; - -export default { - title: 'Components/SideBar', - component: SideBar, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ; - -export const Primary = Template.bind({}); From e95fa48c15978b245b25d00530f5c25301180122 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Thu, 21 Jul 2022 16:32:13 +0900 Subject: [PATCH 0268/1011] =?UTF-8?q?feat:=20=08=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=83=9D=EC=84=B1=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=ED=81=B4=EB=A6=AD=20=EC=8B=9C=20=EB=AA=A8=EB=8B=AC=20=EB=9D=84?= =?UTF-8?q?=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../@common/ModalPortal/ModalPortal.styles.ts | 1 + .../CategoryAddModal/CategoryAddModal.styles.ts | 2 +- frontend/src/components/SideBar/SideBar.tsx | 10 +++++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/@common/ModalPortal/ModalPortal.styles.ts b/frontend/src/components/@common/ModalPortal/ModalPortal.styles.ts index 4e87f407..60b5fda1 100644 --- a/frontend/src/components/@common/ModalPortal/ModalPortal.styles.ts +++ b/frontend/src/components/@common/ModalPortal/ModalPortal.styles.ts @@ -6,6 +6,7 @@ const dimmer = ({ colors, flex }: Theme, isOpen: boolean) => css` position: fixed; top: 0; left: 0; + z-index: 30; width: 100%; height: 100%; diff --git a/frontend/src/components/CategoryAddModal/CategoryAddModal.styles.ts b/frontend/src/components/CategoryAddModal/CategoryAddModal.styles.ts index 1a3c4e86..3e0755f5 100644 --- a/frontend/src/components/CategoryAddModal/CategoryAddModal.styles.ts +++ b/frontend/src/components/CategoryAddModal/CategoryAddModal.styles.ts @@ -4,7 +4,7 @@ const categoryAddModal = ({ colors, flex }: Theme) => css` ${flex.column} width: 120rem; - height: 160rem; + height: 90rem; padding: 12.5rem; border-radius: 12px; justify-content: space-between; diff --git a/frontend/src/components/SideBar/SideBar.tsx b/frontend/src/components/SideBar/SideBar.tsx index 3198097d..aa10b7e1 100644 --- a/frontend/src/components/SideBar/SideBar.tsx +++ b/frontend/src/components/SideBar/SideBar.tsx @@ -1,6 +1,10 @@ import { useTheme } from '@emotion/react'; +import useToggle from '@/hooks/useToggle'; + import Button from '@/components/@common/Button/Button'; +import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; +import CategoryAddModal from '@/components/CategoryAddModal/CategoryAddModal'; import { FiEdit3, FiPlus } from 'react-icons/fi'; import { RiDeleteBin6Line } from 'react-icons/ri'; @@ -13,13 +17,17 @@ interface SideBarProps { function SideBar({ isOpen }: SideBarProps) { const theme = useTheme(); + const { state: isCategoryAddModalOpen, toggleState: toggleCategoryAddModalOpen } = useToggle(); return (
+ + + 나의 카테고리 -
From 11d9f686b348a456498b3d8a364b17ad3f115679 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 17:28:36 +0900 Subject: [PATCH 0269/1011] =?UTF-8?q?feat(Category):=20=EB=8B=A8=EA=B1=B4?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/category/controller/CategoryController.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index cb844b31..74458404 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -11,6 +11,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -43,4 +44,9 @@ public ResponseEntity findMine(@AuthenticationPrincipal fina final Pageable pageable) { return ResponseEntity.ok(categoryService.findMine(loginMember.getId(), pageable)); } + + @GetMapping("/{categoryId}") + public ResponseEntity findById(@PathVariable final Long categoryId) { + return ResponseEntity.ok().body(categoryService.findById(categoryId)); + } } From 1715232319f432857980b6aba7e153f91ec0e0f4 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 18:01:32 +0900 Subject: [PATCH 0270/1011] =?UTF-8?q?refactor(Member):=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/allog/dallog/auth/service/AuthService.java | 2 +- .../java/com/allog/dallog/member/service/MemberService.java | 2 +- .../java/com/allog/dallog/member/service/MemberServiceTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index 358325d8..0732a832 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -39,7 +39,7 @@ public TokenResponse generateTokenWithCode(final String code) { saveMemberIfNotExists(oAuthMember, email); - Member foundMember = memberService.findByEmail(email); + Member foundMember = memberService.getByEmail(email); String accessToken = jwtTokenProvider.createToken(String.valueOf(foundMember.getId())); return new TokenResponse(accessToken); diff --git a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java index 3420fd01..5849d7ba 100644 --- a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java +++ b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java @@ -31,7 +31,7 @@ public Member getMember(final Long id) { .orElseThrow(NoSuchMemberException::new); } - public Member findByEmail(final String email) { + public Member getByEmail(final String email) { return memberRepository.findByEmail(email) .orElseThrow(NoSuchMemberException::new); } diff --git a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java b/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java index 0bdda311..36ca3596 100644 --- a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java @@ -44,7 +44,7 @@ class MemberServiceTest { MemberResponse savedMember = memberService.save(member); // when - Member foundMember = memberService.findByEmail(EMAIL); + Member foundMember = memberService.getByEmail(EMAIL); // then assertThat(foundMember.getId()).isEqualTo(savedMember.getId()); From 6aa85e9cca185bd5ee2bad961df35b0f8e7c674b Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 18:49:05 +0900 Subject: [PATCH 0271/1011] =?UTF-8?q?test:=20=EB=8B=A8=EA=B1=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/service/CategoryServiceTest.java | 14 ++++++++++++++ .../dallog/member/service/MemberServiceTest.java | 13 +++++++++++++ 2 files changed, 27 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index e44beb05..03977c3f 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -106,4 +106,18 @@ class CategoryServiceTest { .extracting(CategoryResponse::getName) .contains("알록달록 회의", "지원플랫폼 근로"); } + + @DisplayName("id를 통해 카테고리를 단건 조회한다.") + @Test + void id를_통해_카테고리를_단건_조회한다() { + // given + Member member = memberRepository.save(MEMBER); + categoryService.save(member.getId(), new CategoryCreateRequest("BE 공식일정")); + CategoryResponse savedCategory = categoryService.save(member.getId(), new CategoryCreateRequest("FE 공식일정")); + + // when & then + assertThat(categoryService.findById(savedCategory.getId())) + .usingRecursiveComparison() + .isEqualTo(savedCategory); + } } diff --git a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java b/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java index 36ca3596..956b9cd7 100644 --- a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java @@ -2,6 +2,7 @@ import static com.allog.dallog.common.fixtures.MemberFixtures.DISPLAY_NAME; import static com.allog.dallog.common.fixtures.MemberFixtures.EMAIL; +import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; import static com.allog.dallog.common.fixtures.MemberFixtures.PROFILE_IMAGE_URI; import static org.assertj.core.api.Assertions.assertThat; @@ -50,6 +51,18 @@ class MemberServiceTest { assertThat(foundMember.getId()).isEqualTo(savedMember.getId()); } + @DisplayName("id를 통해 회원을 단건 조회한다.") + @Test + void id를_통해_회원을_단건_조회한다() { + // given + MemberResponse savedMember = memberService.save(MEMBER); + + // when & then + assertThat(memberService.findById(savedMember.getId())) + .usingRecursiveComparison() + .isEqualTo(savedMember); + } + @DisplayName("주어진 이메일로 가입된 회원이 있는지 확인한다.") @CsvSource(value = {"registerd@gmail.com,true", "notregistered@naver.com,false"}) @ParameterizedTest From 4ce9e22d9e8d82e312a2e1c1f3aac8a1a6e055db Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 19:56:49 +0900 Subject: [PATCH 0272/1011] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=ED=94=BD=EC=8A=A4=EC=B2=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acceptance/CategoryAcceptanceTest.java | 14 ++-- .../domain/CategoryRepositoryTest.java | 75 ++++++++----------- .../category/service/CategoryServiceTest.java | 58 +++++++------- .../common/fixtures/CategoryFixtures.java | 6 +- .../common/fixtures/MemberFixtures.java | 1 + 5 files changed, 74 insertions(+), 80 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 37381081..a5bcfbff 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -7,8 +7,8 @@ import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_1; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE_2; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; import static org.assertj.core.api.Assertions.assertThat; @@ -47,14 +47,14 @@ public class CategoryAcceptanceTest extends AcceptanceTest { 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); // when - ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(PAGE_NUMBER, PAGE_SIZE); + ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(PAGE_NUMBER_1, PAGE_SIZE_2); CategoriesResponse categoriesResponse = response.as(CategoriesResponse.class); // then assertAll(() -> { 상태코드_200이_반환된다(response); - assertThat(categoriesResponse.getPage()).isEqualTo(PAGE_NUMBER); - assertThat(categoriesResponse.getCategories()).hasSize(PAGE_SIZE); + assertThat(categoriesResponse.getPage()).isEqualTo(PAGE_NUMBER_1); + assertThat(categoriesResponse.getCategories()).hasSize(PAGE_SIZE_2); }); } @@ -70,14 +70,14 @@ public class CategoryAcceptanceTest extends AcceptanceTest { int page = 0; // when - ExtractableResponse response = 내가_등록한_카테고리를_페이징을_통해_조회한다(accessToken, page, PAGE_SIZE); + ExtractableResponse response = 내가_등록한_카테고리를_페이징을_통해_조회한다(accessToken, page, PAGE_SIZE_2); CategoriesResponse categoriesResponse = response.as(CategoriesResponse.class); // then assertAll(() -> { 상태코드_200이_반환된다(response); assertThat(categoriesResponse.getPage()).isEqualTo(page); - assertThat(categoriesResponse.getCategories()).hasSize(PAGE_SIZE); + assertThat(categoriesResponse.getCategories()).hasSize(PAGE_SIZE_2); }); } } diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java index 71b93260..c0bd3b47 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java @@ -1,15 +1,17 @@ package com.allog.dallog.category.domain; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE; -import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_0; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_1; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE_2; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE_8; +import static com.allog.dallog.common.fixtures.MemberFixtures.CREATOR; +import static com.allog.dallog.common.fixtures.MemberFixtures.CREATOR2; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.global.config.JpaConfig; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; -import com.allog.dallog.member.domain.SocialType; import java.util.Objects; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -33,37 +35,32 @@ class CategoryRepositoryTest { @Test void 페이지와_사이즈를_받아_해당하는_구간의_카테고리를_조회한다() { // given - Member member = memberRepository.save(MEMBER); - categoryRepository.save(new Category("BE 공식일정", member)); - categoryRepository.save(new Category("FE 공식일정", member)); - categoryRepository.save(new Category("알록달록 회의", member)); - categoryRepository.save(new Category("지원플랫폼 근로", member)); - categoryRepository.save(new Category("파랑의 코틀린 스터디", member)); + Member creator = memberRepository.save(CREATOR); + categoryRepository.save(new Category("BE 공식일정", creator)); + categoryRepository.save(new Category("FE 공식일정", creator)); + categoryRepository.save(new Category("알록달록 회의", creator)); + categoryRepository.save(new Category("지원플랫폼 근로", creator)); + categoryRepository.save(new Category("파랑의 코틀린 스터디", creator)); - PageRequest pageRequest = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); + PageRequest pageRequest = PageRequest.of(PAGE_NUMBER_1, PAGE_SIZE_2); // when Slice categories = categoryRepository.findSliceBy(pageRequest); // then assertAll(() -> { - assertThat(categories.getContent()) - .hasSize(PAGE_SIZE) - .extracting(Category::getName) - .contains("알록달록 회의", "지원플랫폼 근로"); - assertThat(categories.getContent().stream() - .map(Category::getCreatedAt) - .allMatch(Objects::nonNull)) - .isTrue(); - } - ); + assertThat(categories.getContent()).hasSize(PAGE_SIZE_2).extracting(Category::getName) + .contains("알록달록 회의", "지원플랫폼 근로"); + assertThat( + categories.getContent().stream().map(Category::getCreatedAt).allMatch(Objects::nonNull)).isTrue(); + }); } @DisplayName("조회 시 데이터가 존재하지 않는 경우 빈 슬라이스가 반환된다.") @Test void 조회_시_데이터가_존재하지_않는_경우_빈_슬라이스가_반환된다() { // given - PageRequest pageRequest = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); + PageRequest pageRequest = PageRequest.of(PAGE_NUMBER_1, PAGE_SIZE_2); // when Slice categories = categoryRepository.findSliceBy(pageRequest); @@ -76,32 +73,26 @@ class CategoryRepositoryTest { @Test void 특정_멤버가_생성한_카테고리를_페이징을_통해_조회한다() { // given - Member member2 = new Member("a@eamil.com", "/image.png", "parang", SocialType.GOOGLE); - memberRepository.save(MEMBER); - memberRepository.save(member2); - categoryRepository.save(new Category("BE 공식일정", MEMBER)); - categoryRepository.save(new Category("FE 공식일정", MEMBER)); - categoryRepository.save(new Category("알록달록 회의", MEMBER)); - categoryRepository.save(new Category("지원플랫폼 근로", member2)); - categoryRepository.save(new Category("파랑의 코틀린 스터디", member2)); + Member creator = memberRepository.save(CREATOR); + Member creator2 = memberRepository.save(CREATOR2); + categoryRepository.save(new Category("BE 공식일정", creator)); + categoryRepository.save(new Category("FE 공식일정", creator)); + categoryRepository.save(new Category("알록달록 회의", creator)); + categoryRepository.save(new Category("지원플랫폼 근로", creator2)); + categoryRepository.save(new Category("파랑의 코틀린 스터디", creator2)); - PageRequest pageRequest = PageRequest.of(0, 10); + PageRequest pageRequest = PageRequest.of(PAGE_NUMBER_0, PAGE_SIZE_8); // when - Slice categories = categoryRepository.findSliceByMemberId(pageRequest, MEMBER.getId()); + Slice categories = categoryRepository.findSliceByMemberId(pageRequest, creator.getId()); // then assertAll(() -> { - assertThat(categories.getContent()) - .hasSize(3) - .extracting(Category::getName) - .containsExactlyInAnyOrder("BE 공식일정", "FE 공식일정", "알록달록 회의"); - assertThat(categories.getContent().stream() - .map(Category::getCreatedAt) - .allMatch(Objects::nonNull)) - .isTrue(); - } - ); + assertThat(categories.getContent()).hasSize(3).extracting(Category::getName) + .containsExactlyInAnyOrder("BE 공식일정", "FE 공식일정", "알록달록 회의"); + assertThat( + categories.getContent().stream().map(Category::getCreatedAt).allMatch(Objects::nonNull)).isTrue(); + }); } } diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 03977c3f..5dac4877 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -1,9 +1,9 @@ package com.allog.dallog.category.service; import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE; -import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_1; +import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE_2; +import static com.allog.dallog.common.fixtures.MemberFixtures.CREATOR; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -37,10 +37,10 @@ class CategoryServiceTest { void 새로운_카테고리를_생성한다() { // given CategoryCreateRequest request = new CategoryCreateRequest(CATEGORY_NAME); - Member member = memberRepository.save(MEMBER); + Member creator = memberRepository.save(CREATOR); // when - CategoryResponse response = categoryService.save(member.getId(), request); + CategoryResponse response = categoryService.save(creator.getId(), request); // then assertThat(response.getName()).isEqualTo(CATEGORY_NAME); @@ -52,10 +52,10 @@ class CategoryServiceTest { void 새로운_카테고리를_생성_할_때_이름이_공백이거나_길이가_20을_초과하는_경우_예외를_던진다(final String name) { // given CategoryCreateRequest request = new CategoryCreateRequest(name); - Member member = memberRepository.save(MEMBER); + Member creator = memberRepository.save(CREATOR); // when & then - assertThatThrownBy(() -> categoryService.save(member.getId(), request)) + assertThatThrownBy(() -> categoryService.save(creator.getId(), request)) .isInstanceOf(InvalidCategoryException.class); } @@ -63,22 +63,22 @@ class CategoryServiceTest { @Test void 페이지를_받아_해당하는_구간의_카테고리를_가져온다() { // given - Member member = memberRepository.save(MEMBER); - Long memberId = member.getId(); - categoryService.save(memberId, new CategoryCreateRequest("BE 공식일정")); - categoryService.save(memberId, new CategoryCreateRequest("FE 공식일정")); - categoryService.save(memberId, new CategoryCreateRequest("알록달록 회의")); - categoryService.save(memberId, new CategoryCreateRequest("지원플랫폼 근로")); - categoryService.save(memberId, new CategoryCreateRequest("파랑의 코틀린 스터디")); + Member creator = memberRepository.save(CREATOR); + Long creatorId = creator.getId(); + categoryService.save(creatorId, new CategoryCreateRequest("BE 공식일정")); + categoryService.save(creatorId, new CategoryCreateRequest("FE 공식일정")); + categoryService.save(creatorId, new CategoryCreateRequest("알록달록 회의")); + categoryService.save(creatorId, new CategoryCreateRequest("지원플랫폼 근로")); + categoryService.save(creatorId, new CategoryCreateRequest("파랑의 코틀린 스터디")); - PageRequest request = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); + PageRequest request = PageRequest.of(PAGE_NUMBER_1, PAGE_SIZE_2); // when CategoriesResponse response = categoryService.findAll(request); // then assertThat(response.getCategories()) - .hasSize(PAGE_SIZE) + .hasSize(PAGE_SIZE_2) .extracting(CategoryResponse::getName) .contains("알록달록 회의", "지원플랫폼 근로"); } @@ -87,22 +87,22 @@ class CategoryServiceTest { @Test void 회원_id와_페이지를_기반으로_카테고리를_가져온다() { // given - Member member = memberRepository.save(MEMBER); - Long memberId = member.getId(); - categoryService.save(memberId, new CategoryCreateRequest("BE 공식일정")); - categoryService.save(memberId, new CategoryCreateRequest("FE 공식일정")); - categoryService.save(memberId, new CategoryCreateRequest("알록달록 회의")); - categoryService.save(memberId, new CategoryCreateRequest("지원플랫폼 근로")); - categoryService.save(memberId, new CategoryCreateRequest("파랑의 코틀린 스터디")); + Member creator = memberRepository.save(CREATOR); + Long creatorId = creator.getId(); + categoryService.save(creatorId, new CategoryCreateRequest("BE 공식일정")); + categoryService.save(creatorId, new CategoryCreateRequest("FE 공식일정")); + categoryService.save(creatorId, new CategoryCreateRequest("알록달록 회의")); + categoryService.save(creatorId, new CategoryCreateRequest("지원플랫폼 근로")); + categoryService.save(creatorId, new CategoryCreateRequest("파랑의 코틀린 스터디")); - PageRequest request = PageRequest.of(PAGE_NUMBER, PAGE_SIZE); + PageRequest request = PageRequest.of(PAGE_NUMBER_1, PAGE_SIZE_2); // when - CategoriesResponse response = categoryService.findMine(memberId, request); + CategoriesResponse response = categoryService.findMine(creatorId, request); // then assertThat(response.getCategories()) - .hasSize(PAGE_SIZE) + .hasSize(PAGE_SIZE_2) .extracting(CategoryResponse::getName) .contains("알록달록 회의", "지원플랫폼 근로"); } @@ -111,9 +111,9 @@ class CategoryServiceTest { @Test void id를_통해_카테고리를_단건_조회한다() { // given - Member member = memberRepository.save(MEMBER); - categoryService.save(member.getId(), new CategoryCreateRequest("BE 공식일정")); - CategoryResponse savedCategory = categoryService.save(member.getId(), new CategoryCreateRequest("FE 공식일정")); + Member creator = memberRepository.save(CREATOR); + categoryService.save(creator.getId(), new CategoryCreateRequest("BE 공식일정")); + CategoryResponse savedCategory = categoryService.save(creator.getId(), new CategoryCreateRequest("FE 공식일정")); // when & then assertThat(categoryService.findById(savedCategory.getId())) diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 3d2db5e4..349647eb 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -10,8 +10,10 @@ public class CategoryFixtures { public static final String CATEGORY_NAME = "달록"; - public static final int PAGE_NUMBER = 1; - public static final int PAGE_SIZE = 2; + public static final int PAGE_NUMBER_0 = 0; + public static final int PAGE_NUMBER_1 = 1; + public static final int PAGE_SIZE_2 = 2; + public static final int PAGE_SIZE_8 = 8; public static final Category CATEGORY = new Category(CATEGORY_NAME, MEMBER); diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java index 9f1ce14b..853c5aaa 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java @@ -11,4 +11,5 @@ public class MemberFixtures { public static final Member MEMBER = new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE); public static final Member CREATOR = new Member("creator@email.com", "/image.png", "creator", SocialType.GOOGLE); + public static final Member CREATOR2 = new Member("creator2@eamil.com", "/image.png", "creator2", SocialType.GOOGLE); } From 7f3f2fe24e2c8392939226d5953d3126b861c2ef Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 22:03:05 +0900 Subject: [PATCH 0273/1011] =?UTF-8?q?refactor:=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=ED=9A=8C=EC=9B=90=EC=9D=B8=EC=A7=80=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/category/service/CategoryService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index 37331a53..6b8e463f 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -43,7 +43,9 @@ public CategoriesResponse findAll(final Pageable pageable) { } public CategoriesResponse findMine(final Long memberId, final Pageable pageable) { - List categoryResponses = categoryRepository.findSliceByMemberId(pageable, memberId) + Member member = memberService.getMember(memberId); + + List categoryResponses = categoryRepository.findSliceByMemberId(pageable, member.getId()) .getContent() .stream() .map(CategoryResponse::new) From e55ffa107867dc42cb11523365db9bdd08144716 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 21 Jul 2022 16:22:15 +0900 Subject: [PATCH 0274/1011] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EA=B2=A9=EB=A6=AC=EB=A5=BC=20=EC=9C=84=ED=95=9C=20transacti?= =?UTF-8?q?onal=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/allog/dallog/auth/service/AuthServiceTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index b694d45b..4c290df5 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -13,7 +13,9 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; +@Transactional @SpringBootTest(classes = TestConfig.class) class AuthServiceTest { From eab1d3bcae3a60962ae7de9b63815044f9412671 Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 21 Jul 2022 22:16:16 +0900 Subject: [PATCH 0275/1011] =?UTF-8?q?docs:=20README=EC=97=90=20=ED=8C=80?= =?UTF-8?q?=EC=9B=90=20=EC=86=8C=EA=B0=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 098cf0a2..51809af0 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,8 @@ # 2022-dallog +## 알록달록🌈 팀원 소개 + +| Backend | Backend | Backend | Backend | Frontend | Frontend | +| :------------------------------------------: | :------------------------------------------------: | :----------------------------------------------: | :------------------------------------------: | :--------------------------------------------: | :-----------------------------------------: | +| ![](https://github.com/hyeonic.png?size=120) | ![](https://github.com/gudonghee2000.png?size=120) | ![](https://github.com/summerlunaa.png?size=120) | ![](https://github.com/devHudi.png?size=120) | ![](https://github.com/daaaayeah.png?size=120) | ![](https://github.com/jhy979.png?size=120) | +| [매트(최기현)](https://github.com/hyeonic) | [리버(구동희)](https://github.com/gudonghee2000) | [파랑(이하은)](https://github.com/summerlunaa) | [후디(조동현)](https://github.com/devHudi) | [티거(이다예)](https://github.com/daaaayeah) | [나인(장호영)](https://github.com/jhy979) | From 251d0ce59fde8b6ff2f81fc08a0f35ff7bc60bbd Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 21 Jul 2022 13:06:02 +0900 Subject: [PATCH 0276/1011] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20API=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/login.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/api/login.ts b/frontend/src/api/login.ts index 4f966902..5ab3d39d 100644 --- a/frontend/src/api/login.ts +++ b/frontend/src/api/login.ts @@ -1,7 +1,7 @@ import axios from 'axios'; const loginApi = { - baseUrl: 'http://3.38.116.83:8080', + baseUrl: process.env.API_KEY, endPoint: { googleEntry: '/api/auth/google/oauth-uri', googleToken: '/api/auth/google/token', From 6dd2c8484aa95230d14f9773cc507955a964886c Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 21 Jul 2022 14:40:13 +0900 Subject: [PATCH 0277/1011] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?=EB=B0=8F=20API=5FKEY=20=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/login.ts | 7 ++++--- frontend/src/api/profile.ts | 11 ++++------- frontend/src/constants/index.ts | 4 +++- frontend/src/pages/AuthPage/AuthPage.tsx | 1 - 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/frontend/src/api/login.ts b/frontend/src/api/login.ts index 5ab3d39d..b6b1d1bc 100644 --- a/frontend/src/api/login.ts +++ b/frontend/src/api/login.ts @@ -1,21 +1,22 @@ import axios from 'axios'; +import { API_KEY } from '@/constants'; + const loginApi = { - baseUrl: process.env.API_KEY, endPoint: { googleEntry: '/api/auth/google/oauth-uri', googleToken: '/api/auth/google/token', }, getUrl: async () => { - const { data } = await axios.get(`${loginApi.baseUrl}${loginApi.endPoint.googleEntry}`); + const { data } = await axios.get(`${API_KEY}${loginApi.endPoint.googleEntry}`); return data.oAuthUri; }, auth: async () => { const code = new URLSearchParams(location.search).get('code'); - const { data } = await axios.post(`${loginApi.baseUrl}${loginApi.endPoint.googleToken}`, { + const { data } = await axios.post(`${API_KEY}${loginApi.endPoint.googleToken}`, { code, }); diff --git a/frontend/src/api/profile.ts b/frontend/src/api/profile.ts index b4fea33e..5d27834b 100644 --- a/frontend/src/api/profile.ts +++ b/frontend/src/api/profile.ts @@ -2,21 +2,18 @@ import axios from 'axios'; import { ProfileType } from '@/@types/profile'; +import { API_KEY } from '@/constants'; + const profileApi = { - endpoint: '/api/members/me', + endpoint: `${API_KEY}/api/members/me`, headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, - get: async (accessToken: string) => { + get: async (accessToken: string | null) => { const response = await axios.get(profileApi.endpoint, { headers: { ...profileApi.headers, Authorization: `Bearer ${accessToken}` }, - transformResponse: (res) => { - const profile = JSON.parse(res).data; - - return profile; - }, }); return response; diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 173c9a69..a1e4e181 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -2,6 +2,8 @@ const API = { CATEGORY_GET_SIZE: 4, }; +const API_KEY = process.env.API_KEY; + const ATOM_KEY = { USER: 'userState', }; @@ -32,4 +34,4 @@ const PATH = { PROFILE: '/profile', }; -export { API, ATOM_KEY, CACHE_KEY, CONFIRM_MESSAGE, DAYS, STORAGE_KEY, PATH }; +export { API, API_KEY, ATOM_KEY, CACHE_KEY, CONFIRM_MESSAGE, DAYS, STORAGE_KEY, PATH }; diff --git a/frontend/src/pages/AuthPage/AuthPage.tsx b/frontend/src/pages/AuthPage/AuthPage.tsx index f70d2444..b6ba8fc2 100644 --- a/frontend/src/pages/AuthPage/AuthPage.tsx +++ b/frontend/src/pages/AuthPage/AuthPage.tsx @@ -1,4 +1,3 @@ -import { useEffect } from 'react'; import { useQuery } from 'react-query'; import { useNavigate } from 'react-router-dom'; From 4b21a7cc49def94e2b87a96f859009df1ef71b1c Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 21 Jul 2022 14:40:50 +0900 Subject: [PATCH 0278/1011] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=A1=B0=ED=9A=8C=20API=20=EB=AA=85=EC=84=B8=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/@types/profile.ts | 2 +- frontend/src/mocks/data.ts | 8 ++++---- frontend/src/pages/MyPage/MyPage.tsx | 9 ++++++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/frontend/src/@types/profile.ts b/frontend/src/@types/profile.ts index 2bd8103e..f067662b 100644 --- a/frontend/src/@types/profile.ts +++ b/frontend/src/@types/profile.ts @@ -2,7 +2,7 @@ interface ProfileType { id: number; email: string; displayName: string; - profileImageUri: string; + profileImageUrl: string; socialType: string; } diff --git a/frontend/src/mocks/data.ts b/frontend/src/mocks/data.ts index 8953c7c9..4443dfa4 100644 --- a/frontend/src/mocks/data.ts +++ b/frontend/src/mocks/data.ts @@ -120,7 +120,7 @@ const profileDB = { id: 1, email: 'example@email.com', displayName: '매트', - profileImageUri: 'https://img.insight.co.kr/static/2020/05/04/700/51wlu5y2281iku1o0hms.jpg', + profileImageUrl: 'https://img.insight.co.kr/static/2020/05/04/700/51wlu5y2281iku1o0hms.jpg', socialType: 'GOOGLE', }, }; @@ -135,7 +135,7 @@ const subscriptionDB = { id: 1, email: 'example@email.com', displayName: 'example', - profileImageUri: '/image.png', + profileImageUrl: '/image.png', }, createdAt: '2022-07-19T16:42', }, @@ -149,7 +149,7 @@ const subscriptionDB = { id: 1, email: 'example@email.com', displayName: 'example', - profileImageUri: '/image.png', + profileImageUrl: '/image.png', }, createdAt: '2022-07-19T16:42', }, @@ -163,7 +163,7 @@ const subscriptionDB = { id: 1, email: 'example@email.com', displayName: 'example', - profileImageUri: '/image.png', + profileImageUrl: '/image.png', }, createdAt: '2022-07-19T16:42', }, diff --git a/frontend/src/pages/MyPage/MyPage.tsx b/frontend/src/pages/MyPage/MyPage.tsx index f059e027..cbbaf4bf 100644 --- a/frontend/src/pages/MyPage/MyPage.tsx +++ b/frontend/src/pages/MyPage/MyPage.tsx @@ -1,8 +1,11 @@ import { AxiosError, AxiosResponse } from 'axios'; import { useQuery } from 'react-query'; +import { useRecoilValue } from 'recoil'; import { ProfileType } from '@/@types/profile'; +import { userState } from '@/atoms'; + import { CACHE_KEY } from '@/constants'; import profileAPI from '@/api/profile'; @@ -17,7 +20,7 @@ import { } from './MyPage.styles'; function MyPage() { - const accessToken = 'Bearer aaaaaaaaaa.bbbbbbbbbb.cccccccccc'; + const { accessToken } = useRecoilValue(userState); const { isLoading, @@ -35,7 +38,7 @@ function MyPage() { return
Error
; } - const { displayName, email, profileImageUri } = profileGetResponse.data; + const { displayName, email, profileImageUrl } = profileGetResponse.data; return (
@@ -51,7 +54,7 @@ function MyPage() {
프로필 사진 - 프로필 이미지 + 프로필 이미지
From 21eb4810254226b8ee02dfd45601ebb106b49b8c Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 21 Jul 2022 15:16:54 +0900 Subject: [PATCH 0279/1011] =?UTF-8?q?feat:=20=EC=9B=94=EB=B3=84=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EC=A1=B0=ED=9A=8C=20API=20=EC=97=B0?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/schedule.ts | 15 +++++++++----- frontend/src/components/Calendar/Calendar.tsx | 20 +++++++++++++------ .../src/pages/CalendarPage/CalendarPage.tsx | 19 ++++++++++++++---- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/frontend/src/api/schedule.ts b/frontend/src/api/schedule.ts index 68e306ae..40d7fca4 100644 --- a/frontend/src/api/schedule.ts +++ b/frontend/src/api/schedule.ts @@ -2,17 +2,22 @@ import axios from 'axios'; import { Schedule } from '@/@types'; +import { API_KEY } from '@/constants'; + const scheduleApi = { - endpoint: '/api/schedule', + endpoint: `${API_KEY}/api/schedules`, headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, - get: async () => { - const response = await axios.get<{ schedules: Schedule[] }>(scheduleApi.endpoint, { - headers: scheduleApi.headers, - }); + get: async (year: number, month: number) => { + const response = await axios.get<{ schedules: Schedule[] }>( + `${scheduleApi.endpoint}?year=${year}&month=${month}`, + { + headers: scheduleApi.headers, + } + ); return response; }, diff --git a/frontend/src/components/Calendar/Calendar.tsx b/frontend/src/components/Calendar/Calendar.tsx index 1a9ce958..c4316216 100644 --- a/frontend/src/components/Calendar/Calendar.tsx +++ b/frontend/src/components/Calendar/Calendar.tsx @@ -26,18 +26,26 @@ import { navButton, } from './Calendar.styles'; -function Calendar() { +interface CalendarProps { + current: { + year: number; + month: number; + }; + setCurrent: React.Dispatch< + React.SetStateAction<{ + year: number; + month: number; + }> + >; +} + +function Calendar({ current, setCurrent }: CalendarProps) { const theme = useTheme(); const [calendarMonth, setCalendarMonth] = useState( getCalendarMonth(getThisYear(), getThisMonth()) ); - const [current, setCurrent] = useState({ - year: getThisYear(), - month: getThisMonth(), - }); - const handleClickBeforeMonthButton = () => { const { year, month } = getBeforeYearMonth(current.year, current.month); diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index 6a452cfb..1a8adf1b 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -1,4 +1,5 @@ import { AxiosError, AxiosResponse } from 'axios'; +import { useEffect, useState } from 'react'; import { useQuery } from 'react-query'; import useToggle from '@/hooks/useToggle'; @@ -12,23 +13,33 @@ import ScheduleAddModal from '@/components/ScheduleAddModal/ScheduleAddModal'; import { CACHE_KEY } from '@/constants'; +import { getThisMonth, getThisYear } from '@/utils/date'; + import scheduleApi from '@/api/schedule'; import { calendarPage } from './CalendarPage.styles'; function CalendarPage() { + const [current, setCurrent] = useState({ + year: getThisYear(), + month: getThisMonth(), + }); + const { isLoading, error, data: schedulesGetResponse, refetch: refetchSchedules, - } = useQuery, AxiosError>( - CACHE_KEY.SCHEDULES, - scheduleApi.get + } = useQuery, AxiosError>(CACHE_KEY.SCHEDULES, () => + scheduleApi.get(current.year, current.month) ); const { state: isCalendarAddModalOpen, toggleState: toggleCalendarAddModalOpen } = useToggle(); + useEffect(() => { + refetchSchedules(); + }, [current]); + if (isLoading || schedulesGetResponse === undefined) { return <>Loading; } @@ -39,7 +50,7 @@ function CalendarPage() { return (
- + From a3e31a24679120b72c8aed4e5f8dd73a27cb6906 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 21 Jul 2022 15:51:23 +0900 Subject: [PATCH 0280/1011] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20API=20=EC=97=B0=EB=8F=99=20=EB=B0=8F=20?= =?UTF-8?q?=EB=AA=85=EC=84=B8=20=EB=B3=80=EA=B2=BD=20=EB=8C=80=EC=9D=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/@types/category.ts | 3 +-- frontend/src/api/category.ts | 4 +++- .../CategoryList/CategoryList.stories.tsx | 2 +- frontend/src/mocks/data.ts | 4 ++-- frontend/src/mocks/handlers.ts | 15 +++++++-------- frontend/src/pages/CategoryPage/CategoryPage.tsx | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/frontend/src/@types/category.ts b/frontend/src/@types/category.ts index f1348529..d8ae24b4 100644 --- a/frontend/src/@types/category.ts +++ b/frontend/src/@types/category.ts @@ -5,9 +5,8 @@ interface CategoryType { } interface CategoriesGetResponseType { - totalCount: number; page: number; - data: CategoryType[]; + categories: CategoryType[]; } export { CategoryType, CategoriesGetResponseType }; diff --git a/frontend/src/api/category.ts b/frontend/src/api/category.ts index 11deb87a..9f118f99 100644 --- a/frontend/src/api/category.ts +++ b/frontend/src/api/category.ts @@ -2,8 +2,10 @@ import axios from 'axios'; import { CategoriesGetResponseType, CategoryType } from '@/@types/category'; +import { API_KEY } from '@/constants'; + const categoryApi = { - endpoint: '/api/categories', + endpoint: `${API_KEY}/api/categories`, headers: { 'Content-Type': 'application/json', Accept: 'application/json', diff --git a/frontend/src/components/CategoryList/CategoryList.stories.tsx b/frontend/src/components/CategoryList/CategoryList.stories.tsx index e4262129..9bd630f9 100644 --- a/frontend/src/components/CategoryList/CategoryList.stories.tsx +++ b/frontend/src/components/CategoryList/CategoryList.stories.tsx @@ -13,5 +13,5 @@ const Template: ComponentStory = (args) => { const page = parseInt(req.url.searchParams.get('page') as string); const size = parseInt(req.url.searchParams.get('size') as string); - const slicedCategories = categoryDB.data.slice((page - 1) * size, (page - 1) * size + size); + const slicedCategories = categoryDB.categories.slice(page * size, page * size + size); return res( ctx.status(200), ctx.json({ - totalCount: 18, page, - data: slicedCategories, + categories: slicedCategories, }) ); }), rest.post>(categoryApi.endpoint, (req, res, ctx) => { - categoryDB.data.push({ - id: categoryDB.data.length + 1, + categoryDB.categories.push({ + id: categoryDB.categories.length + 1, createdAt: new Date().toISOString().slice(0, -5), ...req.body, }); @@ -62,10 +61,10 @@ const handlers = [ const categoryId = parseInt(id as string); const newSubscription = { category: { - id: categoryDB.data[categoryId - 1].id, - name: categoryDB.data[categoryId - 1].name, + id: categoryDB.categories[categoryId - 1].id, + name: categoryDB.categories[categoryId - 1].name, creator: profileDB.data, - createdAt: categoryDB.data[categoryId - 1].createdAt, + createdAt: categoryDB.categories[categoryId - 1].createdAt, }, color: req.body.color, }; diff --git a/frontend/src/pages/CategoryPage/CategoryPage.tsx b/frontend/src/pages/CategoryPage/CategoryPage.tsx index df7ee135..b7d09abb 100644 --- a/frontend/src/pages/CategoryPage/CategoryPage.tsx +++ b/frontend/src/pages/CategoryPage/CategoryPage.tsx @@ -21,10 +21,10 @@ function CategoryPage() { hasNextPage, } = useInfiniteQuery, AxiosError>( CACHE_KEY.CATEGORIES, - ({ pageParam = 1 }) => categoryApi.get(pageParam, API.CATEGORY_GET_SIZE), + ({ pageParam = 0 }) => categoryApi.get(pageParam, API.CATEGORY_GET_SIZE), { getNextPageParam: ({ data }) => { - if (data.data.length) { + if (data.categories.length > 0) { return data.page + 1; } }, @@ -39,7 +39,7 @@ function CategoryPage() { return
Error
; } - const categoryList = categoriesGetResponse.pages.flatMap(({ data }) => data.data); + const categoryList = categoriesGetResponse.pages.flatMap(({ data }) => data.categories); return (
From 08c35c5d235652e2472bb90f1ac5c06c523ba97f Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 21 Jul 2022 18:08:45 +0900 Subject: [PATCH 0281/1011] =?UTF-8?q?feat:=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EA=B5=AC=EB=8F=85=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?api=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=EB=B3=84=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EA=B5=AC=EB=8F=85=20api=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/@types/category.ts | 3 ++ frontend/src/api/subscription.ts | 9 +++-- .../CategoryItem/CategoryItem.stories.tsx | 4 ++- frontend/src/mocks/data.ts | 36 +++++++++++++------ frontend/src/mocks/handlers.ts | 11 +++--- 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/frontend/src/@types/category.ts b/frontend/src/@types/category.ts index d8ae24b4..b234296a 100644 --- a/frontend/src/@types/category.ts +++ b/frontend/src/@types/category.ts @@ -1,6 +1,9 @@ +import { ProfileType } from './profile'; + interface CategoryType { id: number; name: string; + creator: ProfileType; createdAt: string; } diff --git a/frontend/src/api/subscription.ts b/frontend/src/api/subscription.ts index 4888657d..30713f66 100644 --- a/frontend/src/api/subscription.ts +++ b/frontend/src/api/subscription.ts @@ -2,10 +2,13 @@ import axios, { AxiosResponse } from 'axios'; import { SubscriptionType } from '@/@types/subscription'; +import { API_KEY } from '@/constants'; + const subscriptionApi = { - getEndpoint: '/api/members/me/subscriptions', - postEndpoint: (categoryId: number) => `/api/members/me/categories/${categoryId}/subscriptions`, - deleteEndpoint: (categoryId: number) => `/api/members/me/subscriptions/${categoryId}`, + getEndpoint: `${API_KEY}/api/members/me/subscriptions`, + postEndpoint: (categoryId: number) => + `${API_KEY}/api/members/me/categories/${categoryId}/subscriptions`, + deleteEndpoint: (categoryId: number) => `${API_KEY}/api/members/me/subscriptions/${categoryId}`, headers: { 'Content-Type': 'application/json', diff --git a/frontend/src/components/CategoryItem/CategoryItem.stories.tsx b/frontend/src/components/CategoryItem/CategoryItem.stories.tsx index 535154b9..477f9f01 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.stories.tsx +++ b/frontend/src/components/CategoryItem/CategoryItem.stories.tsx @@ -1,5 +1,7 @@ import { ComponentMeta, ComponentStory } from '@storybook/react'; +import { profileDB } from '@/mocks/data'; + import CategoryItem from './CategoryItem'; export default { @@ -11,5 +13,5 @@ const Template: ComponentStory = (args) => >(categoryApi.endpoint, (req, res, ctx) => { categoryDB.categories.push({ + ...req.body, id: categoryDB.categories.length + 1, createdAt: new Date().toISOString().slice(0, -5), - ...req.body, + creator: profileDB, }); return res(ctx.status(201)); @@ -55,7 +58,7 @@ const handlers = [ }), rest.post>( - `/api/members/me/categories/:id/subscriptions`, + `${API_KEY}/api/members/me/categories/:id/subscriptions`, (req, res, ctx) => { const { id } = req.params; const categoryId = parseInt(id as string); @@ -63,7 +66,7 @@ const handlers = [ category: { id: categoryDB.categories[categoryId - 1].id, name: categoryDB.categories[categoryId - 1].name, - creator: profileDB.data, + creator: profileDB, createdAt: categoryDB.categories[categoryId - 1].createdAt, }, color: req.body.color, @@ -75,7 +78,7 @@ const handlers = [ } ), - rest.delete(`/api/members/me/subscriptions/:id`, (req, res, ctx) => { + rest.delete(`${API_KEY}/api/members/me/subscriptions/:id`, (req, res, ctx) => { const { id } = req.params; const categoryId = parseInt(id as string); const subscriptionIndex = subscriptionDB.subscriptions.findIndex( From b87b5756e62859adb636ad44651440e2f2e089e6 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 21 Jul 2022 19:03:22 +0900 Subject: [PATCH 0282/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=83=9D=EC=84=B1=20api=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/category.ts | 4 ++-- .../components/CategoryAddModal/CategoryAddModal.tsx | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/frontend/src/api/category.ts b/frontend/src/api/category.ts index 9f118f99..d3e5b23a 100644 --- a/frontend/src/api/category.ts +++ b/frontend/src/api/category.ts @@ -20,9 +20,9 @@ const categoryApi = { return response; }, - post: async (body: Pick) => { + post: async (accessToken: string | null, body: Pick) => { const response = await axios.post(categoryApi.endpoint, body, { - headers: categoryApi.headers, + headers: { ...categoryApi.headers, Authorization: `Bearer ${accessToken}` }, }); return response; diff --git a/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx b/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx index c4ddc26e..37ab004f 100644 --- a/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx +++ b/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx @@ -2,9 +2,12 @@ import { useTheme } from '@emotion/react'; import { AxiosError, AxiosResponse } from 'axios'; import { useRef } from 'react'; import { useMutation } from 'react-query'; +import { useRecoilValue } from 'recoil'; import { CategoryType } from '@/@types/category'; +import { userState } from '@/atoms'; + import Button from '@/components/@common/Button/Button'; import FieldSet from '@/components/@common/FieldSet/FieldSet'; @@ -29,12 +32,14 @@ interface CategoryAddModalProps { function CategoryAddModal({ closeModal }: CategoryAddModalProps) { const theme = useTheme(); - const { mutate } = useMutation< + const { accessToken } = useRecoilValue(userState); + + const { mutate: postCategory } = useMutation< AxiosResponse>, AxiosError, Pick, unknown - >(categoryApi.post, { onSuccess: () => onSuccessPostCategory() }); + >((body) => categoryApi.post(accessToken, body), { onSuccess: () => onSuccessPostCategory() }); const inputRef = { name: useRef(null), @@ -53,7 +58,7 @@ function CategoryAddModal({ closeModal }: CategoryAddModalProps) { return; } - mutate(body); + postCategory(body); }; const onSuccessPostCategory = () => { From 9e933712f7f7d27253d681e7988cc44b2ab455f7 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 25 Jul 2022 13:14:48 +0900 Subject: [PATCH 0283/1011] =?UTF-8?q?feat:=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=ED=95=B4=EC=A0=9C=20API=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/@types/subscription.ts | 1 + frontend/src/api/subscription.ts | 10 ++++++--- .../components/CategoryItem/CategoryItem.tsx | 22 +++++++++---------- .../components/CategoryList/CategoryList.tsx | 20 +++++++++-------- frontend/src/mocks/data.ts | 3 +++ frontend/src/mocks/handlers.ts | 5 +++-- 6 files changed, 35 insertions(+), 26 deletions(-) diff --git a/frontend/src/@types/subscription.ts b/frontend/src/@types/subscription.ts index 03a767a5..502bf78d 100644 --- a/frontend/src/@types/subscription.ts +++ b/frontend/src/@types/subscription.ts @@ -1,4 +1,5 @@ interface SubscriptionType { + id: number; category: { id: number; name: string; diff --git a/frontend/src/api/subscription.ts b/frontend/src/api/subscription.ts index 30713f66..f91ed6ec 100644 --- a/frontend/src/api/subscription.ts +++ b/frontend/src/api/subscription.ts @@ -8,7 +8,8 @@ const subscriptionApi = { getEndpoint: `${API_KEY}/api/members/me/subscriptions`, postEndpoint: (categoryId: number) => `${API_KEY}/api/members/me/categories/${categoryId}/subscriptions`, - deleteEndpoint: (categoryId: number) => `${API_KEY}/api/members/me/subscriptions/${categoryId}`, + deleteEndpoint: (subscriptionId: number) => + `${API_KEY}/api/members/me/subscriptions/${subscriptionId}`, headers: { 'Content-Type': 'application/json', @@ -38,8 +39,11 @@ const subscriptionApi = { return response; }, - delete: async (accessToken: string | null, categoryId: number): Promise> => { - const response = await axios.delete(subscriptionApi.deleteEndpoint(categoryId), { + delete: async ( + accessToken: string | null, + subscriptionId: number + ): Promise> => { + const response = await axios.delete(subscriptionApi.deleteEndpoint(subscriptionId), { headers: { ...subscriptionApi.headers, Authorization: `Bearer ${accessToken}` }, }); diff --git a/frontend/src/components/CategoryItem/CategoryItem.tsx b/frontend/src/components/CategoryItem/CategoryItem.tsx index 30c7a790..2fb93892 100644 --- a/frontend/src/components/CategoryItem/CategoryItem.tsx +++ b/frontend/src/components/CategoryItem/CategoryItem.tsx @@ -1,6 +1,6 @@ import { useTheme } from '@emotion/react'; import { AxiosError, AxiosResponse } from 'axios'; -import { QueryObserverResult, RefetchOptions, RefetchQueryFilters, useMutation } from 'react-query'; +import { useMutation, useQueryClient } from 'react-query'; import { useRecoilValue } from 'recoil'; import { CategoryType } from '@/@types/category'; @@ -10,7 +10,7 @@ import { userState } from '@/atoms'; import SubscribeButton from '@/components/SubscribeButton/SubscribeButton'; -import { CONFIRM_MESSAGE } from '@/constants'; +import { CACHE_KEY, CONFIRM_MESSAGE } from '@/constants'; import subscriptionApi from '@/api/subscription'; @@ -18,14 +18,12 @@ import { categoryItem, item } from './CategoryItem.styles'; interface CategoryItemProps { category: CategoryType; - isSubscribing: boolean; - refetchSubscriptions: ( - options?: (RefetchOptions & RefetchQueryFilters) | undefined - ) => Promise, AxiosError>>; + subscriptionId: number; } -function CategoryItem({ category, isSubscribing, refetchSubscriptions }: CategoryItemProps) { +function CategoryItem({ category, subscriptionId }: CategoryItemProps) { const theme = useTheme(); + const queryClient = useQueryClient(); const { accessToken } = useRecoilValue(userState); @@ -40,15 +38,15 @@ function CategoryItem({ category, isSubscribing, refetchSubscriptions }: Categor unknown >(() => subscriptionApi.post(accessToken, category.id, body), { onSuccess: () => { - refetchSubscriptions(); + queryClient.invalidateQueries(CACHE_KEY.SUBSCRIPTIONS); }, }); const { mutate: deleteSubscription } = useMutation( - () => subscriptionApi.delete(accessToken, category.id), + () => subscriptionApi.delete(accessToken, subscriptionId), { onSuccess: () => { - refetchSubscriptions(); + queryClient.invalidateQueries(CACHE_KEY.SUBSCRIPTIONS); }, } ); @@ -60,7 +58,7 @@ function CategoryItem({ category, isSubscribing, refetchSubscriptions }: Categor }; const handleClickSubscribeButton = () => { - isSubscribing ? unsubscribe() : postSubscription(body); + subscriptionId > 0 ? unsubscribe() : postSubscription(body); }; return ( @@ -69,7 +67,7 @@ function CategoryItem({ category, isSubscribing, refetchSubscriptions }: Categor {category.name}
0} handleClickSubscribeButton={handleClickSubscribeButton} >
diff --git a/frontend/src/components/CategoryList/CategoryList.tsx b/frontend/src/components/CategoryList/CategoryList.tsx index 26a107ed..5f6cf51a 100644 --- a/frontend/src/components/CategoryList/CategoryList.tsx +++ b/frontend/src/components/CategoryList/CategoryList.tsx @@ -28,7 +28,7 @@ interface CategoryListProps { function CategoryList({ categoryList, getMoreCategories, hasNextPage }: CategoryListProps) { const { accessToken } = useRecoilValue(userState); - const { data: subscriptionsGetResponse, refetch: refetchSubscriptions } = useQuery< + const { data: subscriptionsGetResponse } = useQuery< AxiosResponse, AxiosError >(CACHE_KEY.SUBSCRIPTIONS, () => subscriptionApi.get(accessToken)); @@ -41,7 +41,12 @@ function CategoryList({ categoryList, getMoreCategories, hasNextPage }: Category return
; } - const subscriptions = subscriptionsGetResponse.data.map((el) => el.category.id); + const subscriptionList = subscriptionsGetResponse.data.map((el) => { + return { + subscriptionId: el.id, + categoryId: el.category.id, + }; + }); return (
@@ -51,15 +56,12 @@ function CategoryList({ categoryList, getMoreCategories, hasNextPage }: Category 구독 상태
{categoryList.map((category) => { - const isSubscribing = subscriptions.includes(category.id); + const { subscriptionId } = subscriptionList.find((el) => el.categoryId === category.id) ?? { + subscriptionId: -1, + }; return ( - + ); })}
diff --git a/frontend/src/mocks/data.ts b/frontend/src/mocks/data.ts index 8c162a58..b73b0167 100644 --- a/frontend/src/mocks/data.ts +++ b/frontend/src/mocks/data.ts @@ -144,6 +144,7 @@ const categoryDB: { const subscriptionDB = { subscriptions: [ { + id: 1, category: { id: 1, name: 'BE 공식일정', @@ -158,6 +159,7 @@ const subscriptionDB = { color: '#ffffff', }, { + id: 2, category: { id: 2, name: '알록달록 팀 회의', @@ -172,6 +174,7 @@ const subscriptionDB = { color: '#123423', }, { + id: 3, category: { id: 5, name: '카테고리 5', diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 84fd0fad..15af7ad2 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -63,6 +63,7 @@ const handlers = [ const { id } = req.params; const categoryId = parseInt(id as string); const newSubscription = { + id: subscriptionDB.subscriptions.length + 1, category: { id: categoryDB.categories[categoryId - 1].id, name: categoryDB.categories[categoryId - 1].name, @@ -80,9 +81,9 @@ const handlers = [ rest.delete(`${API_KEY}/api/members/me/subscriptions/:id`, (req, res, ctx) => { const { id } = req.params; - const categoryId = parseInt(id as string); + const subscriptionId = parseInt(id as string); const subscriptionIndex = subscriptionDB.subscriptions.findIndex( - (el) => el.category.id === categoryId + (el) => el.id === subscriptionId ); if (subscriptionIndex > -1) { From 28e2739748042861617ca368f45ce79668e96390 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 25 Jul 2022 14:21:09 +0900 Subject: [PATCH 0284/1011] =?UTF-8?q?refactor:=20axios=20=EC=9D=B8?= =?UTF-8?q?=EC=8A=A4=ED=84=B4=EC=8A=A4=20baseurl=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EC=83=81=EC=88=98=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/category.ts | 10 ++++------ frontend/src/api/index.ts | 7 +++++++ frontend/src/api/login.ts | 8 +++----- frontend/src/api/profile.ts | 8 +++----- frontend/src/api/schedule.ts | 10 ++++------ frontend/src/api/subscription.ts | 18 ++++++++---------- frontend/src/constants/index.ts | 4 ++-- frontend/src/mocks/handlers.ts | 6 +++--- 8 files changed, 34 insertions(+), 37 deletions(-) create mode 100644 frontend/src/api/index.ts diff --git a/frontend/src/api/category.ts b/frontend/src/api/category.ts index d3e5b23a..512fa6cd 100644 --- a/frontend/src/api/category.ts +++ b/frontend/src/api/category.ts @@ -1,18 +1,16 @@ -import axios from 'axios'; - import { CategoriesGetResponseType, CategoryType } from '@/@types/category'; -import { API_KEY } from '@/constants'; +import dallogApi from './'; const categoryApi = { - endpoint: `${API_KEY}/api/categories`, + endpoint: '/api/categories', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, get: async (page: number, size: number) => { - const response = await axios.get(categoryApi.endpoint, { + const response = await dallogApi.get(categoryApi.endpoint, { params: { page, size }, headers: categoryApi.headers, }); @@ -21,7 +19,7 @@ const categoryApi = { }, post: async (accessToken: string | null, body: Pick) => { - const response = await axios.post(categoryApi.endpoint, body, { + const response = await dallogApi.post(categoryApi.endpoint, body, { headers: { ...categoryApi.headers, Authorization: `Bearer ${accessToken}` }, }); diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts new file mode 100644 index 00000000..267f77f2 --- /dev/null +++ b/frontend/src/api/index.ts @@ -0,0 +1,7 @@ +import axios from 'axios'; + +const dallogApi = axios.create({ + baseURL: process.env.API_URL, +}); + +export default dallogApi; diff --git a/frontend/src/api/login.ts b/frontend/src/api/login.ts index b6b1d1bc..01ddd183 100644 --- a/frontend/src/api/login.ts +++ b/frontend/src/api/login.ts @@ -1,6 +1,4 @@ -import axios from 'axios'; - -import { API_KEY } from '@/constants'; +import dallogApi from './'; const loginApi = { endPoint: { @@ -9,14 +7,14 @@ const loginApi = { }, getUrl: async () => { - const { data } = await axios.get(`${API_KEY}${loginApi.endPoint.googleEntry}`); + const { data } = await dallogApi.get(loginApi.endPoint.googleEntry); return data.oAuthUri; }, auth: async () => { const code = new URLSearchParams(location.search).get('code'); - const { data } = await axios.post(`${API_KEY}${loginApi.endPoint.googleToken}`, { + const { data } = await dallogApi.post(loginApi.endPoint.googleToken, { code, }); diff --git a/frontend/src/api/profile.ts b/frontend/src/api/profile.ts index 5d27834b..7e317dfc 100644 --- a/frontend/src/api/profile.ts +++ b/frontend/src/api/profile.ts @@ -1,18 +1,16 @@ -import axios from 'axios'; - import { ProfileType } from '@/@types/profile'; -import { API_KEY } from '@/constants'; +import dallogApi from './'; const profileApi = { - endpoint: `${API_KEY}/api/members/me`, + endpoint: '/api/members/me', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, get: async (accessToken: string | null) => { - const response = await axios.get(profileApi.endpoint, { + const response = await dallogApi.get(profileApi.endpoint, { headers: { ...profileApi.headers, Authorization: `Bearer ${accessToken}` }, }); diff --git a/frontend/src/api/schedule.ts b/frontend/src/api/schedule.ts index 40d7fca4..2017f5f6 100644 --- a/frontend/src/api/schedule.ts +++ b/frontend/src/api/schedule.ts @@ -1,18 +1,16 @@ -import axios from 'axios'; - import { Schedule } from '@/@types'; -import { API_KEY } from '@/constants'; +import dallogApi from './'; const scheduleApi = { - endpoint: `${API_KEY}/api/schedules`, + endpoint: '/api/schedules', headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, get: async (year: number, month: number) => { - const response = await axios.get<{ schedules: Schedule[] }>( + const response = await dallogApi.get<{ schedules: Schedule[] }>( `${scheduleApi.endpoint}?year=${year}&month=${month}`, { headers: scheduleApi.headers, @@ -23,7 +21,7 @@ const scheduleApi = { }, post: async (body: Omit) => { - const response = await axios.post(scheduleApi.endpoint, body, { + const response = await dallogApi.post(scheduleApi.endpoint, body, { headers: scheduleApi.headers, }); diff --git a/frontend/src/api/subscription.ts b/frontend/src/api/subscription.ts index f91ed6ec..b640afd9 100644 --- a/frontend/src/api/subscription.ts +++ b/frontend/src/api/subscription.ts @@ -1,15 +1,13 @@ -import axios, { AxiosResponse } from 'axios'; +import { AxiosResponse } from 'axios'; import { SubscriptionType } from '@/@types/subscription'; -import { API_KEY } from '@/constants'; +import dallogApi from './'; const subscriptionApi = { - getEndpoint: `${API_KEY}/api/members/me/subscriptions`, - postEndpoint: (categoryId: number) => - `${API_KEY}/api/members/me/categories/${categoryId}/subscriptions`, - deleteEndpoint: (subscriptionId: number) => - `${API_KEY}/api/members/me/subscriptions/${subscriptionId}`, + getEndpoint: '/api/members/me/subscriptions', + postEndpoint: (categoryId: number) => `/api/members/me/categories/${categoryId}/subscriptions`, + deleteEndpoint: (subscriptionId: number) => `/api/members/me/subscriptions/${subscriptionId}`, headers: { 'Content-Type': 'application/json', @@ -17,7 +15,7 @@ const subscriptionApi = { }, get: async (accessToken: string | null) => { - const response = await axios.get(subscriptionApi.getEndpoint, { + const response = await dallogApi.get(subscriptionApi.getEndpoint, { headers: { ...subscriptionApi.headers, Authorization: `Bearer ${accessToken}` }, transformResponse: (res) => { return JSON.parse(res).subscriptions; @@ -32,7 +30,7 @@ const subscriptionApi = { categoryId: number, body: Pick ) => { - const response = await axios.post(subscriptionApi.postEndpoint(categoryId), body, { + const response = await dallogApi.post(subscriptionApi.postEndpoint(categoryId), body, { headers: { ...subscriptionApi.headers, Authorization: `Bearer ${accessToken}` }, }); @@ -43,7 +41,7 @@ const subscriptionApi = { accessToken: string | null, subscriptionId: number ): Promise> => { - const response = await axios.delete(subscriptionApi.deleteEndpoint(subscriptionId), { + const response = await dallogApi.delete(subscriptionApi.deleteEndpoint(subscriptionId), { headers: { ...subscriptionApi.headers, Authorization: `Bearer ${accessToken}` }, }); diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index a1e4e181..08e3371f 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -2,7 +2,7 @@ const API = { CATEGORY_GET_SIZE: 4, }; -const API_KEY = process.env.API_KEY; +const API_URL = process.env.API_URL; const ATOM_KEY = { USER: 'userState', @@ -34,4 +34,4 @@ const PATH = { PROFILE: '/profile', }; -export { API, API_KEY, ATOM_KEY, CACHE_KEY, CONFIRM_MESSAGE, DAYS, STORAGE_KEY, PATH }; +export { API, API_URL, ATOM_KEY, CACHE_KEY, CONFIRM_MESSAGE, DAYS, STORAGE_KEY, PATH }; diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 15af7ad2..4c3900f2 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -4,7 +4,7 @@ import { Schedule } from '@/@types'; import { CategoryType } from '@/@types/category'; import { SubscriptionType } from '@/@types/subscription'; -import { API_KEY } from '@/constants'; +import { API_URL } from '@/constants'; import categoryApi from '@/api/category'; import profileApi from '@/api/profile'; @@ -58,7 +58,7 @@ const handlers = [ }), rest.post>( - `${API_KEY}/api/members/me/categories/:id/subscriptions`, + `${API_URL}/api/members/me/categories/:id/subscriptions`, (req, res, ctx) => { const { id } = req.params; const categoryId = parseInt(id as string); @@ -79,7 +79,7 @@ const handlers = [ } ), - rest.delete(`${API_KEY}/api/members/me/subscriptions/:id`, (req, res, ctx) => { + rest.delete(`${API_URL}/api/members/me/subscriptions/:id`, (req, res, ctx) => { const { id } = req.params; const subscriptionId = parseInt(id as string); const subscriptionIndex = subscriptionDB.subscriptions.findIndex( From e0987e8d5d57eef43939a5ee72b0a7d89d0dc9fd Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 25 Jul 2022 14:25:24 +0900 Subject: [PATCH 0285/1011] =?UTF-8?q?refactor:=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20api=20endpoint=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/subscription.ts | 14 ++++++++------ frontend/src/mocks/handlers.ts | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/frontend/src/api/subscription.ts b/frontend/src/api/subscription.ts index b640afd9..6468b77d 100644 --- a/frontend/src/api/subscription.ts +++ b/frontend/src/api/subscription.ts @@ -5,9 +5,11 @@ import { SubscriptionType } from '@/@types/subscription'; import dallogApi from './'; const subscriptionApi = { - getEndpoint: '/api/members/me/subscriptions', - postEndpoint: (categoryId: number) => `/api/members/me/categories/${categoryId}/subscriptions`, - deleteEndpoint: (subscriptionId: number) => `/api/members/me/subscriptions/${subscriptionId}`, + endpoint: { + get: '/api/members/me/subscriptions', + post: (categoryId: number) => `/api/members/me/categories/${categoryId}/subscriptions`, + delete: (subscriptionId: number) => `/api/members/me/subscriptions/${subscriptionId}`, + }, headers: { 'Content-Type': 'application/json', @@ -15,7 +17,7 @@ const subscriptionApi = { }, get: async (accessToken: string | null) => { - const response = await dallogApi.get(subscriptionApi.getEndpoint, { + const response = await dallogApi.get(subscriptionApi.endpoint.get, { headers: { ...subscriptionApi.headers, Authorization: `Bearer ${accessToken}` }, transformResponse: (res) => { return JSON.parse(res).subscriptions; @@ -30,7 +32,7 @@ const subscriptionApi = { categoryId: number, body: Pick ) => { - const response = await dallogApi.post(subscriptionApi.postEndpoint(categoryId), body, { + const response = await dallogApi.post(subscriptionApi.endpoint.post(categoryId), body, { headers: { ...subscriptionApi.headers, Authorization: `Bearer ${accessToken}` }, }); @@ -41,7 +43,7 @@ const subscriptionApi = { accessToken: string | null, subscriptionId: number ): Promise> => { - const response = await dallogApi.delete(subscriptionApi.deleteEndpoint(subscriptionId), { + const response = await dallogApi.delete(subscriptionApi.endpoint.delete(subscriptionId), { headers: { ...subscriptionApi.headers, Authorization: `Bearer ${accessToken}` }, }); diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 4c3900f2..7713931a 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -53,7 +53,7 @@ const handlers = [ return res(ctx.status(201)); }), - rest.get(subscriptionApi.getEndpoint, (req, res, ctx) => { + rest.get(subscriptionApi.endpoint.get, (req, res, ctx) => { return res(ctx.status(200), ctx.json(subscriptionDB)); }), From 0217c42bb9982f3e41280c63dd5777192956a35b Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Sat, 16 Jul 2022 14:23:30 +0900 Subject: [PATCH 0286/1011] =?UTF-8?q?feat:=20=EC=8B=9C=EC=9E=91=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/@common/Button/Button.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/@common/Button/Button.tsx b/frontend/src/components/@common/Button/Button.tsx index 82b1de48..eea7841d 100644 --- a/frontend/src/components/@common/Button/Button.tsx +++ b/frontend/src/components/@common/Button/Button.tsx @@ -1,10 +1,10 @@ -import { SerializedStyles } from '@emotion/react'; +import { SerializedStyles, Theme } from '@emotion/react'; import { button } from './Button.styles'; interface ButtonProps { type?: 'button' | 'submit' | 'reset'; - cssProp?: SerializedStyles; + cssProp?: SerializedStyles | (({ colors, flex }: Theme) => SerializedStyles); onClick?: (e?: React.FormEvent) => void; children?: string | JSX.Element | JSX.Element[]; } From b6efc450e530052533f3a14fd9c37181d9d2db0b Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 20 Jul 2022 22:15:35 +0900 Subject: [PATCH 0287/1011] =?UTF-8?q?test(Category):=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=88=98=EC=A0=95=20=EC=9D=B8=EC=88=98?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/request/CategoryUpdateRequest.java | 20 +++++++++++++++ .../acceptance/CategoryAcceptanceTest.java | 25 +++++++++++++++++++ .../fixtures/CategoryAcceptanceFixtures.java | 19 ++++++++++++++ .../fixtures/CommonAcceptanceFixtures.java | 4 +++ .../common/fixtures/CategoryFixtures.java | 1 + 5 files changed, 69 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/category/dto/request/CategoryUpdateRequest.java diff --git a/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryUpdateRequest.java b/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryUpdateRequest.java new file mode 100644 index 00000000..961b7b61 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryUpdateRequest.java @@ -0,0 +1,20 @@ +package com.allog.dallog.category.dto.request; + +import javax.validation.constraints.NotBlank; + +public class CategoryUpdateRequest { + + @NotBlank + private String name; + + private CategoryUpdateRequest() { + } + + public CategoryUpdateRequest(final String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index a5bcfbff..4e31c74f 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -1,12 +1,16 @@ package com.allog.dallog.acceptance; import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.자체_토큰을_생성하고_토큰을_반환한다; +import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.id를_통해_카테고리를_가져온다; +import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.내가_등록한_카테고리를_수정한다; import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.내가_등록한_카테고리를_페이징을_통해_조회한다; import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.새로운_카테고리를_등록한다; import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.카테고리를_페이징을_통해_조회한다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_204가_반환된다; import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; +import static com.allog.dallog.common.fixtures.CategoryFixtures.MODIFIED_CATEGORY_NAME; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_1; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE_2; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; @@ -15,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.category.dto.response.CategoriesResponse; +import com.allog.dallog.category.dto.response.CategoryResponse; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.junit.jupiter.api.DisplayName; @@ -80,4 +85,24 @@ public class CategoryAcceptanceTest extends AcceptanceTest { assertThat(categoriesResponse.getCategories()).hasSize(PAGE_SIZE_2); }); } + + @DisplayName("카테고리를 등록하고 내가 등록한 카테고리를 수정하면 상태코드 204를 반환한다.") + @Test + void 카테고리를_등록하고_내가_등록한_카테고리를_수정하면_상태코드_204를_반환한다() { + // given + String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(OAUTH_PROVIDER, CODE); + CategoryResponse savedCategory = 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME) + .as(CategoryResponse.class); + + // when + ExtractableResponse response + = 내가_등록한_카테고리를_수정한다(accessToken, savedCategory.getId(), MODIFIED_CATEGORY_NAME); + CategoryResponse categoryResponse = id를_통해_카테고리를_가져온다(savedCategory.getId()).as(CategoryResponse.class); + + // then + assertAll(() -> { + 상태코드_204가_반환된다(response); + assertThat(categoryResponse.getName()).isEqualTo(MODIFIED_CATEGORY_NAME); + }); + } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java index b0497883..9e10f80a 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java @@ -1,6 +1,7 @@ package com.allog.dallog.acceptance.fixtures; import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.dto.request.CategoryUpdateRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; @@ -34,4 +35,22 @@ public class CategoryAcceptanceFixtures { .then().log().all() .extract(); } + + public static ExtractableResponse id를_통해_카테고리를_가져온다(final Long id) { + return RestAssured.given().log().all() + .when().get("/api/categories/{id}", id) + .then().log().all() + .extract(); + } + + public static ExtractableResponse 내가_등록한_카테고리를_수정한다(final String accessToken, final Long id, + final String name) { + CategoryUpdateRequest request = new CategoryUpdateRequest(name); + return RestAssured.given().log().all() + .auth().oauth2(accessToken) + .body(request) + .when().patch("/api/categories/{id}", id) + .then().log().all() + .extract(); + } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CommonAcceptanceFixtures.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CommonAcceptanceFixtures.java index 111c5ce3..5bc00788 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CommonAcceptanceFixtures.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CommonAcceptanceFixtures.java @@ -15,4 +15,8 @@ public class CommonAcceptanceFixtures { public static void 상태코드_201이_반환된다(final ExtractableResponse response) { assertThat(response.statusCode()).isEqualTo(HttpStatus.CREATED.value()); } + + public static void 상태코드_204가_반환된다(final ExtractableResponse response) { + assertThat(response.statusCode()).isEqualTo(HttpStatus.NO_CONTENT.value()); + } } diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 349647eb..9630065a 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -9,6 +9,7 @@ public class CategoryFixtures { public static final String CATEGORY_NAME = "달록"; + public static final String MODIFIED_CATEGORY_NAME = "수정된 달록"; public static final int PAGE_NUMBER_0 = 0; public static final int PAGE_NUMBER_1 = 1; From b9d2adda537fc5dc6c5a0ced963c62fb4ae2ae39 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 21 Jul 2022 04:24:05 +0900 Subject: [PATCH 0288/1011] =?UTF-8?q?test(Category):=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=82=AD=EC=A0=9C=20=EC=9D=B8=EC=88=98?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acceptance/CategoryAcceptanceTest.java | 22 +++++++++++++++++++ .../fixtures/CategoryAcceptanceFixtures.java | 8 +++++++ .../fixtures/CommonAcceptanceFixtures.java | 4 ++++ 3 files changed, 34 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 4e31c74f..47250508 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -2,6 +2,7 @@ import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.자체_토큰을_생성하고_토큰을_반환한다; import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.id를_통해_카테고리를_가져온다; +import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.내가_등록한_카테고리를_삭제한다; import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.내가_등록한_카테고리를_수정한다; import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.내가_등록한_카테고리를_페이징을_통해_조회한다; import static com.allog.dallog.acceptance.fixtures.CategoryAcceptanceFixtures.새로운_카테고리를_등록한다; @@ -9,6 +10,7 @@ import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_204가_반환된다; +import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_404가_반환된다; import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; import static com.allog.dallog.common.fixtures.CategoryFixtures.MODIFIED_CATEGORY_NAME; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_1; @@ -105,4 +107,24 @@ public class CategoryAcceptanceTest extends AcceptanceTest { assertThat(categoryResponse.getName()).isEqualTo(MODIFIED_CATEGORY_NAME); }); } + + @DisplayName("카테고리를 등록하고 내가 등록한 카테고리를 삭제하면 상태코드 204를 반환한다.") + @Test + void 카테고리를_등록하고_내가_등록한_카테고리를_삭제하면_상태코드_204를_반환한다() { + // given + TokenResponse tokenResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); + CategoryResponse savedCategory = 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME) + .as(CategoryResponse.class); + + // when + ExtractableResponse response + = 내가_등록한_카테고리를_삭제한다(tokenResponse.getAccessToken(), savedCategory.getId()); + ExtractableResponse categoryResponse = id를_통해_카테고리를_가져온다(savedCategory.getId()); + + // then + assertAll(() -> { + 상태코드_204가_반환된다(response); + 상태코드_404가_반환된다(categoryResponse); + }); + } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java index 9e10f80a..205a5a92 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java @@ -53,4 +53,12 @@ public class CategoryAcceptanceFixtures { .then().log().all() .extract(); } + + public static ExtractableResponse 내가_등록한_카테고리를_삭제한다(final String accessToken, final Long id) { + return RestAssured.given().log().all() + .auth().oauth2(accessToken) + .when().delete("/api/categories/{id}", id) + .then().log().all() + .extract(); + } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CommonAcceptanceFixtures.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CommonAcceptanceFixtures.java index 5bc00788..aa74ee0d 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CommonAcceptanceFixtures.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CommonAcceptanceFixtures.java @@ -19,4 +19,8 @@ public class CommonAcceptanceFixtures { public static void 상태코드_204가_반환된다(final ExtractableResponse response) { assertThat(response.statusCode()).isEqualTo(HttpStatus.NO_CONTENT.value()); } + + public static void 상태코드_404가_반환된다(final ExtractableResponse response) { + assertThat(response.statusCode()).isEqualTo(HttpStatus.NOT_FOUND.value()); + } } From 4ea422a11c0bfe4a4a07078870eba8f4e7b394be Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 21 Jul 2022 16:02:18 +0900 Subject: [PATCH 0289/1011] =?UTF-8?q?feat(Category):=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20id=EC=99=80=20=ED=9A=8C=EC=9B=90=20id?= =?UTF-8?q?=EA=B0=80=20=EB=AA=A8=EB=91=90=20=EC=9D=BC=EC=B9=98=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=EA=B0=80=20?= =?UTF-8?q?=EC=9E=88=EB=8A=94=EC=A7=80=20=ED=99=95=EC=9D=B8=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/domain/CategoryRepository.java | 2 ++ .../domain/CategoryRepositoryTest.java | 32 ++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java b/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java index 5edf4878..40157213 100644 --- a/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java +++ b/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java @@ -9,4 +9,6 @@ public interface CategoryRepository extends JpaRepository { Slice findSliceBy(final Pageable pageable); Slice findSliceByMemberId(final Pageable pageable, final Long memberId); + + boolean existsByIdAndMemberId(Long id, Long memberId); } diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java index c0bd3b47..62937b04 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java @@ -52,7 +52,10 @@ class CategoryRepositoryTest { assertThat(categories.getContent()).hasSize(PAGE_SIZE_2).extracting(Category::getName) .contains("알록달록 회의", "지원플랫폼 근로"); assertThat( - categories.getContent().stream().map(Category::getCreatedAt).allMatch(Objects::nonNull)).isTrue(); + categories.getContent().stream() + .map(Category::getCreatedAt) + .allMatch(Objects::nonNull)) + .isTrue(); }); } @@ -95,4 +98,31 @@ class CategoryRepositoryTest { }); } + @DisplayName("카테고리 id와 회원의 id가 모두 일치하는 카테고리가 있으면 true를 반환한다.") + @Test + void 카테고리_id와_회원의_id가_모두_일치하는_카테고리가_있으면_true를_반환한다() { + // given + Member creator = memberRepository.save(CREATOR); + Category category = categoryRepository.save(new Category("BE 공식일정", creator)); + + // when + boolean actual = categoryRepository.existsByIdAndMemberId(category.getId(), creator.getId()); + + // then + assertThat(actual).isTrue(); + } + + @DisplayName("카테고리 id와 회원의 id가 모두 일치하는 카테고리가 없으면 false를 반환한다.") + @Test + void 카테고리_id와_회원의_id가_모두_일치하는_카테고리가_없으면_false를_반환한다() { + // given + Member creator = memberRepository.save(CREATOR); + Category category = categoryRepository.save(new Category("BE 공식일정", creator)); + + // when + boolean actual = categoryRepository.existsByIdAndMemberId(category.getId(), creator.getId() + 1L); + + // then + assertThat(actual).isFalse(); + } } From dd256164ee275eb3e9d4d6edb6df1e1073051f02 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 21 Jul 2022 16:04:03 +0900 Subject: [PATCH 0290/1011] =?UTF-8?q?feat(Category):=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=88=98=EC=A0=95=20Service=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/category/domain/Category.java | 4 ++ .../category/service/CategoryService.java | 14 +++++++ .../category/service/CategoryServiceTest.java | 39 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/backend/src/main/java/com/allog/dallog/category/domain/Category.java b/backend/src/main/java/com/allog/dallog/category/domain/Category.java index 8e236b1d..5aec013f 100644 --- a/backend/src/main/java/com/allog/dallog/category/domain/Category.java +++ b/backend/src/main/java/com/allog/dallog/category/domain/Category.java @@ -49,6 +49,10 @@ private void validateNameLength(final String name) { } } + public void changeName(final String name) { + this.name = name; + } + public Long getId() { return id; } diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index 6b8e463f..a16d8e10 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -1,8 +1,10 @@ package com.allog.dallog.category.service; +import com.allog.dallog.auth.exception.NoPermissionException; import com.allog.dallog.category.domain.Category; import com.allog.dallog.category.domain.CategoryRepository; import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.dto.request.CategoryUpdateRequest; import com.allog.dallog.category.dto.response.CategoriesResponse; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.exception.NoSuchCategoryException; @@ -61,4 +63,16 @@ public Category getCategory(final Long id) { return categoryRepository.findById(id) .orElseThrow(NoSuchCategoryException::new); } + + @Transactional + public void update(final Long memberId, final Long categoryId, final CategoryUpdateRequest request) { + memberService.getMember(memberId); + Category category = getCategory(categoryId); + + if (!categoryRepository.existsByIdAndMemberId(category.getId(), memberId)) { + throw new NoPermissionException(); + } + + category.changeName(request.getName()); + } } diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 5dac4877..cbc0291f 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -1,13 +1,18 @@ package com.allog.dallog.category.service; import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; +import static com.allog.dallog.common.fixtures.CategoryFixtures.MODIFIED_CATEGORY_NAME; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_1; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE_2; import static com.allog.dallog.common.fixtures.MemberFixtures.CREATOR; +import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.allog.dallog.auth.exception.NoPermissionException; +import com.allog.dallog.category.domain.Category; import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.dto.request.CategoryUpdateRequest; import com.allog.dallog.category.dto.response.CategoriesResponse; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.exception.InvalidCategoryException; @@ -120,4 +125,38 @@ class CategoryServiceTest { .usingRecursiveComparison() .isEqualTo(savedCategory); } + + @DisplayName("회원과 카테고리 id를 통해 카테고리를 수정한다.") + @Test + void 회원과_카테고리_id를_통해_카테고리를_수정한다() { + // given + Member creator = memberRepository.save(CREATOR); + categoryService.save(creator.getId(), new CategoryCreateRequest("BE 공식일정")); + CategoryResponse savedCategory = categoryService.save(creator.getId(), new CategoryCreateRequest("FE 공식일정")); + + // when + CategoryUpdateRequest categoryUpdateRequest = new CategoryUpdateRequest(MODIFIED_CATEGORY_NAME); + categoryService.update(creator.getId(), savedCategory.getId(), categoryUpdateRequest); + + //then + Category category = categoryService.getCategory(savedCategory.getId()); + assertThat(category.getName()) + .isEqualTo(MODIFIED_CATEGORY_NAME); + } + + @DisplayName("자신이 만들지 않은 카테고리를 수정할 경우 예외를 던진다.") + @Test + void 자신이_만들지_않은_카테고리를_수정할_경우_예외를_던진다() { + // given + Member member = memberRepository.save(MEMBER); + Member creator = memberRepository.save(CREATOR); + CategoryResponse savedCategory = categoryService.save(creator.getId(), new CategoryCreateRequest("FE 공식일정")); + + CategoryUpdateRequest categoryUpdateRequest = new CategoryUpdateRequest(MODIFIED_CATEGORY_NAME); + + // when & then + assertThatThrownBy( + () -> categoryService.update(member.getId(), savedCategory.getId(), categoryUpdateRequest)) + .isInstanceOf(NoPermissionException.class); + } } From 1c705024eef1856e8fddfc9c92cbfa7ce0fe7e0f Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 21 Jul 2022 16:13:29 +0900 Subject: [PATCH 0291/1011] =?UTF-8?q?feat(Category):=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=88=98=EC=A0=95=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/category/controller/CategoryController.java | 10 ++++++++++ .../fixtures/CategoryAcceptanceFixtures.java | 7 ++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index 74458404..51941b4b 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -3,6 +3,7 @@ import com.allog.dallog.auth.dto.LoginMember; import com.allog.dallog.auth.support.AuthenticationPrincipal; import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.category.dto.request.CategoryUpdateRequest; import com.allog.dallog.category.dto.response.CategoriesResponse; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; @@ -11,6 +12,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -49,4 +51,12 @@ public ResponseEntity findMine(@AuthenticationPrincipal fina public ResponseEntity findById(@PathVariable final Long categoryId) { return ResponseEntity.ok().body(categoryService.findById(categoryId)); } + + @PatchMapping("/{categoryId}") + public ResponseEntity update(@AuthenticationPrincipal final LoginMember loginMember, + @PathVariable final Long categoryId, + @RequestBody final CategoryUpdateRequest request) { + categoryService.update(loginMember.getId(), categoryId, request); + return ResponseEntity.noContent().build(); + } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java index 205a5a92..68c0a983 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java @@ -38,7 +38,7 @@ public class CategoryAcceptanceFixtures { public static ExtractableResponse id를_통해_카테고리를_가져온다(final Long id) { return RestAssured.given().log().all() - .when().get("/api/categories/{id}", id) + .when().get("/api/categories/{categoryId}", id) .then().log().all() .extract(); } @@ -48,8 +48,9 @@ public class CategoryAcceptanceFixtures { CategoryUpdateRequest request = new CategoryUpdateRequest(name); return RestAssured.given().log().all() .auth().oauth2(accessToken) + .contentType(MediaType.APPLICATION_JSON_VALUE) .body(request) - .when().patch("/api/categories/{id}", id) + .when().patch("/api/categories/{categoryId}", id) .then().log().all() .extract(); } @@ -57,7 +58,7 @@ public class CategoryAcceptanceFixtures { public static ExtractableResponse 내가_등록한_카테고리를_삭제한다(final String accessToken, final Long id) { return RestAssured.given().log().all() .auth().oauth2(accessToken) - .when().delete("/api/categories/{id}", id) + .when().delete("/api/categories/{categoryId}", id) .then().log().all() .extract(); } From 53367cffc0d0224884d3648d61e6a3ad346858ca Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 21 Jul 2022 16:32:00 +0900 Subject: [PATCH 0292/1011] =?UTF-8?q?feat(Category):=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=82=AD=EC=A0=9C=20Service=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/service/CategoryService.java | 11 ++++++ .../category/service/CategoryServiceTest.java | 38 +++++++++++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index a16d8e10..71be8619 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -75,4 +75,15 @@ public void update(final Long memberId, final Long categoryId, final CategoryUpd category.changeName(request.getName()); } + + @Transactional + public void delete(final Long memberId, final Long categoryId) { + memberService.getMember(memberId); + + if (!categoryRepository.existsByIdAndMemberId(categoryId, memberId)) { + throw new NoPermissionException(); + } + + categoryRepository.deleteById(categoryId); + } } diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index cbc0291f..9a3a7eca 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -16,6 +16,7 @@ import com.allog.dallog.category.dto.response.CategoriesResponse; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.exception.InvalidCategoryException; +import com.allog.dallog.category.exception.NoSuchCategoryException; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; import org.junit.jupiter.api.DisplayName; @@ -131,8 +132,8 @@ class CategoryServiceTest { void 회원과_카테고리_id를_통해_카테고리를_수정한다() { // given Member creator = memberRepository.save(CREATOR); - categoryService.save(creator.getId(), new CategoryCreateRequest("BE 공식일정")); - CategoryResponse savedCategory = categoryService.save(creator.getId(), new CategoryCreateRequest("FE 공식일정")); + CategoryResponse savedCategory = categoryService.save(creator.getId(), + new CategoryCreateRequest(CATEGORY_NAME)); // when CategoryUpdateRequest categoryUpdateRequest = new CategoryUpdateRequest(MODIFIED_CATEGORY_NAME); @@ -150,7 +151,8 @@ class CategoryServiceTest { // given Member member = memberRepository.save(MEMBER); Member creator = memberRepository.save(CREATOR); - CategoryResponse savedCategory = categoryService.save(creator.getId(), new CategoryCreateRequest("FE 공식일정")); + CategoryResponse savedCategory = categoryService.save(creator.getId(), + new CategoryCreateRequest(CATEGORY_NAME)); CategoryUpdateRequest categoryUpdateRequest = new CategoryUpdateRequest(MODIFIED_CATEGORY_NAME); @@ -159,4 +161,34 @@ class CategoryServiceTest { () -> categoryService.update(member.getId(), savedCategory.getId(), categoryUpdateRequest)) .isInstanceOf(NoPermissionException.class); } + + @DisplayName("회원과 카테고리 id를 통해 카테고리를 삭제한다.") + @Test + void 회원과_카테고리_id를_통해_카테고리를_삭제한다() { + // given + Member creator = memberRepository.save(CREATOR); + CategoryResponse savedCategory = categoryService.save(creator.getId(), + new CategoryCreateRequest(CATEGORY_NAME)); + + // when + categoryService.delete(creator.getId(), savedCategory.getId()); + + //then + assertThatThrownBy(() -> categoryService.getCategory(savedCategory.getId())) + .isInstanceOf(NoSuchCategoryException.class); + } + + @DisplayName("자신이 만들지 않은 카테고리를 삭제할 경우 예외를 던진다.") + @Test + void 자신이_만들지_않은_카테고리를_삭제할_경우_예외를_던진다() { + // given + Member member = memberRepository.save(MEMBER); + Member creator = memberRepository.save(CREATOR); + CategoryResponse savedCategory = categoryService.save(creator.getId(), new CategoryCreateRequest("FE 공식일정")); + + // when & then + assertThatThrownBy( + () -> categoryService.delete(member.getId(), savedCategory.getId())) + .isInstanceOf(NoPermissionException.class); + } } From 48fdc48d8a1b32813560fa4cd35664650f25d2be Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 21 Jul 2022 16:39:21 +0900 Subject: [PATCH 0293/1011] =?UTF-8?q?feat(Category):=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=82=AD=EC=A0=9C=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/category/controller/CategoryController.java | 8 ++++++++ .../allog/dallog/acceptance/CategoryAcceptanceTest.java | 8 ++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java index 51941b4b..f2f543f0 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java @@ -11,6 +11,7 @@ import javax.validation.Valid; import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -59,4 +60,11 @@ public ResponseEntity update(@AuthenticationPrincipal final LoginMember lo categoryService.update(loginMember.getId(), categoryId, request); return ResponseEntity.noContent().build(); } + + @DeleteMapping("/{categoryId}") + public ResponseEntity delete(@AuthenticationPrincipal final LoginMember loginMember, + @PathVariable final Long categoryId) { + categoryService.delete(loginMember.getId(), categoryId); + return ResponseEntity.noContent().build(); + } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 47250508..52ef5fdc 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -10,7 +10,6 @@ import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_204가_반환된다; -import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_404가_반환된다; import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; import static com.allog.dallog.common.fixtures.CategoryFixtures.MODIFIED_CATEGORY_NAME; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_1; @@ -119,12 +118,9 @@ public class CategoryAcceptanceTest extends AcceptanceTest { // when ExtractableResponse response = 내가_등록한_카테고리를_삭제한다(tokenResponse.getAccessToken(), savedCategory.getId()); - ExtractableResponse categoryResponse = id를_통해_카테고리를_가져온다(savedCategory.getId()); + // todo: ExceptionHandler 구현 이후 카테고리 단건 조회 응답 상태코드 404인지 확인 // then - assertAll(() -> { - 상태코드_204가_반환된다(response); - 상태코드_404가_반환된다(categoryResponse); - }); + 상태코드_204가_반환된다(response); } } From 1e4b3b4ae16d92ab68ade2360397fb8f5918e68f Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 21 Jul 2022 18:07:05 +0900 Subject: [PATCH 0294/1011] =?UTF-8?q?test:=20Import=20=EC=96=B4=EB=85=B8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/member/domain/MemberRepositoryTest.java | 3 +++ .../allog/dallog/schedule/domain/ScheduleRepositoryTest.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java b/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java index e465030c..e0956554 100644 --- a/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java @@ -5,12 +5,15 @@ import static com.allog.dallog.common.fixtures.MemberFixtures.PROFILE_IMAGE_URI; import static org.assertj.core.api.Assertions.assertThat; +import com.allog.dallog.global.config.JpaConfig; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; @DataJpaTest +@Import(JpaConfig.class) class MemberRepositoryTest { @Autowired diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java index 8a43d67b..1da9ed25 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java @@ -6,14 +6,17 @@ import static com.allog.dallog.common.fixtures.ScheduleFixtures.TITLE; import static org.assertj.core.api.Assertions.assertThat; +import com.allog.dallog.global.config.JpaConfig; import java.time.LocalDateTime; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; @DataJpaTest +@Import(JpaConfig.class) class ScheduleRepositoryTest { @Autowired From 13cb291585271fb2753954cdfd154d5b70515f9d Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 21 Jul 2022 18:07:22 +0900 Subject: [PATCH 0295/1011] =?UTF-8?q?test:=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/acceptance/CategoryAcceptanceTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index 52ef5fdc..b277ad0b 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -111,13 +111,13 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @Test void 카테고리를_등록하고_내가_등록한_카테고리를_삭제하면_상태코드_204를_반환한다() { // given - TokenResponse tokenResponse = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); - CategoryResponse savedCategory = 새로운_카테고리를_등록한다(tokenResponse, CATEGORY_NAME) + String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(OAUTH_PROVIDER, CODE); + CategoryResponse savedCategory = 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME) .as(CategoryResponse.class); // when ExtractableResponse response - = 내가_등록한_카테고리를_삭제한다(tokenResponse.getAccessToken(), savedCategory.getId()); + = 내가_등록한_카테고리를_삭제한다(accessToken, savedCategory.getId()); // todo: ExceptionHandler 구현 이후 카테고리 단건 조회 응답 상태코드 404인지 확인 // then From ac0b4945c4cca8447f77a516112cd91b7311b03f Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 21 Jul 2022 18:34:20 +0900 Subject: [PATCH 0296/1011] =?UTF-8?q?chore:=20ddl=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/test/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/resources/application.properties b/backend/src/test/resources/application.properties index b3dada05..d7ad05e8 100644 --- a/backend/src/test/resources/application.properties +++ b/backend/src/test/resources/application.properties @@ -3,7 +3,7 @@ spring.datasource.url=jdbc:h2:~/dallog;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_ spring.datasource.username=sa spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true -spring.jpa.hibernate.ddl-auto=create +spring.jpa.hibernate.ddl-auto=create-drop logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE spring.main.allow-bean-definition-overriding=true oauth.google.redirect_uri=http://localhost:3000 From e947cdeedbc48a789982f63ed9042e6e7a28859e Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 21 Jul 2022 18:43:48 +0900 Subject: [PATCH 0297/1011] =?UTF-8?q?chore:=20ddl=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/test/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/resources/application.properties b/backend/src/test/resources/application.properties index d7ad05e8..b3dada05 100644 --- a/backend/src/test/resources/application.properties +++ b/backend/src/test/resources/application.properties @@ -3,7 +3,7 @@ spring.datasource.url=jdbc:h2:~/dallog;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_ spring.datasource.username=sa spring.jpa.properties.hibernate.format_sql=true spring.jpa.show-sql=true -spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.hibernate.ddl-auto=create logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE spring.main.allow-bean-definition-overriding=true oauth.google.redirect_uri=http://localhost:3000 From f781f0af03e1c3d69af5b9c22f35f9ea374efaa1 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 21 Jul 2022 19:36:35 +0900 Subject: [PATCH 0298/1011] =?UTF-8?q?test:=20=EA=B0=9D=EC=B2=B4=EB=A5=BC?= =?UTF-8?q?=20=ED=94=BD=EC=8A=A4=EC=B2=98=EA=B0=80=20=EC=95=84=EB=8B=88?= =?UTF-8?q?=EB=9D=BC=20=EC=A7=81=EC=A0=91=20=EC=83=9D=EC=84=B1=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B2=83=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/service/CategoryServiceTest.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 9a3a7eca..8cd05b5e 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -5,7 +5,9 @@ import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_1; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE_2; import static com.allog.dallog.common.fixtures.MemberFixtures.CREATOR; -import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; +import static com.allog.dallog.common.fixtures.MemberFixtures.DISPLAY_NAME; +import static com.allog.dallog.common.fixtures.MemberFixtures.EMAIL; +import static com.allog.dallog.common.fixtures.MemberFixtures.PROFILE_IMAGE_URI; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -19,6 +21,7 @@ import com.allog.dallog.category.exception.NoSuchCategoryException; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; +import com.allog.dallog.member.domain.SocialType; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -26,10 +29,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.PageRequest; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.transaction.annotation.Transactional; @Transactional @SpringBootTest +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class CategoryServiceTest { @Autowired @@ -149,8 +154,9 @@ class CategoryServiceTest { @Test void 자신이_만들지_않은_카테고리를_수정할_경우_예외를_던진다() { // given - Member member = memberRepository.save(MEMBER); - Member creator = memberRepository.save(CREATOR); + Member member = memberRepository.save(new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE)); + Member creator = memberRepository.save( + new Member("creator@email.com", "/image.png", "creator", SocialType.GOOGLE)); CategoryResponse savedCategory = categoryService.save(creator.getId(), new CategoryCreateRequest(CATEGORY_NAME)); @@ -182,8 +188,9 @@ class CategoryServiceTest { @Test void 자신이_만들지_않은_카테고리를_삭제할_경우_예외를_던진다() { // given - Member member = memberRepository.save(MEMBER); - Member creator = memberRepository.save(CREATOR); + Member member = memberRepository.save(new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE)); + Member creator = memberRepository.save( + new Member("creator@email.com", "/image.png", "creator", SocialType.GOOGLE)); CategoryResponse savedCategory = categoryService.save(creator.getId(), new CategoryCreateRequest("FE 공식일정")); // when & then From e78c1dae5e1caa9be8c80987aac252acbec9ce00 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Mon, 25 Jul 2022 16:49:36 +0900 Subject: [PATCH 0299/1011] =?UTF-8?q?test:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/category/service/CategoryServiceTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 8cd05b5e..990f419a 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -29,12 +29,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.PageRequest; -import org.springframework.test.annotation.DirtiesContext; import org.springframework.transaction.annotation.Transactional; @Transactional @SpringBootTest -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) class CategoryServiceTest { @Autowired From 82a8be0b37334e2d6222a9d5a6072f8d9a131f72 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Mon, 25 Jul 2022 16:52:40 +0900 Subject: [PATCH 0300/1011] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/allog/dallog/category/domain/Category.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/domain/Category.java b/backend/src/main/java/com/allog/dallog/category/domain/Category.java index 5aec013f..780a42d4 100644 --- a/backend/src/main/java/com/allog/dallog/category/domain/Category.java +++ b/backend/src/main/java/com/allog/dallog/category/domain/Category.java @@ -40,6 +40,11 @@ public Category(final String name, final Member member) { this.member = member; } + public void changeName(final String name) { + validateNameLength(name); + this.name = name; + } + private void validateNameLength(final String name) { if (name.isBlank()) { throw new InvalidCategoryException("카테고리 이름은 공백일 수 없습니다."); @@ -49,10 +54,6 @@ private void validateNameLength(final String name) { } } - public void changeName(final String name) { - this.name = name; - } - public Long getId() { return id; } From 9154a886db1a3b03206079834bad75246b6cfe5c Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Mon, 25 Jul 2022 16:54:49 +0900 Subject: [PATCH 0301/1011] =?UTF-8?q?refactor:=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/category/service/CategoryService.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index 71be8619..8f92c564 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -69,9 +69,7 @@ public void update(final Long memberId, final Long categoryId, final CategoryUpd memberService.getMember(memberId); Category category = getCategory(categoryId); - if (!categoryRepository.existsByIdAndMemberId(category.getId(), memberId)) { - throw new NoPermissionException(); - } + validatePermission(memberId, categoryId); category.changeName(request.getName()); } @@ -80,10 +78,14 @@ public void update(final Long memberId, final Long categoryId, final CategoryUpd public void delete(final Long memberId, final Long categoryId) { memberService.getMember(memberId); + validatePermission(memberId, categoryId); + + categoryRepository.deleteById(categoryId); + } + + private void validatePermission(final Long memberId, final Long categoryId) { if (!categoryRepository.existsByIdAndMemberId(categoryId, memberId)) { throw new NoPermissionException(); } - - categoryRepository.deleteById(categoryId); } } From 7f6a9730b33c6081e3c4d3bc2810a815e70cc01d Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Mon, 25 Jul 2022 20:17:16 +0900 Subject: [PATCH 0302/1011] =?UTF-8?q?feat:=20=EC=82=AC=EC=9D=B4=EB=93=9C?= =?UTF-8?q?=20=EB=B0=94=20recoil=20selector=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: jhy979 --- frontend/.prettierrc.json | 2 +- frontend/src/App.tsx | 9 ++------- .../CategoryAddModal/CategoryAddModal.tsx | 2 +- .../components/CategoryItem/CategoryItem.tsx | 2 +- .../components/CategoryList/CategoryList.tsx | 2 +- frontend/src/components/NavBar/NavBar.tsx | 16 ++++++++++------ frontend/src/components/ProtectRoute/index.tsx | 2 +- .../src/components/SideBar/SideBar.styles.ts | 10 +++++----- frontend/src/components/SideBar/SideBar.tsx | 15 ++++++++------- frontend/src/constants/index.ts | 17 ++++++++++++++++- frontend/src/pages/MainPage/MainPage.tsx | 2 +- frontend/src/pages/MyPage/MyPage.tsx | 2 +- frontend/src/{ => recoil}/atoms/index.ts | 7 ++++++- frontend/src/recoil/selectors/index.ts | 13 +++++++++++++ 14 files changed, 67 insertions(+), 34 deletions(-) rename frontend/src/{ => recoil}/atoms/index.ts (66%) create mode 100644 frontend/src/recoil/selectors/index.ts diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json index 597ae9eb..ca2ae640 100644 --- a/frontend/.prettierrc.json +++ b/frontend/.prettierrc.json @@ -12,7 +12,7 @@ "importOrder": [ "@/hooks/(.*)$", "@/@types", - "@/atoms", + "@/recoil/(atoms|selectors)", "@/styles/(.*)$", "@/(components/@common/|components/|pages/)(.*)$", "@/constants", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 33109c2e..92e53308 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -14,16 +14,11 @@ import { PATH } from '@/constants'; function App() { const { state: isLoginModalOpen, toggleState: toggleLoginModalOpen } = useToggle(); - const { state: isSideBarOpen, toggleState: toggleSideBarOpen } = useToggle(); return ( - - + + void; openLoginModal: () => void; } -function NavBar({ isSideBarOpen, toggleSideBarOpen, openLoginModal }: NavBarProps) { +function NavBar({ openLoginModal }: NavBarProps) { + const [isSideBarOpen, toggleSideBarOpen] = useRecoilState(sideBarSelector); const { accessToken } = useRecoilValue(userState); const theme = useTheme(); const navigate = useNavigate(); + const handleClickSideBarButton = () => { + toggleSideBarOpen(isSideBarOpen); + }; + const handleClickMainButton = () => { navigate(PATH.MAIN); }; @@ -41,7 +45,7 @@ function NavBar({ isSideBarOpen, toggleSideBarOpen, openLoginModal }: NavBarProp return (
- diff --git a/frontend/src/components/ProtectRoute/index.tsx b/frontend/src/components/ProtectRoute/index.tsx index ffb9d6c9..d57c2823 100644 --- a/frontend/src/components/ProtectRoute/index.tsx +++ b/frontend/src/components/ProtectRoute/index.tsx @@ -1,7 +1,7 @@ import { Navigate, Outlet } from 'react-router-dom'; import { useRecoilState } from 'recoil'; -import { userState } from '@/atoms'; +import { userState } from '@/recoil/atoms'; import { PATH } from '@/constants'; diff --git a/frontend/src/components/SideBar/SideBar.styles.ts b/frontend/src/components/SideBar/SideBar.styles.ts index 808d90bd..4537b142 100644 --- a/frontend/src/components/SideBar/SideBar.styles.ts +++ b/frontend/src/components/SideBar/SideBar.styles.ts @@ -1,14 +1,14 @@ import { css, Theme } from '@emotion/react'; -const sideBar = ({ colors, flex }: Theme, isOpen: boolean) => css` +const sideBar = ({ colors, flex }: Theme, isSideBarOpen: boolean) => css` ${flex.row} position: absolute; z-index: 10; - width: ${isOpen ? '64rem' : '0'}; + width: ${isSideBarOpen ? '64rem' : '0'}; height: 100vh; - padding: ${isOpen ? '5rem' : '0'}; + padding: ${isSideBarOpen ? '5rem' : '0'}; border: 1px solid ${colors.GRAY_400}; background: ${colors.WHITE}; @@ -16,10 +16,10 @@ const sideBar = ({ colors, flex }: Theme, isOpen: boolean) => css` transition: width 0.3s; `; -const list = ({ flex }: Theme, isOpen: boolean) => css` +const list = ({ flex }: Theme, isSideBarOpen: boolean) => css` ${flex.column} - display: ${isOpen ? 'flex' : 'none'}; + display: ${isSideBarOpen ? 'flex' : 'none'}; gap: 3rem; width: 56rem; diff --git a/frontend/src/components/SideBar/SideBar.tsx b/frontend/src/components/SideBar/SideBar.tsx index aa10b7e1..b7cec39e 100644 --- a/frontend/src/components/SideBar/SideBar.tsx +++ b/frontend/src/components/SideBar/SideBar.tsx @@ -1,7 +1,10 @@ import { useTheme } from '@emotion/react'; +import { useRecoilValue } from 'recoil'; import useToggle from '@/hooks/useToggle'; +import { sideBarState } from '@/recoil/atoms'; + import Button from '@/components/@common/Button/Button'; import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; import CategoryAddModal from '@/components/CategoryAddModal/CategoryAddModal'; @@ -11,17 +14,15 @@ import { RiDeleteBin6Line } from 'react-icons/ri'; import { button, list, myCategory, sideBar, title } from './SideBar.styles'; -interface SideBarProps { - isOpen: boolean; -} - -function SideBar({ isOpen }: SideBarProps) { +function SideBar() { + const isSideBarOpen = useRecoilValue(sideBarState); const theme = useTheme(); + const { state: isCategoryAddModalOpen, toggleState: toggleCategoryAddModalOpen } = useToggle(); return ( -
-
+
+
diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 08e3371f..18b3371f 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -5,6 +5,7 @@ const API = { const API_URL = process.env.API_URL; const ATOM_KEY = { + SIDE_BAR: 'sideBarState', USER: 'userState', }; @@ -23,6 +24,10 @@ const CONFIRM_MESSAGE = { const DAYS = ['일', '월', '화', '수', '목', '금', '토']; +const SELECTOR_KEY = { + SIDE_BAR: 'sideBarSelector', +}; + const STORAGE_KEY = { ACCESS_TOKEN: 'accessToken', }; @@ -34,4 +39,14 @@ const PATH = { PROFILE: '/profile', }; -export { API, API_URL, ATOM_KEY, CACHE_KEY, CONFIRM_MESSAGE, DAYS, STORAGE_KEY, PATH }; +export { + API, + API_URL, + ATOM_KEY, + CACHE_KEY, + CONFIRM_MESSAGE, + DAYS, + SELECTOR_KEY, + STORAGE_KEY, + PATH, +}; diff --git a/frontend/src/pages/MainPage/MainPage.tsx b/frontend/src/pages/MainPage/MainPage.tsx index 192a281b..b783e9ef 100644 --- a/frontend/src/pages/MainPage/MainPage.tsx +++ b/frontend/src/pages/MainPage/MainPage.tsx @@ -1,7 +1,7 @@ import { useEffect } from 'react'; import { useRecoilState } from 'recoil'; -import { userState } from '@/atoms'; +import { userState } from '@/recoil/atoms'; import CalendarPage from '@/pages/CalendarPage/CalendarPage'; import StartPage from '@/pages/StartPage/StartPage'; diff --git a/frontend/src/pages/MyPage/MyPage.tsx b/frontend/src/pages/MyPage/MyPage.tsx index cbbaf4bf..638eefca 100644 --- a/frontend/src/pages/MyPage/MyPage.tsx +++ b/frontend/src/pages/MyPage/MyPage.tsx @@ -4,7 +4,7 @@ import { useRecoilValue } from 'recoil'; import { ProfileType } from '@/@types/profile'; -import { userState } from '@/atoms'; +import { userState } from '@/recoil/atoms'; import { CACHE_KEY } from '@/constants'; diff --git a/frontend/src/atoms/index.ts b/frontend/src/recoil/atoms/index.ts similarity index 66% rename from frontend/src/atoms/index.ts rename to frontend/src/recoil/atoms/index.ts index ef31392f..5093dcb6 100644 --- a/frontend/src/atoms/index.ts +++ b/frontend/src/recoil/atoms/index.ts @@ -4,6 +4,11 @@ import { ATOM_KEY } from '@/constants'; import { getAccessToken } from '@/utils'; +const sideBarState = atom({ + key: ATOM_KEY.SIDE_BAR, + default: false, +}); + const userState = atom({ key: ATOM_KEY.USER, default: { @@ -11,4 +16,4 @@ const userState = atom({ }, }); -export { userState }; +export { sideBarState, userState }; diff --git a/frontend/src/recoil/selectors/index.ts b/frontend/src/recoil/selectors/index.ts new file mode 100644 index 00000000..4372137a --- /dev/null +++ b/frontend/src/recoil/selectors/index.ts @@ -0,0 +1,13 @@ +import { selector } from 'recoil'; + +import { sideBarState } from '@/recoil/atoms'; + +import { SELECTOR_KEY } from '@/constants'; + +const sideBarSelector = selector({ + key: SELECTOR_KEY.SIDE_BAR, + get: ({ get }) => get(sideBarState), + set: ({ set }) => set(sideBarState, (prev) => !prev), +}); + +export { sideBarSelector }; From 2a96f1b5705273b3399bbf99cf2b5a1de51fd6e3 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Mon, 25 Jul 2022 21:15:27 +0900 Subject: [PATCH 0303/1011] =?UTF-8?q?feat:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: jhy979 --- .../@common/PageLayout/PageLayout.styles.ts | 13 +++++++ .../@common/PageLayout/PageLayout.tsx | 17 ++++++++++ .../components/Calendar/Calendar.styles.ts | 6 +--- .../CategoryList/CategoryList.styles.ts | 4 +++ .../components/CategoryList/CategoryList.tsx | 28 ++++++++------- .../src/components/SideBar/SideBar.styles.ts | 5 +-- .../src/pages/CalendarPage/CalendarPage.tsx | 17 ++++++---- .../pages/CategoryPage/CategoryPage.styles.ts | 5 ++- .../src/pages/CategoryPage/CategoryPage.tsx | 21 +++++++----- frontend/src/pages/MyPage/MyPage.styles.ts | 4 +-- frontend/src/pages/MyPage/MyPage.tsx | 34 +++++++++++-------- 11 files changed, 98 insertions(+), 56 deletions(-) create mode 100644 frontend/src/components/@common/PageLayout/PageLayout.styles.ts create mode 100644 frontend/src/components/@common/PageLayout/PageLayout.tsx diff --git a/frontend/src/components/@common/PageLayout/PageLayout.styles.ts b/frontend/src/components/@common/PageLayout/PageLayout.styles.ts new file mode 100644 index 00000000..6e304a55 --- /dev/null +++ b/frontend/src/components/@common/PageLayout/PageLayout.styles.ts @@ -0,0 +1,13 @@ +import { css } from '@emotion/react'; + +const pageLayout = (isSideBarOpen: boolean) => css` + overflow-y: scroll; + + height: calc(100vh - 16rem); + margin-top: 16rem; + margin-left: ${isSideBarOpen ? '64rem' : '0'}; + + transition: margin-left 0.3s; +`; + +export { pageLayout }; diff --git a/frontend/src/components/@common/PageLayout/PageLayout.tsx b/frontend/src/components/@common/PageLayout/PageLayout.tsx new file mode 100644 index 00000000..15f2f439 --- /dev/null +++ b/frontend/src/components/@common/PageLayout/PageLayout.tsx @@ -0,0 +1,17 @@ +import { useRecoilValue } from 'recoil'; + +import { sideBarState } from '@/recoil/atoms'; + +import { pageLayout } from './PageLayout.styles'; + +interface PageLayoutProps { + children: JSX.Element | JSX.Element[]; +} + +function PageLayout({ children }: PageLayoutProps) { + const isSideBarOpen = useRecoilValue(sideBarState); + + return
{children}
; +} + +export default PageLayout; diff --git a/frontend/src/components/Calendar/Calendar.styles.ts b/frontend/src/components/Calendar/Calendar.styles.ts index d3486957..9a78b88c 100644 --- a/frontend/src/components/Calendar/Calendar.styles.ts +++ b/frontend/src/components/Calendar/Calendar.styles.ts @@ -3,7 +3,6 @@ import { css, Theme } from '@emotion/react'; import { DAYS } from '@/constants'; const calendar = css` - height: 95vh; margin: 3rem; `; @@ -13,7 +12,6 @@ const calendarHeader = ({ flex }: Theme) => css` justify-content:space-between; width: 100%; - height: 5vh; padding: 3rem; font-size: 6rem; @@ -44,14 +42,12 @@ const navButton = css` const navBarGrid = css` display: grid; grid-template-columns: repeat(7, calc(100% / 7)); - - height: 5vh; `; const calendarGrid = (rowNum: number) => css` display: grid; grid-template-columns: repeat(7, calc(100% / 7)); - grid-auto-rows: calc(85vh / ${rowNum}); + grid-auto-rows: calc(75vh / ${rowNum}); `; const dayBar = ({ colors }: Theme, day: string) => css` diff --git a/frontend/src/components/CategoryList/CategoryList.styles.ts b/frontend/src/components/CategoryList/CategoryList.styles.ts index 861bc11c..fb441e5d 100644 --- a/frontend/src/components/CategoryList/CategoryList.styles.ts +++ b/frontend/src/components/CategoryList/CategoryList.styles.ts @@ -1,7 +1,10 @@ import { css, Theme } from '@emotion/react'; const categoryTable = css` + overflow-y: scroll; + width: 100%; + height: 72vh; `; const categoryTableHeader = ({ flex, colors }: Theme) => css` @@ -9,6 +12,7 @@ const categoryTableHeader = ({ flex, colors }: Theme) => css` justify-content: space-around; + width: 100%; height: 12rem; border-bottom: 2px solid ${colors.GRAY_400}; diff --git a/frontend/src/components/CategoryList/CategoryList.tsx b/frontend/src/components/CategoryList/CategoryList.tsx index 21f8b429..f4005b3e 100644 --- a/frontend/src/components/CategoryList/CategoryList.tsx +++ b/frontend/src/components/CategoryList/CategoryList.tsx @@ -49,23 +49,27 @@ function CategoryList({ categoryList, getMoreCategories, hasNextPage }: Category }); return ( -
+ <>
생성 날짜 카테고리 이름 구독 상태
- {categoryList.map((category) => { - const { subscriptionId } = subscriptionList.find((el) => el.categoryId === category.id) ?? { - subscriptionId: -1, - }; - - return ( - - ); - })} -
-
+
+ {categoryList.map((category) => { + const { subscriptionId } = subscriptionList.find( + (el) => el.categoryId === category.id + ) ?? { + subscriptionId: -1, + }; + + return ( + + ); + })} +
+
+ ); } diff --git a/frontend/src/components/SideBar/SideBar.styles.ts b/frontend/src/components/SideBar/SideBar.styles.ts index 4537b142..a6218b78 100644 --- a/frontend/src/components/SideBar/SideBar.styles.ts +++ b/frontend/src/components/SideBar/SideBar.styles.ts @@ -3,11 +3,12 @@ import { css, Theme } from '@emotion/react'; const sideBar = ({ colors, flex }: Theme, isSideBarOpen: boolean) => css` ${flex.row} - position: absolute; + overflow: hidden; + position: fixed; z-index: 10; width: ${isSideBarOpen ? '64rem' : '0'}; - height: 100vh; + height: calc(100vh - 16rem); padding: ${isSideBarOpen ? '5rem' : '0'}; border: 1px solid ${colors.GRAY_400}; diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index 1a8adf1b..8aa3ced0 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -7,6 +7,7 @@ import useToggle from '@/hooks/useToggle'; import { Schedule } from '@/@types'; import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; +import PageLayout from '@/components/@common/PageLayout/PageLayout'; import Calendar from '@/components/Calendar/Calendar'; import ScheduleAddButton from '@/components/ScheduleAddButton/ScheduleAddButton'; import ScheduleAddModal from '@/components/ScheduleAddModal/ScheduleAddModal'; @@ -49,13 +50,15 @@ function CalendarPage() { } return ( -
- - - - - -
+ +
+ + + + + +
+
); } diff --git a/frontend/src/pages/CategoryPage/CategoryPage.styles.ts b/frontend/src/pages/CategoryPage/CategoryPage.styles.ts index 62dd9348..157494a9 100644 --- a/frontend/src/pages/CategoryPage/CategoryPage.styles.ts +++ b/frontend/src/pages/CategoryPage/CategoryPage.styles.ts @@ -5,18 +5,17 @@ const categoryPage = ({ flex }: Theme) => css` align-items: center; - margin-top: 16rem; - padding: 10rem 20rem; + padding: 5rem; `; const categoryNav = css` width: 100%; + margin-bottom: 5rem; `; const categorySearch = css` width: 62.5rem; height: 12.5rem; - margin-bottom: 17.5rem; `; export { categoryPage, categoryNav, categorySearch }; diff --git a/frontend/src/pages/CategoryPage/CategoryPage.tsx b/frontend/src/pages/CategoryPage/CategoryPage.tsx index b7d09abb..b225dc21 100644 --- a/frontend/src/pages/CategoryPage/CategoryPage.tsx +++ b/frontend/src/pages/CategoryPage/CategoryPage.tsx @@ -4,6 +4,7 @@ import { useInfiniteQuery } from 'react-query'; import { CategoriesGetResponseType } from '@/@types/category'; import FieldSet from '@/components/@common/FieldSet/FieldSet'; +import PageLayout from '@/components/@common/PageLayout/PageLayout'; import CategoryList from '@/components/CategoryList/CategoryList'; import { API, CACHE_KEY } from '@/constants'; @@ -42,16 +43,18 @@ function CategoryPage() { const categoryList = categoriesGetResponse.pages.flatMap(({ data }) => data.categories); return ( -
-
-
+ +
+
+
+
+
- -
+ ); } diff --git a/frontend/src/pages/MyPage/MyPage.styles.ts b/frontend/src/pages/MyPage/MyPage.styles.ts index 9ff3d661..ecc8d5fb 100644 --- a/frontend/src/pages/MyPage/MyPage.styles.ts +++ b/frontend/src/pages/MyPage/MyPage.styles.ts @@ -1,9 +1,7 @@ import { css, Theme } from '@emotion/react'; const myPage = ({ colors }: Theme) => css` - width: 100vw; - height: 100vh; - margin-top: 16rem; + width: 100%; padding: 2rem; background: ${colors.GRAY_100}; diff --git a/frontend/src/pages/MyPage/MyPage.tsx b/frontend/src/pages/MyPage/MyPage.tsx index 638eefca..246a0083 100644 --- a/frontend/src/pages/MyPage/MyPage.tsx +++ b/frontend/src/pages/MyPage/MyPage.tsx @@ -6,6 +6,8 @@ import { ProfileType } from '@/@types/profile'; import { userState } from '@/recoil/atoms'; +import PageLayout from '@/components/@common/PageLayout/PageLayout'; + import { CACHE_KEY } from '@/constants'; import profileAPI from '@/api/profile'; @@ -41,23 +43,25 @@ function MyPage() { const { displayName, email, profileImageUrl } = profileGetResponse.data; return ( -
-
-
프로필
-
- 이름(닉네임) - {displayName} -
-
- 계정 - {email} -
-
- 프로필 사진 - 프로필 이미지 + +
+
+
프로필
+
+ 이름(닉네임) + {displayName} +
+
+ 계정 + {email} +
+
+ 프로필 사진 + 프로필 이미지 +
-
+ ); } From daaaadf3468125f1c168e1872ef96051c5362de3 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Tue, 26 Jul 2022 00:33:37 +0900 Subject: [PATCH 0304/1011] =?UTF-8?q?feat:=20properties=20=ED=98=95?= =?UTF-8?q?=EC=8B=9D=EC=9D=84=20yml=20=ED=98=95=EC=8B=9D=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oauth/client/GoogleOAuthClient.java | 37 +++++++++-------- .../oauth/uri/GoogleOAuthUri.java | 30 +++++++------- .../src/main/resources/application.properties | 15 ------- backend/src/main/resources/application.yml | 39 ++++++++++++++++++ .../src/test/resources/application.properties | 14 ------- backend/src/test/resources/application.yml | 41 +++++++++++++++++++ 6 files changed, 116 insertions(+), 60 deletions(-) delete mode 100644 backend/src/main/resources/application.properties create mode 100644 backend/src/main/resources/application.yml delete mode 100644 backend/src/test/resources/application.properties create mode 100644 backend/src/test/resources/application.yml diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java index 848c6a79..3cacf0a8 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java @@ -24,22 +24,25 @@ public class GoogleOAuthClient implements OAuthClient { private static final String JWT_DELIMITER = "\\."; - private final String googleRedirectUri; - private final String googleClientId; - private final String googleClientSecret; - private final String googleTokenUri; + private final String clientId; + private final String clientSecret; + private final String grantType; + private final String redirectUri; + private final String tokenUri; private final RestTemplate restTemplate; private final ObjectMapper objectMapper; - public GoogleOAuthClient(@Value("${oauth.google.redirect_uri}") final String googleRedirectUri, - @Value("${oauth.google.client_id}") final String googleClientId, - @Value("${oauth.google.client_secret}") final String googleClientSecret, - @Value("${oauth.google.token_uri}") final String googleTokenUri, + public GoogleOAuthClient(@Value("${oauth.google.client-id}") final String clientId, + @Value("${oauth.google.client-secret}") final String clientSecret, + @Value("oauth.google.grant-type") final String grantType, + @Value("${oauth.google.redirect-uri}") final String redirectUri, + @Value("${oauth.google.token-uri}") final String tokenUri, final RestTemplateBuilder restTemplateBuilder, final ObjectMapper objectMapper) { - this.googleRedirectUri = googleRedirectUri; - this.googleClientId = googleClientId; - this.googleClientSecret = googleClientSecret; - this.googleTokenUri = googleTokenUri; + this.clientId = clientId; + this.clientSecret = clientSecret; + this.grantType = grantType; + this.redirectUri = redirectUri; + this.tokenUri = tokenUri; this.restTemplate = restTemplateBuilder.build(); this.objectMapper = objectMapper; } @@ -63,16 +66,16 @@ private GoogleTokenResponse requestGoogleToken(final String code) { MultiValueMap params = generateRequestParams(code); HttpEntity> request = new HttpEntity<>(params, headers); - return restTemplate.postForEntity(googleTokenUri, request, GoogleTokenResponse.class).getBody(); + return restTemplate.postForEntity(tokenUri, request, GoogleTokenResponse.class).getBody(); } private MultiValueMap generateRequestParams(final String code) { MultiValueMap params = new LinkedMultiValueMap<>(); - params.add("client_id", googleClientId); - params.add("client_secret", googleClientSecret); + params.add("client_id", clientId); + params.add("client_secret", clientSecret); params.add("code", code); - params.add("grant_type", "authorization_code"); - params.add("redirect_uri", googleRedirectUri); + params.add("grant_type", grantType); + params.add("redirect_uri", redirectUri); return params; } diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java index 5748d04c..967cdacd 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java @@ -8,25 +8,27 @@ @Component public class GoogleOAuthUri implements OAuthUri { - private static final String GOOGLE_OAUTH_END_POINT = "https://accounts.google.com/o/oauth2/v2/auth"; - private static final List SCOPES = List.of("https://www.googleapis.com/auth/userinfo.profile", - "https://www.googleapis.com/auth/userinfo.email"); + private final String oauthEndPoint; + private final String clientId; + private final String redirectUri; + private final List scopes; - private final String googleRedirectUri; - private final String googleClientId; - - public GoogleOAuthUri(@Value("${oauth.google.redirect_uri}") final String googleRedirectUri, - @Value("${oauth.google.client_id}") final String googleClientId) { - this.googleRedirectUri = googleRedirectUri; - this.googleClientId = googleClientId; + public GoogleOAuthUri(@Value("${oauth.google.oauth-end-point}") final String oauthEndPoint, + @Value("${oauth.google.client-id}") final String clientId, + @Value("${oauth.google.redirect-uri}") final String redirectUri, + @Value("${oauth.google.scopes}") final List scopes) { + this.oauthEndPoint = oauthEndPoint; + this.clientId = clientId; + this.redirectUri = redirectUri; + this.scopes = scopes; } @Override public String generate() { - return GOOGLE_OAUTH_END_POINT + "?" - + "client_id=" + googleClientId + "&" - + "redirect_uri=" + googleRedirectUri + "&" + return oauthEndPoint + "?" + + "client_id=" + clientId + "&" + + "redirect_uri=" + redirectUri + "&" + "response_type=code&" - + "scope=" + String.join(" ", SCOPES); + + "scope=" + String.join(" ", scopes); } } diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties deleted file mode 100644 index 1da117aa..00000000 --- a/backend/src/main/resources/application.properties +++ /dev/null @@ -1,15 +0,0 @@ -spring.sql.init.mode=always -spring.datasource.url=jdbc:h2:~/dallog;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE -spring.datasource.username=sa -spring.jpa.properties.hibernate.format_sql=true -spring.jpa.show-sql=true -spring.jpa.hibernate.ddl-auto=create -spring.jpa.defer-datasource-initialization=true -spring.h2.console.enabled=true -logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE -oauth.google.redirect_uri=${GOOGLE_REDIRECT_URI} -oauth.google.client_id=${GOOGLE_CLIENT_ID} -oauth.google.client_secret=${GOOGLE_CLIENT_SECRET} -oauth.google.token_uri=${GOOGLE_TOKEN_URI} -security.jwt.token.secret-key=${JWT_SECRET_KEY} -security.jwt.token.expire-length=${JWT_EXPIRE_LENGTH} diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml new file mode 100644 index 00000000..9a2d4f3e --- /dev/null +++ b/backend/src/main/resources/application.yml @@ -0,0 +1,39 @@ +spring: + datasource: + url: jdbc:h2:~/dallog;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + username: sa + + jpa: + properties: + hibernate: + format_sql: true + show-sql: true + + hibernate: + ddl-auto: create + defer-datasource-initialization: true + + h2: + console: + enabled: true + +logging: + level: + org.hibernate.type.descriptor.sql.BasicBinder: TRACE + +oauth: + google: + client-id: ${GOOGLE_CLIENT_ID} + client-secret: ${GOOGLE_CLIENT_SECRET} + redirect-uri: ${GOOGLE_REDIRECT_URI} + oauth-end-point: https://accounts.google.com/o/oauth2/v2/auth + response-type: code + scopes: https://www.googleapis.com/auth/userinfo.profile, https://www.googleapis.com/auth/userinfo.email + token-uri: ${GOOGLE_TOKEN_URI} + grant-type: authorization_code + +security: + jwt: + token: + secret-key: ${JWT_SECRET_KEY} + expire-length: ${JWT_EXPIRE_LENGTH} diff --git a/backend/src/test/resources/application.properties b/backend/src/test/resources/application.properties deleted file mode 100644 index b3dada05..00000000 --- a/backend/src/test/resources/application.properties +++ /dev/null @@ -1,14 +0,0 @@ -spring.sql.init.mode=NEVER -spring.datasource.url=jdbc:h2:~/dallog;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE -spring.datasource.username=sa -spring.jpa.properties.hibernate.format_sql=true -spring.jpa.show-sql=true -spring.jpa.hibernate.ddl-auto=create -logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE -spring.main.allow-bean-definition-overriding=true -oauth.google.redirect_uri=http://localhost:3000 -oauth.google.client_id=hyeonic -oauth.google.client_secret=123 -oauth.google.token_uri=https://oauth2.googleapis.com/token -security.jwt.token.secret-key=fsmjgbdafmjgbasmfgadbsgmadfhgbfamjghbvmssdgsdfgdf -security.jwt.token.expire-length=3600 diff --git a/backend/src/test/resources/application.yml b/backend/src/test/resources/application.yml new file mode 100644 index 00000000..a03967c5 --- /dev/null +++ b/backend/src/test/resources/application.yml @@ -0,0 +1,41 @@ +spring: + main: + allow-bean-definition-overriding: true + + datasource: + url: jdbc:h2:~/dallog;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + username: sa + + sql: + init: + mode: NEVER + + jpa: + properties: + hibernate: + format_sql: true + show-sql: true + + hibernate: + ddl-auto: create + +logging: + level: + org.hibernate.type.descriptor.sql.BasicBinder: TRACE + +oauth: + google: + client-id: hyeonic + client-secret: 123 + redirect-uri: http://localhost:3000 + oauth-end-point: https://accounts.google.com/o/oauth2/v2/auth + response-type: code + scopes: https://www.googleapis.com/auth/userinfo.profile, https://www.googleapis.com/auth/userinfo.email + token-uri: https://oauth2.googleapis.com/token + grant-type: authorization_code + +security: + jwt: + token: + secret-key: fsmjgbdafmjgbasmfgadbsgmadfhgbfamjghbvmssdgsdfgdf + expire-length: 3600000 From 66ef24efe7dd52c41d2a7b3620d91be96b5bc21c Mon Sep 17 00:00:00 2001 From: koo Date: Mon, 25 Jul 2022 17:15:53 +0900 Subject: [PATCH 0305/1011] =?UTF-8?q?refactor:=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=EC=97=90=20=EB=8C=80=ED=95=9C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=EC=9D=84=20AuthService=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/auth/service/AuthService.java | 11 +++++++++++ .../AuthenticationPrincipalArgumentResolver.java | 11 ++++++----- .../dallog/auth/support/JwtTokenProvider.java | 7 +++---- .../dallog/auth/service/AuthServiceTest.java | 13 +++++++++++++ .../auth/support/JwtTokenProviderTest.java | 16 ++++++---------- .../controller/ScheduleControllerTest.java | 7 ++++--- 6 files changed, 43 insertions(+), 22 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index 0732a832..73da7092 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -2,6 +2,7 @@ import com.allog.dallog.auth.dto.OAuthMember; import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.auth.exception.InvalidTokenException; import com.allog.dallog.auth.support.JwtTokenProvider; import com.allog.dallog.auth.support.OAuthClient; import com.allog.dallog.auth.support.OAuthUri; @@ -55,4 +56,14 @@ private Member generateMemberBy(final OAuthMember oAuthMember) { return new Member(oAuthMember.getEmail(), oAuthMember.getProfileImageUrl(), oAuthMember.getDisplayName(), SocialType.GOOGLE); } + + public void validateToken(final String accessToken) { + if (accessToken == null || !jwtTokenProvider.validateToken(accessToken)) { + throw new InvalidTokenException("권한이 없습니다."); + } + } + + public String getPayload(final String accessToken) { + return jwtTokenProvider.getPayload(accessToken); + } } diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java index c974e498..5cf11280 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java @@ -1,6 +1,7 @@ package com.allog.dallog.auth.support; import com.allog.dallog.auth.dto.LoginMember; +import com.allog.dallog.auth.service.AuthService; import javax.servlet.http.HttpServletRequest; import org.springframework.core.MethodParameter; import org.springframework.stereotype.Component; @@ -12,10 +13,10 @@ @Component public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver { - private final JwtTokenProvider jwtTokenProvider; + private final AuthService authService; - public AuthenticationPrincipalArgumentResolver(final JwtTokenProvider jwtTokenProvider) { - this.jwtTokenProvider = jwtTokenProvider; + public AuthenticationPrincipalArgumentResolver(final AuthService authService) { + this.authService = authService; } @Override @@ -28,9 +29,9 @@ public Object resolveArgument(final MethodParameter parameter, final ModelAndVie final NativeWebRequest webRequest, final WebDataBinderFactory binderFactory) { HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); String accessToken = AuthorizationExtractor.extract(request); - jwtTokenProvider.validateToken(accessToken); + authService.validateToken(accessToken); - Long id = Long.parseLong(jwtTokenProvider.getPayload(accessToken)); + Long id = Long.parseLong(authService.getPayload(accessToken)); return new LoginMember(id); } diff --git a/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java b/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java index 72742118..77151b4d 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java @@ -1,6 +1,5 @@ package com.allog.dallog.auth.support; -import com.allog.dallog.auth.exception.InvalidTokenException; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.JwtException; @@ -46,16 +45,16 @@ public String getPayload(final String token) { .getSubject(); } - public void validateToken(final String token) { + public boolean validateToken(final String token) { try { Jws claims = Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token); - claims.getBody().getExpiration().before(new Date()); + return !claims.getBody().getExpiration().before(new Date()); } catch (JwtException | IllegalArgumentException e) { - throw new InvalidTokenException(); + return false; } } } diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index 4c290df5..2176265a 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -3,8 +3,10 @@ import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.EMAIL; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.auth.exception.InvalidTokenException; import com.allog.dallog.common.config.TestConfig; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; @@ -71,4 +73,15 @@ class AuthServiceTest { // then assertThat(actual).hasSize(1); } + + @DisplayName("validateToken 메서드는 유효하지 않은 토큰을 전달하면 예외를 던진다.") + @Test + void validateToken_메서드는_유효하지_않은_토큰을_전달하면_예외를_던진다() { + // given + String malformedToken = "malformed"; + + // when & then + assertThatThrownBy(() -> authService.validateToken(malformedToken)) + .isInstanceOf(InvalidTokenException.class); + } } diff --git a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java b/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java index bf2c5c99..57ff231c 100644 --- a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java @@ -1,9 +1,7 @@ package com.allog.dallog.auth.support; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.allog.dallog.auth.exception.InvalidTokenException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -41,26 +39,24 @@ class JwtTokenProviderTest { assertThat(actual).isEqualTo(expected); } - @DisplayName("validateToken 메서드는 만료된 토큰을 전달하면 예외를 던진다.") + @DisplayName("validateToken 메서드는 만료된 토큰을 전달하면 false를 반환한다.") @Test - void validateToken_메서드는_만료된_토큰을_전달하면_예외를_던진다() { + void validateToken_메서드는_만료된_토큰을_전달하면_false를_반환한다() { // given JwtTokenProvider expiredJwtTokenProvider = new JwtTokenProvider(JWT_SECRET_KEY, 0); String expiredToken = expiredJwtTokenProvider.createToken("payload"); // when & then - assertThatThrownBy(() -> jwtTokenProvider.validateToken(expiredToken)) - .isInstanceOf(InvalidTokenException.class); + assertThat(jwtTokenProvider.validateToken(expiredToken)).isFalse(); } - @DisplayName("validateToken 메서드는 유효하지 않은 토큰을 전달하면 예외를 던진다.") + @DisplayName("validateToken 메서드는 유효하지 않은 토큰을 전달하면 false를 반환한다.") @Test - void validateToken_메서드는_유효하지_않은_토큰을_전달하면_예외를_던진다() { + void validateToken_메서드는_유효하지_않은_토큰을_전달하면_false를_반환한다() { // given String malformedToken = "malformed"; // when & then - assertThatThrownBy(() -> jwtTokenProvider.validateToken(malformedToken)) - .isInstanceOf(InvalidTokenException.class); + assertThat(jwtTokenProvider.validateToken(malformedToken)).isFalse(); } } diff --git a/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java b/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java index 22f9e3b0..8c16b967 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java @@ -18,7 +18,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.allog.dallog.auth.support.JwtTokenProvider; +import com.allog.dallog.auth.service.AuthService; import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; import com.allog.dallog.schedule.dto.response.ScheduleResponse; import com.allog.dallog.schedule.service.ScheduleService; @@ -30,13 +30,11 @@ import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; @AutoConfigureRestDocs @WebMvcTest(ScheduleController.class) -@Import(JwtTokenProvider.class) class ScheduleControllerTest { @Autowired @@ -45,6 +43,9 @@ class ScheduleControllerTest { @Autowired private ObjectMapper ObjectMapper; + @MockBean + private AuthService authService; + @MockBean private ScheduleService scheduleService; From 4724a3dcefa97ef5b90e714fddc22c9c73ee6a8b Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 26 Jul 2022 09:34:44 +0900 Subject: [PATCH 0306/1011] =?UTF-8?q?refactor:=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EC=A1=B4=EC=9E=AC=20=EC=9C=A0=EB=AC=B4=EB=A5=BC=20=EA=B2=80?= =?UTF-8?q?=EC=82=AC=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=EC=9D=84=20Aut?= =?UTF-8?q?hService=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/auth/exception/NotFoundDataException.java | 12 ++++++++++++ .../com/allog/dallog/auth/service/AuthService.java | 7 +++++++ .../AuthenticationPrincipalArgumentResolver.java | 1 + .../allog/dallog/member/service/MemberService.java | 4 ++++ .../allog/dallog/auth/service/AuthServiceTest.java | 12 ++++++++++++ 5 files changed, 36 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/auth/exception/NotFoundDataException.java diff --git a/backend/src/main/java/com/allog/dallog/auth/exception/NotFoundDataException.java b/backend/src/main/java/com/allog/dallog/auth/exception/NotFoundDataException.java new file mode 100644 index 00000000..401027f6 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/exception/NotFoundDataException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.auth.exception; + +public class NotFoundDataException extends RuntimeException { + + public NotFoundDataException(final String message) { + super(message); + } + + public NotFoundDataException() { + this("존재하지 않는 데이터 입니다."); + } +} diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index 73da7092..14f85729 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -3,6 +3,7 @@ import com.allog.dallog.auth.dto.OAuthMember; import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.auth.exception.InvalidTokenException; +import com.allog.dallog.auth.exception.NotFoundDataException; import com.allog.dallog.auth.support.JwtTokenProvider; import com.allog.dallog.auth.support.OAuthClient; import com.allog.dallog.auth.support.OAuthUri; @@ -66,4 +67,10 @@ public void validateToken(final String accessToken) { public String getPayload(final String accessToken) { return jwtTokenProvider.getPayload(accessToken); } + + public void validateExistsId(final Long id) { + if (!memberService.existsById(id)) { + throw new NotFoundDataException("존재하지 않는 회원 입니다."); + } + } } diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java index 5cf11280..dc0484e1 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java @@ -32,6 +32,7 @@ public Object resolveArgument(final MethodParameter parameter, final ModelAndVie authService.validateToken(accessToken); Long id = Long.parseLong(authService.getPayload(accessToken)); + authService.validateExistsId(id); return new LoginMember(id); } diff --git a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java index 5849d7ba..855baf63 100644 --- a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java +++ b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java @@ -39,4 +39,8 @@ public Member getByEmail(final String email) { public boolean existsByEmail(final String email) { return memberRepository.existsByEmail(email); } + + public boolean existsById(final Long id) { + return memberRepository.existsById(id); + } } diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index 2176265a..6ac72313 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -7,6 +7,7 @@ import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.auth.exception.InvalidTokenException; +import com.allog.dallog.auth.exception.NotFoundDataException; import com.allog.dallog.common.config.TestConfig; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; @@ -84,4 +85,15 @@ class AuthServiceTest { assertThatThrownBy(() -> authService.validateToken(malformedToken)) .isInstanceOf(InvalidTokenException.class); } + + @DisplayName("회원이 존재하지 않으면 예외를 던진다.") + @Test + void 회원이_존재하지_않으면_예외를_던진다() { + // given + Long id = 0L; + + // when & then + assertThatThrownBy(() -> authService.validateExistsId(id)) + .isInstanceOf(NotFoundDataException.class); + } } From 34a30380ace906dde615e31a92dcb07ad8874bd2 Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 26 Jul 2022 09:44:57 +0900 Subject: [PATCH 0307/1011] =?UTF-8?q?refactor:=20Service=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=EC=9D=98=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20mem?= =?UTF-8?q?ber=20=EA=B2=80=EC=A6=9D=EB=A1=9C=EC=A7=81=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/auth/service/AuthService.java | 10 +++++----- .../AuthenticationPrincipalArgumentResolver.java | 2 +- .../allog/dallog/category/service/CategoryService.java | 4 +--- .../subscription/service/SubscriptionService.java | 10 +++------- .../com/allog/dallog/auth/service/AuthServiceTest.java | 2 +- 5 files changed, 11 insertions(+), 17 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index 14f85729..bfd11c1f 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -64,13 +64,13 @@ public void validateToken(final String accessToken) { } } - public String getPayload(final String accessToken) { - return jwtTokenProvider.getPayload(accessToken); - } - - public void validateExistsId(final Long id) { + public void validateExistsMember(final Long id) { if (!memberService.existsById(id)) { throw new NotFoundDataException("존재하지 않는 회원 입니다."); } } + + public String getPayload(final String accessToken) { + return jwtTokenProvider.getPayload(accessToken); + } } diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java index dc0484e1..918f6bd1 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java @@ -32,7 +32,7 @@ public Object resolveArgument(final MethodParameter parameter, final ModelAndVie authService.validateToken(accessToken); Long id = Long.parseLong(authService.getPayload(accessToken)); - authService.validateExistsId(id); + authService.validateExistsMember(id); return new LoginMember(id); } diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index 8f92c564..4d331d83 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -45,9 +45,7 @@ public CategoriesResponse findAll(final Pageable pageable) { } public CategoriesResponse findMine(final Long memberId, final Pageable pageable) { - Member member = memberService.getMember(memberId); - - List categoryResponses = categoryRepository.findSliceByMemberId(pageable, member.getId()) + List categoryResponses = categoryRepository.findSliceByMemberId(pageable, memberId) .getContent() .stream() .map(CategoryResponse::new) diff --git a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java b/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java index e5973dcc..35d54184 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java +++ b/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java @@ -43,9 +43,7 @@ public SubscriptionResponse save(final Long memberId, final Long categoryId, } public SubscriptionsResponse findByMemberId(final Long memberId) { - Member member = memberService.getMember(memberId); - - List subscriptions = subscriptionRepository.findByMemberId(member.getId()); + List subscriptions = subscriptionRepository.findByMemberId(memberId); List subscriptionResponses = subscriptions.stream() .map(SubscriptionResponse::new) @@ -62,12 +60,10 @@ public SubscriptionResponse findById(final Long id) { } public void deleteByIdAndMemberId(final Long id, final Long memberId) { - Member member = memberService.getMember(memberId); - - if (!subscriptionRepository.existsByIdAndMemberId(id, member.getId())) { + if (!subscriptionRepository.existsByIdAndMemberId(id, memberId)) { throw new NoPermissionException(); } - subscriptionRepository.deleteByIdAndMemberId(id, member.getId()); + subscriptionRepository.deleteByIdAndMemberId(id, memberId); } } diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index 6ac72313..1b1812fc 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -93,7 +93,7 @@ class AuthServiceTest { Long id = 0L; // when & then - assertThatThrownBy(() -> authService.validateExistsId(id)) + assertThatThrownBy(() -> authService.validateExistsMember(id)) .isInstanceOf(NotFoundDataException.class); } } From 159fabbdea185d09342120cd3314e869b0858cb1 Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 26 Jul 2022 11:23:48 +0900 Subject: [PATCH 0308/1011] =?UTF-8?q?refactor:=20JwtTokenProvider=EC=9D=98?= =?UTF-8?q?=20validateToken=20=EB=A9=94=EC=84=9C=EB=93=9C=EB=AA=85=20isVal?= =?UTF-8?q?idToken=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/auth/support/JwtTokenProvider.java | 6 ++++-- .../com/allog/dallog/auth/support/JwtTokenProviderTest.java | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java b/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java index 77151b4d..325778db 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java @@ -45,14 +45,16 @@ public String getPayload(final String token) { .getSubject(); } - public boolean validateToken(final String token) { + public boolean isValidToken(final String token) { try { Jws claims = Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token); - return !claims.getBody().getExpiration().before(new Date()); + return !claims.getBody() + .getExpiration() + .before(new Date()); } catch (JwtException | IllegalArgumentException e) { return false; } diff --git a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java b/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java index 57ff231c..802c0fa4 100644 --- a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java @@ -47,7 +47,7 @@ class JwtTokenProviderTest { String expiredToken = expiredJwtTokenProvider.createToken("payload"); // when & then - assertThat(jwtTokenProvider.validateToken(expiredToken)).isFalse(); + assertThat(jwtTokenProvider.isValidToken(expiredToken)).isFalse(); } @DisplayName("validateToken 메서드는 유효하지 않은 토큰을 전달하면 false를 반환한다.") @@ -57,6 +57,6 @@ class JwtTokenProviderTest { String malformedToken = "malformed"; // when & then - assertThat(jwtTokenProvider.validateToken(malformedToken)).isFalse(); + assertThat(jwtTokenProvider.isValidToken(malformedToken)).isFalse(); } } From 9bc47d9c01400795e46efd60710ba77753ae510f Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 26 Jul 2022 11:24:55 +0900 Subject: [PATCH 0309/1011] =?UTF-8?q?refactor:=20NotFoundDataException=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=EB=AA=85=EC=9D=84=20NotFoundMemberE?= =?UTF-8?q?xception=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/auth/exception/NotFoundDataException.java | 12 ------------ .../auth/exception/NotFoundMemberException.java | 12 ++++++++++++ .../com/allog/dallog/auth/service/AuthService.java | 6 +++--- .../allog/dallog/auth/service/AuthServiceTest.java | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) delete mode 100644 backend/src/main/java/com/allog/dallog/auth/exception/NotFoundDataException.java create mode 100644 backend/src/main/java/com/allog/dallog/auth/exception/NotFoundMemberException.java diff --git a/backend/src/main/java/com/allog/dallog/auth/exception/NotFoundDataException.java b/backend/src/main/java/com/allog/dallog/auth/exception/NotFoundDataException.java deleted file mode 100644 index 401027f6..00000000 --- a/backend/src/main/java/com/allog/dallog/auth/exception/NotFoundDataException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.allog.dallog.auth.exception; - -public class NotFoundDataException extends RuntimeException { - - public NotFoundDataException(final String message) { - super(message); - } - - public NotFoundDataException() { - this("존재하지 않는 데이터 입니다."); - } -} diff --git a/backend/src/main/java/com/allog/dallog/auth/exception/NotFoundMemberException.java b/backend/src/main/java/com/allog/dallog/auth/exception/NotFoundMemberException.java new file mode 100644 index 00000000..1805ed21 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/auth/exception/NotFoundMemberException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.auth.exception; + +public class NotFoundMemberException extends RuntimeException { + + public NotFoundMemberException(final String message) { + super(message); + } + + public NotFoundMemberException() { + this("존재하지 않는 데이터 입니다."); + } +} diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index bfd11c1f..17043487 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -3,7 +3,7 @@ import com.allog.dallog.auth.dto.OAuthMember; import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.auth.exception.InvalidTokenException; -import com.allog.dallog.auth.exception.NotFoundDataException; +import com.allog.dallog.auth.exception.NotFoundMemberException; import com.allog.dallog.auth.support.JwtTokenProvider; import com.allog.dallog.auth.support.OAuthClient; import com.allog.dallog.auth.support.OAuthUri; @@ -59,14 +59,14 @@ private Member generateMemberBy(final OAuthMember oAuthMember) { } public void validateToken(final String accessToken) { - if (accessToken == null || !jwtTokenProvider.validateToken(accessToken)) { + if (accessToken == null || !jwtTokenProvider.isValidToken(accessToken)) { throw new InvalidTokenException("권한이 없습니다."); } } public void validateExistsMember(final Long id) { if (!memberService.existsById(id)) { - throw new NotFoundDataException("존재하지 않는 회원 입니다."); + throw new NotFoundMemberException("존재하지 않는 회원 입니다."); } } diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index 1b1812fc..dc6280e4 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -7,7 +7,7 @@ import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.auth.exception.InvalidTokenException; -import com.allog.dallog.auth.exception.NotFoundDataException; +import com.allog.dallog.auth.exception.NotFoundMemberException; import com.allog.dallog.common.config.TestConfig; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; @@ -94,6 +94,6 @@ class AuthServiceTest { // when & then assertThatThrownBy(() -> authService.validateExistsMember(id)) - .isInstanceOf(NotFoundDataException.class); + .isInstanceOf(NotFoundMemberException.class); } } From 3271a1ef6b075a097d4bb0211101b925c62928ba Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 26 Jul 2022 11:25:23 +0900 Subject: [PATCH 0310/1011] =?UTF-8?q?refactor:=20CategoryService=EC=9D=98?= =?UTF-8?q?=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/CategoriesResponse.java | 12 ++++++++++-- .../category/service/CategoryService.java | 19 ++++++------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java index dc85e725..7fdddb35 100644 --- a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java +++ b/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java @@ -1,6 +1,8 @@ package com.allog.dallog.category.dto.response; +import com.allog.dallog.category.domain.Category; import java.util.List; +import java.util.stream.Collectors; public class CategoriesResponse { @@ -10,9 +12,15 @@ public class CategoriesResponse { public CategoriesResponse() { } - public CategoriesResponse(final int page, final List categories) { + public CategoriesResponse(final int page, final List categories) { this.page = page; - this.categories = categories; + this.categories = convertToResponses(categories); + } + + private List convertToResponses(final List categories) { + return categories.stream() + .map(CategoryResponse::new) + .collect(Collectors.toList()); } public int getPage() { diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java index 4d331d83..88738661 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java @@ -11,7 +11,6 @@ import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.service.MemberService; import java.util.List; -import java.util.stream.Collectors; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -36,21 +35,15 @@ public CategoryResponse save(final Long memberId, final CategoryCreateRequest re } public CategoriesResponse findAll(final Pageable pageable) { - List categoryResponses = categoryRepository.findSliceBy(pageable) - .getContent() - .stream() - .map(CategoryResponse::new) - .collect(Collectors.toList()); - return new CategoriesResponse(pageable.getPageNumber(), categoryResponses); + List categories = categoryRepository.findSliceBy(pageable).getContent(); + + return new CategoriesResponse(pageable.getPageNumber(), categories); } public CategoriesResponse findMine(final Long memberId, final Pageable pageable) { - List categoryResponses = categoryRepository.findSliceByMemberId(pageable, memberId) - .getContent() - .stream() - .map(CategoryResponse::new) - .collect(Collectors.toList()); - return new CategoriesResponse(pageable.getPageNumber(), categoryResponses); + List categories = categoryRepository.findSliceByMemberId(pageable, memberId).getContent(); + + return new CategoriesResponse(pageable.getPageNumber(), categories); } public CategoryResponse findById(final Long id) { From ad999a1730258226c062073a70a41aaf83595275 Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 26 Jul 2022 13:39:48 +0900 Subject: [PATCH 0311/1011] =?UTF-8?q?refactor:=20JwtTokenProvider.validate?= =?UTF-8?q?Token=EC=9D=98=20=EB=B0=98=ED=99=98=EA=B0=92=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/auth/service/AuthService.java | 8 +------- .../AuthenticationPrincipalArgumentResolver.java | 1 - .../dallog/auth/support/JwtTokenProvider.java | 7 ++++--- .../dallog/auth/service/AuthServiceTest.java | 11 ----------- .../auth/support/JwtTokenProviderTest.java | 16 ++++++++++------ 5 files changed, 15 insertions(+), 28 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index 17043487..55fbf77b 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -2,7 +2,6 @@ import com.allog.dallog.auth.dto.OAuthMember; import com.allog.dallog.auth.dto.TokenResponse; -import com.allog.dallog.auth.exception.InvalidTokenException; import com.allog.dallog.auth.exception.NotFoundMemberException; import com.allog.dallog.auth.support.JwtTokenProvider; import com.allog.dallog.auth.support.OAuthClient; @@ -58,12 +57,6 @@ private Member generateMemberBy(final OAuthMember oAuthMember) { SocialType.GOOGLE); } - public void validateToken(final String accessToken) { - if (accessToken == null || !jwtTokenProvider.isValidToken(accessToken)) { - throw new InvalidTokenException("권한이 없습니다."); - } - } - public void validateExistsMember(final Long id) { if (!memberService.existsById(id)) { throw new NotFoundMemberException("존재하지 않는 회원 입니다."); @@ -71,6 +64,7 @@ public void validateExistsMember(final Long id) { } public String getPayload(final String accessToken) { + jwtTokenProvider.validateToken(accessToken); return jwtTokenProvider.getPayload(accessToken); } } diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java index 918f6bd1..f16214b1 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java @@ -29,7 +29,6 @@ public Object resolveArgument(final MethodParameter parameter, final ModelAndVie final NativeWebRequest webRequest, final WebDataBinderFactory binderFactory) { HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); String accessToken = AuthorizationExtractor.extract(request); - authService.validateToken(accessToken); Long id = Long.parseLong(authService.getPayload(accessToken)); authService.validateExistsMember(id); diff --git a/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java b/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java index 325778db..df31dbb3 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java @@ -1,5 +1,6 @@ package com.allog.dallog.auth.support; +import com.allog.dallog.auth.exception.InvalidTokenException; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.JwtException; @@ -45,18 +46,18 @@ public String getPayload(final String token) { .getSubject(); } - public boolean isValidToken(final String token) { + public void validateToken(final String token) { try { Jws claims = Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token); - return !claims.getBody() + claims.getBody() .getExpiration() .before(new Date()); } catch (JwtException | IllegalArgumentException e) { - return false; + throw new InvalidTokenException("권한이 없습니다."); } } } diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index dc6280e4..11749755 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -75,17 +75,6 @@ class AuthServiceTest { assertThat(actual).hasSize(1); } - @DisplayName("validateToken 메서드는 유효하지 않은 토큰을 전달하면 예외를 던진다.") - @Test - void validateToken_메서드는_유효하지_않은_토큰을_전달하면_예외를_던진다() { - // given - String malformedToken = "malformed"; - - // when & then - assertThatThrownBy(() -> authService.validateToken(malformedToken)) - .isInstanceOf(InvalidTokenException.class); - } - @DisplayName("회원이 존재하지 않으면 예외를 던진다.") @Test void 회원이_존재하지_않으면_예외를_던진다() { diff --git a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java b/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java index 802c0fa4..bf2c5c99 100644 --- a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java @@ -1,7 +1,9 @@ package com.allog.dallog.auth.support; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import com.allog.dallog.auth.exception.InvalidTokenException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -39,24 +41,26 @@ class JwtTokenProviderTest { assertThat(actual).isEqualTo(expected); } - @DisplayName("validateToken 메서드는 만료된 토큰을 전달하면 false를 반환한다.") + @DisplayName("validateToken 메서드는 만료된 토큰을 전달하면 예외를 던진다.") @Test - void validateToken_메서드는_만료된_토큰을_전달하면_false를_반환한다() { + void validateToken_메서드는_만료된_토큰을_전달하면_예외를_던진다() { // given JwtTokenProvider expiredJwtTokenProvider = new JwtTokenProvider(JWT_SECRET_KEY, 0); String expiredToken = expiredJwtTokenProvider.createToken("payload"); // when & then - assertThat(jwtTokenProvider.isValidToken(expiredToken)).isFalse(); + assertThatThrownBy(() -> jwtTokenProvider.validateToken(expiredToken)) + .isInstanceOf(InvalidTokenException.class); } - @DisplayName("validateToken 메서드는 유효하지 않은 토큰을 전달하면 false를 반환한다.") + @DisplayName("validateToken 메서드는 유효하지 않은 토큰을 전달하면 예외를 던진다.") @Test - void validateToken_메서드는_유효하지_않은_토큰을_전달하면_false를_반환한다() { + void validateToken_메서드는_유효하지_않은_토큰을_전달하면_예외를_던진다() { // given String malformedToken = "malformed"; // when & then - assertThat(jwtTokenProvider.isValidToken(malformedToken)).isFalse(); + assertThatThrownBy(() -> jwtTokenProvider.validateToken(malformedToken)) + .isInstanceOf(InvalidTokenException.class); } } From 9450e4672184faaad80a273a8ae769d99c213de3 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 26 Jul 2022 13:01:10 +0900 Subject: [PATCH 0312/1011] =?UTF-8?q?fix:=20handler=20mocking=20api=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/mocks/handlers.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 7713931a..ff4cf5f8 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -14,7 +14,7 @@ import subscriptionApi from '@/api/subscription'; import { categoryDB, profileDB, scheduleDB, subscriptionDB } from './data'; const handlers = [ - rest.get(categoryApi.endpoint, (req, res, ctx) => { + rest.get(API_URL + categoryApi.endpoint, (req, res, ctx) => { const page = parseInt(req.url.searchParams.get('page') as string); const size = parseInt(req.url.searchParams.get('size') as string); const slicedCategories = categoryDB.categories.slice(page * size, page * size + size); @@ -28,7 +28,7 @@ const handlers = [ ); }), - rest.post>(categoryApi.endpoint, (req, res, ctx) => { + rest.post>(API_URL + categoryApi.endpoint, (req, res, ctx) => { categoryDB.categories.push({ ...req.body, id: categoryDB.categories.length + 1, @@ -39,21 +39,21 @@ const handlers = [ return res(ctx.status(201)); }), - rest.get(profileApi.endpoint, (req, res, ctx) => { + rest.get(API_URL + profileApi.endpoint, (req, res, ctx) => { return res(ctx.status(200), ctx.json(profileDB)); }), - rest.get(scheduleApi.endpoint, (req, res, ctx) => { + rest.get(API_URL + scheduleApi.endpoint, (req, res, ctx) => { return res(ctx.status(200), ctx.json({ schedules: scheduleDB })); }), - rest.post>(scheduleApi.endpoint, (req, res, ctx) => { + rest.post>(API_URL + scheduleApi.endpoint, (req, res, ctx) => { scheduleDB.push({ id: scheduleDB.length + 1, ...req.body }); return res(ctx.status(201)); }), - rest.get(subscriptionApi.endpoint.get, (req, res, ctx) => { + rest.get(API_URL + subscriptionApi.endpoint.get, (req, res, ctx) => { return res(ctx.status(200), ctx.json(subscriptionDB)); }), From 1f591115959168074179116d3997c409cb8e93fa Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 26 Jul 2022 14:58:47 +0900 Subject: [PATCH 0313/1011] =?UTF-8?q?style:=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=B0=B0=EA=B2=BD?= =?UTF-8?q?=EC=83=89=20=ED=88=AC=EA=B2=BD=ED=95=98=EA=B2=8C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/@common/Button/Button.styles.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/components/@common/Button/Button.styles.ts b/frontend/src/components/@common/Button/Button.styles.ts index 72b3af71..34f68990 100644 --- a/frontend/src/components/@common/Button/Button.styles.ts +++ b/frontend/src/components/@common/Button/Button.styles.ts @@ -3,6 +3,8 @@ import { css } from '@emotion/react'; const button = css` border: none; + background: transparent; + font-family: inherit; text-align: center; From cef44234642490e81d4a738424c0f36756d8f80d Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 26 Jul 2022 14:59:50 +0900 Subject: [PATCH 0314/1011] =?UTF-8?q?style:=20=EB=8B=AC=EB=A0=A5=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../@common/PageLayout/PageLayout.styles.ts | 2 +- .../components/Calendar/Calendar.styles.ts | 88 ++++++++++++++----- frontend/src/components/Calendar/Calendar.tsx | 13 +-- .../CalendarDate/CalendarDate.style.ts | 27 +++--- .../components/CalendarDate/CalendarDate.tsx | 8 +- .../src/components/NavBar/NavBar.styles.ts | 19 +++- frontend/src/components/NavBar/NavBar.tsx | 4 +- .../ScheduleAddButton.styles.ts | 2 +- .../pages/CalendarPage/CalendarPage.styles.ts | 3 +- .../pages/CategoryPage/CategoryPage.styles.ts | 1 + frontend/src/pages/MyPage/MyPage.styles.ts | 1 + frontend/src/styles/theme.ts | 10 +++ 12 files changed, 124 insertions(+), 54 deletions(-) diff --git a/frontend/src/components/@common/PageLayout/PageLayout.styles.ts b/frontend/src/components/@common/PageLayout/PageLayout.styles.ts index 6e304a55..fc14ac18 100644 --- a/frontend/src/components/@common/PageLayout/PageLayout.styles.ts +++ b/frontend/src/components/@common/PageLayout/PageLayout.styles.ts @@ -1,7 +1,7 @@ import { css } from '@emotion/react'; const pageLayout = (isSideBarOpen: boolean) => css` - overflow-y: scroll; + overflow-y: auto; height: calc(100vh - 16rem); margin-top: 16rem; diff --git a/frontend/src/components/Calendar/Calendar.styles.ts b/frontend/src/components/Calendar/Calendar.styles.ts index 9a78b88c..740ff963 100644 --- a/frontend/src/components/Calendar/Calendar.styles.ts +++ b/frontend/src/components/Calendar/Calendar.styles.ts @@ -2,41 +2,75 @@ import { css, Theme } from '@emotion/react'; import { DAYS } from '@/constants'; -const calendar = css` - margin: 3rem; -`; - -const calendarHeader = ({ flex }: Theme) => css` +const calendarHeader = ({ colors, flex }: Theme) => css` ${flex.row} - justify-content:space-between; + justify-content: space-between; width: 100%; - padding: 3rem; + padding: 3rem 2rem; - font-size: 6rem; - font-weight: 700; + font-size: 5rem; + font-weight: 500; + color: ${colors.GRAY_700}; `; const monthPicker = ({ flex }: Theme) => css` ${flex.row} - justify-content:space-around; + justify-content: space-around; align-items: center; +`; + +const todayButton = ({ colors }: Theme) => css` + width: 12rem; + height: 8rem; - width: 40rem; + padding: auto 0; + + font-size: 4rem; + line-height: 4rem; + font-weight: 500; + color: ${colors.GRAY_700}; `; -const navButton = css` - background: transparent; +const navButton = ({ colors }: Theme) => css` + position: relative; - font-size: 5rem; - line-height: 3rem; - font-weight: 700; + width: 8rem; + height: 8rem; + padding: 0; + + font-size: 4rem; + line-height: 4rem; + color: ${colors.GRAY_600}; &:hover { - transform: scale(1.1); + border-radius: 50%; + background: ${colors.GRAY_300}; } + + &:hover span { + visibility: visible; + } +`; + +const navButtonTitle = ({ colors }: Theme) => css` + visibility: hidden; + position: absolute; + + top: 120%; + left: 50%; + transform: translateX(-50%); + + padding: 2rem 3rem; + + background: ${colors.GRAY_700}ee; + + font-size: 3rem; + font-weight: normal; + color: ${colors.WHITE}; + white-space: nowrap; `; const navBarGrid = css` @@ -51,15 +85,23 @@ const calendarGrid = (rowNum: number) => css` `; const dayBar = ({ colors }: Theme, day: string) => css` - padding: 3rem; + padding: 2rem 3rem; border-top: 1px solid ${colors.GRAY_300}; border-right: 1px solid ${colors.GRAY_300}; + border-left: ${day === DAYS[0] && `1px solid ${colors.GRAY_300}`}; - background: ${day === DAYS[0] || day === DAYS[6] ? colors.GRAY_100 : colors.WHITE}; - - font-size: 3.5rem; - font-weight: 700; + font-size: 3rem; text-align: right; + color: ${day === DAYS[0] && colors.RED_400}; `; -export { calendar, calendarHeader, navBarGrid, calendarGrid, dayBar, monthPicker, navButton }; +export { + calendarGrid, + calendarHeader, + dayBar, + monthPicker, + navBarGrid, + navButton, + navButtonTitle, + todayButton, +}; diff --git a/frontend/src/components/Calendar/Calendar.tsx b/frontend/src/components/Calendar/Calendar.tsx index c4316216..ebed520c 100644 --- a/frontend/src/components/Calendar/Calendar.tsx +++ b/frontend/src/components/Calendar/Calendar.tsx @@ -17,13 +17,14 @@ import { AiOutlineLeft, AiOutlineRight } from 'react-icons/ai'; import Button from '../@common/Button/Button'; import { - calendar, calendarGrid, calendarHeader, dayBar, monthPicker, navBarGrid, navButton, + navButtonTitle, + todayButton, } from './Calendar.styles'; interface CalendarProps { @@ -71,7 +72,7 @@ function Calendar({ current, setCurrent }: CalendarProps) { const rowNum = Math.ceil(calendarMonth.length / 7); return ( -
+ <>
{current.year}년 {current.month}월 @@ -79,12 +80,14 @@ function Calendar({ current, setCurrent }: CalendarProps) {
-
@@ -105,7 +108,7 @@ function Calendar({ current, setCurrent }: CalendarProps) { ); })}
-
+ ); } diff --git a/frontend/src/components/CalendarDate/CalendarDate.style.ts b/frontend/src/components/CalendarDate/CalendarDate.style.ts index 5fe9c03d..8a695ea8 100644 --- a/frontend/src/components/CalendarDate/CalendarDate.style.ts +++ b/frontend/src/components/CalendarDate/CalendarDate.style.ts @@ -1,29 +1,32 @@ import { css, Theme } from '@emotion/react'; -const calendarDate = ({ colors }: Theme, day: number, isThisMonth: boolean) => css` - background: ${day === 0 || day === 6 ? colors.GRAY_100 : colors.WHITE}; - - opacity: ${isThisMonth || 0.5}; -`; - -const dateBorder = ({ colors }: Theme) => css` +const dateBorder = ({ colors }: Theme, day: number) => css` position: relative; height: 100%; padding: 1rem; - border-top: 1px solid ${colors.GRAY_300}; + border-bottom: 1px solid ${colors.GRAY_300}; border-right: 1px solid ${colors.GRAY_300}; + border-left: ${day === 0 && `1px solid ${colors.GRAY_300}`}; `; -const dateText = css` +const dateText = ({ colors }: Theme, day: number, isThisMonth: boolean) => css` position: absolute; top: 2rem; right: 2rem; padding: 1rem; - font-size: 4rem; - font-weight: 700; + font-size: 3rem; + font-weight: 500; + + color: ${day === 0 + ? isThisMonth + ? colors.RED_400 + : `${colors.RED_400}80` + : isThisMonth + ? colors.GRAY_700 + : `${colors.GRAY_700}80`}; `; -export { calendarDate, dateText, dateBorder }; +export { dateText, dateBorder }; diff --git a/frontend/src/components/CalendarDate/CalendarDate.tsx b/frontend/src/components/CalendarDate/CalendarDate.tsx index f2907592..48aa79e7 100644 --- a/frontend/src/components/CalendarDate/CalendarDate.tsx +++ b/frontend/src/components/CalendarDate/CalendarDate.tsx @@ -2,7 +2,7 @@ import { useTheme } from '@emotion/react'; import { CalendarType } from '@/@types/calendar'; -import { calendarDate, dateBorder, dateText } from './CalendarDate.style'; +import { dateBorder, dateText } from './CalendarDate.style'; interface CalendarDateProps { dateInfo: CalendarType; @@ -13,10 +13,8 @@ function CalendarDate({ dateInfo, isThisMonth }: CalendarDateProps) { const theme = useTheme(); return ( -
-
- {dateInfo.date} -
+
+ {dateInfo.date}
); } diff --git a/frontend/src/components/NavBar/NavBar.styles.ts b/frontend/src/components/NavBar/NavBar.styles.ts index 661acca1..ad20eab8 100644 --- a/frontend/src/components/NavBar/NavBar.styles.ts +++ b/frontend/src/components/NavBar/NavBar.styles.ts @@ -24,7 +24,7 @@ const menus = ({ flex }: Theme) => css` gap: 3rem; `; -const menu = ({ colors, flex }: Theme) => css` +const logo = ({ colors, flex }: Theme) => css` ${flex.row} position: relative; @@ -34,6 +34,19 @@ const menu = ({ colors, flex }: Theme) => css` font-size: 5rem; font-weight: bold; color: ${colors.GRAY_700}; +`; + +const menu = ({ colors, flex }: Theme) => css` + ${logo({ colors, flex })} + + width: 11rem; + height: 11rem; + + &:hover { + border-radius: 50%; + + background: ${colors.GRAY_300}; + } &:hover span { visibility: visible; @@ -59,7 +72,7 @@ const menuTitle = ({ colors }: Theme) => css` padding: 2rem 3rem; - background: ${colors.GRAY_700}; + background: ${colors.GRAY_700}ee; font-size: 3rem; font-weight: normal; @@ -67,4 +80,4 @@ const menuTitle = ({ colors }: Theme) => css` white-space: nowrap; `; -export { loginButton, menu, menus, menuTitle, navBar }; +export { loginButton, logo, menu, menus, menuTitle, navBar }; diff --git a/frontend/src/components/NavBar/NavBar.tsx b/frontend/src/components/NavBar/NavBar.tsx index fbc54692..3c487a44 100644 --- a/frontend/src/components/NavBar/NavBar.tsx +++ b/frontend/src/components/NavBar/NavBar.tsx @@ -14,7 +14,7 @@ import { FaUserCircle } from 'react-icons/fa'; import { FiCalendar } from 'react-icons/fi'; import { HiChevronDoubleLeft, HiMenu } from 'react-icons/hi'; -import { loginButton, menu, menus, menuTitle, navBar } from './NavBar.styles'; +import { loginButton, logo, menu, menus, menuTitle, navBar } from './NavBar.styles'; interface NavBarProps { openLoginModal: () => void; @@ -49,7 +49,7 @@ function NavBar({ openLoginModal }: NavBarProps) { {isSideBarOpen ? : } 메뉴 -
diff --git a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts index fc3526ca..c4a1f16c 100644 --- a/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts +++ b/frontend/src/components/ScheduleAddButton/ScheduleAddButton.styles.ts @@ -12,7 +12,7 @@ const scheduleAddButton = ({ colors }: Theme) => css` background: ${colors.YELLOW_500}; font-size: 7rem; - line-height: 11rem; + line-height: 7rem; font-weight: 700; color: ${colors.WHITE}; `; diff --git a/frontend/src/pages/CalendarPage/CalendarPage.styles.ts b/frontend/src/pages/CalendarPage/CalendarPage.styles.ts index d52c7b07..421b0591 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.styles.ts +++ b/frontend/src/pages/CalendarPage/CalendarPage.styles.ts @@ -1,8 +1,7 @@ import { css } from '@emotion/react'; const calendarPage = css` - margin-top: 16rem; - padding: 2rem; + padding: 0 5rem; `; export { calendarPage }; diff --git a/frontend/src/pages/CategoryPage/CategoryPage.styles.ts b/frontend/src/pages/CategoryPage/CategoryPage.styles.ts index 157494a9..e148eef3 100644 --- a/frontend/src/pages/CategoryPage/CategoryPage.styles.ts +++ b/frontend/src/pages/CategoryPage/CategoryPage.styles.ts @@ -5,6 +5,7 @@ const categoryPage = ({ flex }: Theme) => css` align-items: center; + height: 100%; padding: 5rem; `; diff --git a/frontend/src/pages/MyPage/MyPage.styles.ts b/frontend/src/pages/MyPage/MyPage.styles.ts index ecc8d5fb..541f58ba 100644 --- a/frontend/src/pages/MyPage/MyPage.styles.ts +++ b/frontend/src/pages/MyPage/MyPage.styles.ts @@ -2,6 +2,7 @@ import { css, Theme } from '@emotion/react'; const myPage = ({ colors }: Theme) => css` width: 100%; + height: 100%; padding: 2rem; background: ${colors.GRAY_100}; diff --git a/frontend/src/styles/theme.ts b/frontend/src/styles/theme.ts index 602524a0..091b977a 100644 --- a/frontend/src/styles/theme.ts +++ b/frontend/src/styles/theme.ts @@ -16,6 +16,16 @@ const colors = { GRAY_800: '#343a40', GRAY_900: '#212529', BLACK: '#000000', + RED_000: '#fff5f5', + RED_100: '#ffe3e3', + RED_200: '#ffc9c9', + RED_300: '#ffa8a8', + RED_400: '#ff8787', + RED_500: '#ff6b6b', + RED_600: '#fa5252', + RED_700: '#f03e3e', + RED_800: '#e03131', + RED_900: '#c92a2a', }; const flex = { From c713395c27c4ac68feb77bcff416c15315ed134b Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 26 Jul 2022 15:38:05 +0900 Subject: [PATCH 0315/1011] =?UTF-8?q?refactor:=20=EB=8B=AC=EB=A0=A5=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/Calendar/Calendar.styles.ts | 31 +++++++ frontend/src/components/Calendar/Calendar.tsx | 86 ++++++++----------- .../CalendarDate/CalendarDate.stories.tsx | 20 ----- .../CalendarDate/CalendarDate.style.ts | 32 ------- .../components/CalendarDate/CalendarDate.tsx | 22 ----- .../ScheduleAddModal/ScheduleAddModal.tsx | 12 +-- frontend/src/hooks/useCalendar.ts | 52 +++++++++++ .../src/pages/CalendarPage/CalendarPage.tsx | 42 +-------- 8 files changed, 125 insertions(+), 172 deletions(-) delete mode 100644 frontend/src/components/CalendarDate/CalendarDate.stories.tsx delete mode 100644 frontend/src/components/CalendarDate/CalendarDate.style.ts delete mode 100644 frontend/src/components/CalendarDate/CalendarDate.tsx create mode 100644 frontend/src/hooks/useCalendar.ts diff --git a/frontend/src/components/Calendar/Calendar.styles.ts b/frontend/src/components/Calendar/Calendar.styles.ts index 740ff963..21623425 100644 --- a/frontend/src/components/Calendar/Calendar.styles.ts +++ b/frontend/src/components/Calendar/Calendar.styles.ts @@ -95,10 +95,41 @@ const dayBar = ({ colors }: Theme, day: string) => css` color: ${day === DAYS[0] && colors.RED_400}; `; +const dateBorder = ({ colors }: Theme, day: number) => css` + position: relative; + + height: 100%; + padding: 1rem; + border-bottom: 1px solid ${colors.GRAY_300}; + border-right: 1px solid ${colors.GRAY_300}; + border-left: ${day === 0 && `1px solid ${colors.GRAY_300}`}; +`; + +const dateText = ({ colors }: Theme, day: number, isThisMonth: boolean) => css` + position: absolute; + top: 2rem; + right: 2rem; + + padding: 1rem; + + font-size: 3rem; + font-weight: 500; + + color: ${day === 0 + ? isThisMonth + ? colors.RED_400 + : `${colors.RED_400}80` + : isThisMonth + ? colors.GRAY_700 + : `${colors.GRAY_700}80`}; +`; + export { calendarGrid, calendarHeader, dayBar, + dateBorder, + dateText, monthPicker, navBarGrid, navButton, diff --git a/frontend/src/components/Calendar/Calendar.tsx b/frontend/src/components/Calendar/Calendar.tsx index ebed520c..fb83f2e8 100644 --- a/frontend/src/components/Calendar/Calendar.tsx +++ b/frontend/src/components/Calendar/Calendar.tsx @@ -1,24 +1,25 @@ import { useTheme } from '@emotion/react'; -import { useState } from 'react'; +import { AxiosError, AxiosResponse } from 'axios'; +import { useEffect } from 'react'; +import { useQuery } from 'react-query'; -import CalendarDate from '@/components/CalendarDate/CalendarDate'; +import useCalendar from '@/hooks/useCalendar'; -import { DAYS } from '@/constants'; +import { Schedule } from '@/@types'; -import { - getBeforeYearMonth, - getCalendarMonth, - getNextYearMonth, - getThisMonth, - getThisYear, -} from '@/utils/date'; +import Button from '@/components/@common/Button/Button'; + +import { CACHE_KEY, DAYS } from '@/constants'; + +import scheduleApi from '@/api/schedule'; import { AiOutlineLeft, AiOutlineRight } from 'react-icons/ai'; -import Button from '../@common/Button/Button'; import { calendarGrid, calendarHeader, + dateBorder, + dateText, dayBar, monthPicker, navBarGrid, @@ -27,49 +28,29 @@ import { todayButton, } from './Calendar.styles'; -interface CalendarProps { - current: { - year: number; - month: number; - }; - setCurrent: React.Dispatch< - React.SetStateAction<{ - year: number; - month: number; - }> - >; -} - -function Calendar({ current, setCurrent }: CalendarProps) { +function Calendar() { const theme = useTheme(); - const [calendarMonth, setCalendarMonth] = useState( - getCalendarMonth(getThisYear(), getThisMonth()) - ); + const { calendarMonth, current, moveToBeforeMonth, moveToToday, moveToNextMonth } = useCalendar(); - const handleClickBeforeMonthButton = () => { - const { year, month } = getBeforeYearMonth(current.year, current.month); + const { isLoading, error, data, refetch } = useQuery< + AxiosResponse<{ schedules: Schedule[] }>, + AxiosError + >(CACHE_KEY.SCHEDULES, () => scheduleApi.get(current.year, current.month)); - setCurrent({ year, month }); - setCalendarMonth(getCalendarMonth(year, month)); - }; - - const handleClickTodayButton = () => { - const year = getThisYear(); - const month = getThisMonth(); + const rowNum = Math.ceil(calendarMonth.length / 7); - setCurrent({ year, month }); - setCalendarMonth(getCalendarMonth(year, month)); - }; + useEffect(() => { + refetch(); + }, [current]); - const handleClickNextMonthButton = () => { - const { year, month } = getNextYearMonth(current.year, current.month); + if (isLoading || data === undefined) { + return <>Loading; + } - setCurrent({ year, month }); - setCalendarMonth(getCalendarMonth(year, month)); - }; - - const rowNum = Math.ceil(calendarMonth.length / 7); + if (error) { + return <>Error; + } return ( <> @@ -78,20 +59,19 @@ function Calendar({ current, setCurrent }: CalendarProps) { {current.year}년 {current.month}월
- - -
-
{DAYS.map((day) => ( @@ -104,7 +84,9 @@ function Calendar({ current, setCurrent }: CalendarProps) { const key = `${info.year}${info.month}${info.date}${info.day}`; return ( - +
+ {info.date} +
); })}
diff --git a/frontend/src/components/CalendarDate/CalendarDate.stories.tsx b/frontend/src/components/CalendarDate/CalendarDate.stories.tsx deleted file mode 100644 index 08487c3d..00000000 --- a/frontend/src/components/CalendarDate/CalendarDate.stories.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; - -import CalendarDate from './CalendarDate'; - -export default { - title: 'Components/CalendarDate', - component: CalendarDate, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ; - -export const Primary = Template.bind({}); -Primary.args = { - dateInfo: { - year: 2022, - month: 7, - date: 22, - day: 0, - }, -}; diff --git a/frontend/src/components/CalendarDate/CalendarDate.style.ts b/frontend/src/components/CalendarDate/CalendarDate.style.ts deleted file mode 100644 index 8a695ea8..00000000 --- a/frontend/src/components/CalendarDate/CalendarDate.style.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -const dateBorder = ({ colors }: Theme, day: number) => css` - position: relative; - - height: 100%; - padding: 1rem; - border-bottom: 1px solid ${colors.GRAY_300}; - border-right: 1px solid ${colors.GRAY_300}; - border-left: ${day === 0 && `1px solid ${colors.GRAY_300}`}; -`; - -const dateText = ({ colors }: Theme, day: number, isThisMonth: boolean) => css` - position: absolute; - top: 2rem; - right: 2rem; - - padding: 1rem; - - font-size: 3rem; - font-weight: 500; - - color: ${day === 0 - ? isThisMonth - ? colors.RED_400 - : `${colors.RED_400}80` - : isThisMonth - ? colors.GRAY_700 - : `${colors.GRAY_700}80`}; -`; - -export { dateText, dateBorder }; diff --git a/frontend/src/components/CalendarDate/CalendarDate.tsx b/frontend/src/components/CalendarDate/CalendarDate.tsx deleted file mode 100644 index 48aa79e7..00000000 --- a/frontend/src/components/CalendarDate/CalendarDate.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { useTheme } from '@emotion/react'; - -import { CalendarType } from '@/@types/calendar'; - -import { dateBorder, dateText } from './CalendarDate.style'; - -interface CalendarDateProps { - dateInfo: CalendarType; - isThisMonth: boolean; -} - -function CalendarDate({ dateInfo, isThisMonth }: CalendarDateProps) { - const theme = useTheme(); - - return ( -
- {dateInfo.date} -
- ); -} - -export default CalendarDate; diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index df1ffe0c..579679f2 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -1,10 +1,12 @@ import { useTheme } from '@emotion/react'; import { AxiosError, AxiosResponse } from 'axios'; import { useRef, useState } from 'react'; -import { QueryObserverResult, RefetchOptions, RefetchQueryFilters, useMutation } from 'react-query'; +import { useMutation, useQueryClient } from 'react-query'; import { Schedule } from '@/@types'; +import { CACHE_KEY } from '@/constants'; + import { createPostBody } from '@/utils'; import { getDate, getDateTime } from '@/utils/date'; @@ -25,15 +27,13 @@ import { interface ScheduleAddModalProps { closeModal: () => void; - refetch: ( - options?: (RefetchOptions & RefetchQueryFilters) | undefined - ) => Promise, AxiosError>>; } -function ScheduleAddModal({ closeModal, refetch }: ScheduleAddModalProps) { +function ScheduleAddModal({ closeModal }: ScheduleAddModalProps) { const [isAllDay, setAllDay] = useState(true); const theme = useTheme(); + const queryClient = useQueryClient(); const { isLoading, error, @@ -77,7 +77,7 @@ function ScheduleAddModal({ closeModal, refetch }: ScheduleAddModalProps) { }; const onSuccessPostSchedule = () => { - refetch(); + queryClient.invalidateQueries(CACHE_KEY.SCHEDULES); closeModal(); }; diff --git a/frontend/src/hooks/useCalendar.ts b/frontend/src/hooks/useCalendar.ts new file mode 100644 index 00000000..1ca3053b --- /dev/null +++ b/frontend/src/hooks/useCalendar.ts @@ -0,0 +1,52 @@ +import { useState } from 'react'; + +import { + getBeforeYearMonth, + getCalendarMonth, + getNextYearMonth, + getThisMonth, + getThisYear, +} from '@/utils/date'; + +function useCalendar() { + const [current, setCurrent] = useState({ + year: getThisYear(), + month: getThisMonth(), + }); + + const [calendarMonth, setCalendarMonth] = useState( + getCalendarMonth(getThisYear(), getThisMonth()) + ); + + const moveToBeforeMonth = () => { + const { year, month } = getBeforeYearMonth(current.year, current.month); + + setCurrent({ year, month }); + setCalendarMonth(getCalendarMonth(year, month)); + }; + + const moveToToday = () => { + const year = getThisYear(); + const month = getThisMonth(); + + setCurrent({ year, month }); + setCalendarMonth(getCalendarMonth(year, month)); + }; + + const moveToNextMonth = () => { + const { year, month } = getNextYearMonth(current.year, current.month); + + setCurrent({ year, month }); + setCalendarMonth(getCalendarMonth(year, month)); + }; + + return { + calendarMonth, + current, + moveToBeforeMonth, + moveToNextMonth, + moveToToday, + }; +} + +export default useCalendar; diff --git a/frontend/src/pages/CalendarPage/CalendarPage.tsx b/frontend/src/pages/CalendarPage/CalendarPage.tsx index 8aa3ced0..b6b70245 100644 --- a/frontend/src/pages/CalendarPage/CalendarPage.tsx +++ b/frontend/src/pages/CalendarPage/CalendarPage.tsx @@ -1,60 +1,22 @@ -import { AxiosError, AxiosResponse } from 'axios'; -import { useEffect, useState } from 'react'; -import { useQuery } from 'react-query'; - import useToggle from '@/hooks/useToggle'; -import { Schedule } from '@/@types'; - import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; import PageLayout from '@/components/@common/PageLayout/PageLayout'; import Calendar from '@/components/Calendar/Calendar'; import ScheduleAddButton from '@/components/ScheduleAddButton/ScheduleAddButton'; import ScheduleAddModal from '@/components/ScheduleAddModal/ScheduleAddModal'; -import { CACHE_KEY } from '@/constants'; - -import { getThisMonth, getThisYear } from '@/utils/date'; - -import scheduleApi from '@/api/schedule'; - import { calendarPage } from './CalendarPage.styles'; function CalendarPage() { - const [current, setCurrent] = useState({ - year: getThisYear(), - month: getThisMonth(), - }); - - const { - isLoading, - error, - data: schedulesGetResponse, - refetch: refetchSchedules, - } = useQuery, AxiosError>(CACHE_KEY.SCHEDULES, () => - scheduleApi.get(current.year, current.month) - ); - const { state: isCalendarAddModalOpen, toggleState: toggleCalendarAddModalOpen } = useToggle(); - useEffect(() => { - refetchSchedules(); - }, [current]); - - if (isLoading || schedulesGetResponse === undefined) { - return <>Loading; - } - - if (error) { - return <>Error; - } - return (
- + - +
From 1f8d2610517a68884cfc49d9790b8c6fc5a53563 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Tue, 26 Jul 2022 14:57:45 +0900 Subject: [PATCH 0316/1011] =?UTF-8?q?test(Auth):=20Auth=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=94=BD=EC=8A=A4=EC=B2=98=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/acceptance/AuthAcceptanceTest.java | 8 ++++---- .../acceptance/CategoryAcceptanceTest.java | 14 +++++++------- .../acceptance/MemberAcceptanceTest.java | 18 +++++++++--------- .../acceptance/SubscriptionAcceptanceTest.java | 10 +++++----- .../dallog/auth/service/AuthServiceTest.java | 15 +++++++-------- .../auth/support/JwtTokenProviderTest.java | 15 ++++++--------- .../dallog/common/fixtures/AuthFixtures.java | 12 ++++++++++++ .../common/fixtures/OAuthMemberFixtures.java | 16 ---------------- .../oauth/client/StubOAuthClient.java | 6 ++++-- 9 files changed, 54 insertions(+), 60 deletions(-) create mode 100644 backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java delete mode 100644 backend/src/test/java/com/allog/dallog/common/fixtures/OAuthMemberFixtures.java diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java index 2d022729..34bea5f5 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java @@ -3,8 +3,8 @@ import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.OAuth_인증_URI를_생성한다; import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.자체_토큰을_생성한다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; -import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; -import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; +import static com.allog.dallog.common.fixtures.AuthFixtures.GOOGLE_PROVIDER; +import static com.allog.dallog.common.fixtures.AuthFixtures.인증_코드; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @@ -25,7 +25,7 @@ public class AuthAcceptanceTest extends AcceptanceTest { @Test void 구글_OAuth_인증_URI를_생성하여_반환한다() { // given & when - ExtractableResponse response = OAuth_인증_URI를_생성한다(OAUTH_PROVIDER); + ExtractableResponse response = OAuth_인증_URI를_생성한다(GOOGLE_PROVIDER); OAuthUriResponse oAuthUriResponse = response.as(OAuthUriResponse.class); // then @@ -39,7 +39,7 @@ public class AuthAcceptanceTest extends AcceptanceTest { @Test void 최초_사용자거나_기존에_존재하는_회원인_경우_200을_발급한다() { // given & when - ExtractableResponse response = 자체_토큰을_생성한다(OAUTH_PROVIDER, CODE); + ExtractableResponse response = 자체_토큰을_생성한다(GOOGLE_PROVIDER, 인증_코드); TokenResponse tokenResponse = response.as(TokenResponse.class); // then diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index b277ad0b..cb4e8413 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -10,12 +10,12 @@ import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_204가_반환된다; +import static com.allog.dallog.common.fixtures.AuthFixtures.GOOGLE_PROVIDER; +import static com.allog.dallog.common.fixtures.AuthFixtures.인증_코드; import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; import static com.allog.dallog.common.fixtures.CategoryFixtures.MODIFIED_CATEGORY_NAME; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_1; import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE_2; -import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; -import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @@ -33,7 +33,7 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @Test void 정상적인_카테고리_정보를_등록하면_상태코드_201을_반환한다() { // given - String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(OAUTH_PROVIDER, CODE); + String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); // when ExtractableResponse response = 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); @@ -46,7 +46,7 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @Test void 카테고리를_등록하고_페이징을_통해_나누어_조회한다() { // given - String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(OAUTH_PROVIDER, CODE); + String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); @@ -68,7 +68,7 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @Test void 카테고리를_등록하고_내가_등록한_카테고리를_페이징을_통해_나누어_조회한다() { // given - String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(OAUTH_PROVIDER, CODE); + String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); @@ -91,7 +91,7 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @Test void 카테고리를_등록하고_내가_등록한_카테고리를_수정하면_상태코드_204를_반환한다() { // given - String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(OAUTH_PROVIDER, CODE); + String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); CategoryResponse savedCategory = 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME) .as(CategoryResponse.class); @@ -111,7 +111,7 @@ public class CategoryAcceptanceTest extends AcceptanceTest { @Test void 카테고리를_등록하고_내가_등록한_카테고리를_삭제하면_상태코드_204를_반환한다() { // given - String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(OAUTH_PROVIDER, CODE); + String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); CategoryResponse savedCategory = 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME) .as(CategoryResponse.class); diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java index 0485dbee..36c0c940 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -3,11 +3,11 @@ import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.자체_토큰을_생성하고_토큰을_반환한다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_200이_반환된다; import static com.allog.dallog.acceptance.fixtures.MemberAcceptanceFixtures.자신의_정보를_조회한다; -import static com.allog.dallog.common.fixtures.MemberFixtures.DISPLAY_NAME; -import static com.allog.dallog.common.fixtures.MemberFixtures.EMAIL; -import static com.allog.dallog.common.fixtures.MemberFixtures.PROFILE_IMAGE_URI; -import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; -import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; +import static com.allog.dallog.common.fixtures.AuthFixtures.GOOGLE_PROVIDER; +import static com.allog.dallog.common.fixtures.AuthFixtures.STUB_이름; +import static com.allog.dallog.common.fixtures.AuthFixtures.STUB_이메일; +import static com.allog.dallog.common.fixtures.AuthFixtures.STUB_프로필; +import static com.allog.dallog.common.fixtures.AuthFixtures.인증_코드; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @@ -27,7 +27,7 @@ public class MemberAcceptanceTest extends AcceptanceTest { @Test void 등록된_회원이_자신의_정보를_조회하면_상태코드_200_을_반환한다() { // given - String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(OAUTH_PROVIDER, CODE); + String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); // when ExtractableResponse response = 자신의_정보를_조회한다(accessToken); @@ -36,9 +36,9 @@ public class MemberAcceptanceTest extends AcceptanceTest { // then assertAll(() -> { 상태코드_200이_반환된다(response); - assertThat(memberResponse.getEmail()).isEqualTo(EMAIL); - assertThat(memberResponse.getDisplayName()).isEqualTo(DISPLAY_NAME); - assertThat(memberResponse.getProfileImageUrl()).isEqualTo(PROFILE_IMAGE_URI); + assertThat(memberResponse.getEmail()).isEqualTo(STUB_이메일); + assertThat(memberResponse.getDisplayName()).isEqualTo(STUB_이름); + assertThat(memberResponse.getProfileImageUrl()).isEqualTo(STUB_프로필); }); } } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java index c67b9c6e..c594d825 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java @@ -2,8 +2,8 @@ import static com.allog.dallog.acceptance.fixtures.AuthAcceptanceFixtures.자체_토큰을_생성하고_토큰을_반환한다; import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; -import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; -import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_PROVIDER; +import static com.allog.dallog.common.fixtures.AuthFixtures.GOOGLE_PROVIDER; +import static com.allog.dallog.common.fixtures.AuthFixtures.인증_코드; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.COLOR_RED; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @@ -31,7 +31,7 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { @Test void 인증된_회원이_카테고리를_구독하면_201을_반환한다() { // given - String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(OAUTH_PROVIDER, CODE); + String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); CategoryResponse categoryResponse = 새로운_카테고리를_등록한다(accessToken, "BE 공식일정"); // when @@ -52,7 +52,7 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { @Test void 인증된_회원이_구독_목록을_조회하면_200을_반환한다() { // given - String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(OAUTH_PROVIDER, CODE); + String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); CategoryResponse categoryResponse1 = 새로운_카테고리를_등록한다(accessToken, "BE 일정"); CategoryResponse categoryResponse2 = 새로운_카테고리를_등록한다(accessToken, "FE 일정"); CategoryResponse categoryResponse3 = 새로운_카테고리를_등록한다(accessToken, "공통 일정"); @@ -76,7 +76,7 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { @Test void 구독을_취소할_경우_204를_반환한다() { // given - String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(OAUTH_PROVIDER, CODE); + String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); CategoryResponse categoryResponse1 = 새로운_카테고리를_등록한다(accessToken, "BE 일정"); CategoryResponse categoryResponse2 = 새로운_카테고리를_등록한다(accessToken, "FE 일정"); CategoryResponse categoryResponse3 = 새로운_카테고리를_등록한다(accessToken, "공통 일정"); diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index 11749755..981b2715 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -1,12 +1,11 @@ package com.allog.dallog.auth.service; -import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.CODE; -import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.EMAIL; +import static com.allog.dallog.common.fixtures.AuthFixtures.STUB_이메일; +import static com.allog.dallog.common.fixtures.AuthFixtures.인증_코드; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.allog.dallog.auth.dto.TokenResponse; -import com.allog.dallog.auth.exception.InvalidTokenException; import com.allog.dallog.auth.exception.NotFoundMemberException; import com.allog.dallog.common.config.TestConfig; import com.allog.dallog.member.domain.Member; @@ -42,7 +41,7 @@ class AuthServiceTest { @Test void 토큰_생성을_하면_OAuth_서버에서_인증_후_토큰을_반환한다() { // given & when - TokenResponse actual = authService.generateTokenWithCode(CODE); + TokenResponse actual = authService.generateTokenWithCode(인증_코드); // then assertThat(actual.getAccessToken()).isNotEmpty(); @@ -52,10 +51,10 @@ class AuthServiceTest { @Test void Authorization_Code를_받으면_회원이_데이터베이스에_저장된다() { // given - authService.generateTokenWithCode(CODE); + authService.generateTokenWithCode(인증_코드); // when & then - assertThat(memberRepository.existsByEmail(EMAIL)).isTrue(); + assertThat(memberRepository.existsByEmail(STUB_이메일)).isTrue(); // SutbOAuthClient가 반환하는 OAuthMember의 이메일 } @@ -65,10 +64,10 @@ class AuthServiceTest { // 이미 가입된 유저가 소셜 로그인 버튼을 클릭했을 경우엔 회원가입 과정이 생략되고, 곧바로 access token이 발급되어야 한다. // given - authService.generateTokenWithCode(CODE); + authService.generateTokenWithCode(인증_코드); // when & then - authService.generateTokenWithCode(CODE); + authService.generateTokenWithCode(인증_코드); List actual = memberRepository.findAll(); // then diff --git a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java b/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java index bf2c5c99..51d4e25a 100644 --- a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java @@ -11,17 +11,15 @@ class JwtTokenProviderTest { private static final String JWT_SECRET_KEY = "A".repeat(32); // Secret Key는 최소 32바이트 이상이어야함. private static final int JWT_EXPIRE_LENGTH = 3600; + private static final String PAYLOAD = "payload"; private final JwtTokenProvider jwtTokenProvider = new JwtTokenProvider(JWT_SECRET_KEY, JWT_EXPIRE_LENGTH); @DisplayName("JWT 토큰을 생성한다.") @Test void JWT_토큰을_생성한다() { - // given - String payload = "hello"; - - // when - String actual = jwtTokenProvider.createToken(payload); + // given & when + String actual = jwtTokenProvider.createToken(PAYLOAD); // then assertThat(actual.split("\\.")).hasSize(3); @@ -31,14 +29,13 @@ class JwtTokenProviderTest { @Test void JWT_토큰의_Payload를_가져온다() { // given - String expected = "Hello"; - String token = jwtTokenProvider.createToken(expected); + String token = jwtTokenProvider.createToken(PAYLOAD); // when String actual = jwtTokenProvider.getPayload(token); // then - assertThat(actual).isEqualTo(expected); + assertThat(actual).isEqualTo(PAYLOAD); } @DisplayName("validateToken 메서드는 만료된 토큰을 전달하면 예외를 던진다.") @@ -46,7 +43,7 @@ class JwtTokenProviderTest { void validateToken_메서드는_만료된_토큰을_전달하면_예외를_던진다() { // given JwtTokenProvider expiredJwtTokenProvider = new JwtTokenProvider(JWT_SECRET_KEY, 0); - String expiredToken = expiredJwtTokenProvider.createToken("payload"); + String expiredToken = expiredJwtTokenProvider.createToken(PAYLOAD); // when & then assertThatThrownBy(() -> jwtTokenProvider.validateToken(expiredToken)) diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java new file mode 100644 index 00000000..3bf4b82c --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java @@ -0,0 +1,12 @@ +package com.allog.dallog.common.fixtures; + +public class AuthFixtures { + + public static final String GOOGLE_PROVIDER = "google"; + + public static final String 인증_코드 = "authorization code"; + + public static final String STUB_이메일 = "stub@email.com"; + public static final String STUB_이름 = "stub"; + public static final String STUB_프로필 = "/image.png"; +} diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/OAuthMemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/OAuthMemberFixtures.java deleted file mode 100644 index 21c6c6a8..00000000 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/OAuthMemberFixtures.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.allog.dallog.common.fixtures; - -import com.allog.dallog.auth.dto.OAuthMember; - -public class OAuthMemberFixtures { - - public static final String OAUTH_PROVIDER = "google"; - - public static final String CODE = "authorization code"; - - public static final String EMAIL = "example@email.com"; - public static final String DISPLAY_NAME = "example"; - public static final String PROFILE_IMAGE_URI = "/image.png"; - - public static final OAuthMember OAUTH_MEMBER = new OAuthMember(EMAIL, DISPLAY_NAME, PROFILE_IMAGE_URI); -} diff --git a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java index 2b4ef480..64031aa1 100644 --- a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java +++ b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java @@ -1,6 +1,8 @@ package com.allog.dallog.infrastructure.oauth.client; -import static com.allog.dallog.common.fixtures.OAuthMemberFixtures.OAUTH_MEMBER; +import static com.allog.dallog.common.fixtures.AuthFixtures.STUB_이름; +import static com.allog.dallog.common.fixtures.AuthFixtures.STUB_이메일; +import static com.allog.dallog.common.fixtures.AuthFixtures.STUB_프로필; import com.allog.dallog.auth.dto.OAuthMember; import com.allog.dallog.auth.support.OAuthClient; @@ -9,6 +11,6 @@ public class StubOAuthClient implements OAuthClient { @Override public OAuthMember getOAuthMember(final String code) { - return OAUTH_MEMBER; + return new OAuthMember(STUB_이메일, STUB_이름, STUB_프로필); } } From bfeaa725a0add16a5b4763e32c562a5a22700313 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Tue, 26 Jul 2022 15:17:19 +0900 Subject: [PATCH 0317/1011] =?UTF-8?q?test(Member):=20MemberTest=20?= =?UTF-8?q?=ED=94=BD=EC=8A=A4=EC=B2=98=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/fixtures/MemberFixtures.java | 4 ++ .../dallog/member/domain/MemberTest.java | 37 ++++++------------- 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java index 853c5aaa..98b36538 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java @@ -5,6 +5,10 @@ public class MemberFixtures { + public static final String 파랑_이메일 = "parang@email.com"; + public static final String 파랑_프로필 = "/parang.png"; + public static final String 파랑_이름 = "파랑"; + public static final String EMAIL = "example@email.com"; public static final String PROFILE_IMAGE_URI = "/image.png"; public static final String DISPLAY_NAME = "example"; diff --git a/backend/src/test/java/com/allog/dallog/member/domain/MemberTest.java b/backend/src/test/java/com/allog/dallog/member/domain/MemberTest.java index 3c9be418..614fd558 100644 --- a/backend/src/test/java/com/allog/dallog/member/domain/MemberTest.java +++ b/backend/src/test/java/com/allog/dallog/member/domain/MemberTest.java @@ -1,5 +1,8 @@ package com.allog.dallog.member.domain; +import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_이름; +import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_이메일; +import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_프로필; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -14,43 +17,25 @@ class MemberTest { @DisplayName("회원을 생성한다.") @Test void 회원을_생성한다() { - // given - String email = "dev.hyeonic@gmail.com"; - String profileImageUrl = "https://avatars.githubusercontent.com/u/59357153?v=4"; - String displayName = "매트"; - SocialType socialType = SocialType.GOOGLE; - - // when & then - assertDoesNotThrow(() -> new Member(email, profileImageUrl, displayName, socialType)); + // given & when & then + assertDoesNotThrow(() -> new Member(파랑_이메일, 파랑_프로필, 파랑_이름, SocialType.GOOGLE)); } @DisplayName("회원의 email이 형식이 맞지 않으면 예외를 던진다.") @ParameterizedTest @ValueSource(strings = {"dev.hyeonic@", "dev.hyeonicgmail.com", "dev.hyeonic@gmail", "@gmail.com", "dev.hyeonic"}) void 회원의_email이_형식이_맞지_않으면_예외를_던진다(final String email) { - // given - String profileImageUrl = "https://avatars.githubusercontent.com/u/59357153?v=4"; - String displayName = "매트"; - SocialType socialType = SocialType.GOOGLE; - - // when & then - assertThatThrownBy(() -> new Member(email, profileImageUrl, displayName, socialType)) - .isInstanceOf(InvalidMemberException.class) - .hasMessage("이메일 형식이 올바르지 않습니다."); + // given & when & then + assertThatThrownBy(() -> new Member(email, 파랑_프로필, 파랑_이름, SocialType.GOOGLE)) + .isInstanceOf(InvalidMemberException.class); } @DisplayName("회원의 이름이 1 ~ 10 사이가 아닌 경우 예외를 던진다.") @ParameterizedTest @ValueSource(strings = {"", "일이삼사오육칠팔구십일"}) void 회원의_이름이_1_에서_10_사이가_아닌_경우_예외를_던진다(final String displayName) { - // given - String email = "dev.hyeonic@gmail.com"; - String profileImageUrl = "https://avatars.githubusercontent.com/u/59357153?v=4"; - SocialType socialType = SocialType.GOOGLE; - - // when & then - assertThatThrownBy(() -> new Member(email, profileImageUrl, displayName, socialType)) - .isInstanceOf(InvalidMemberException.class) - .hasMessage("이름 형식이 올바르지 않습니다."); + // given & when & then + assertThatThrownBy(() -> new Member(파랑_이메일, 파랑_프로필, displayName, SocialType.GOOGLE)) + .isInstanceOf(InvalidMemberException.class); } } From 5e70238e7a3337ab8e50dce44e1b5d600471e323 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Tue, 26 Jul 2022 15:33:18 +0900 Subject: [PATCH 0318/1011] =?UTF-8?q?test(Member):=20MemberRepositoryTest,?= =?UTF-8?q?=20MemberServiceTest=20=ED=94=BD=EC=8A=A4=EC=B2=98=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/fixtures/MemberFixtures.java | 8 +++ .../member/domain/MemberRepositoryTest.java | 17 +++--- .../member/service/MemberServiceTest.java | 60 ++++++++++--------- 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java index 98b36538..6eee6e6e 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java @@ -9,6 +9,10 @@ public class MemberFixtures { public static final String 파랑_프로필 = "/parang.png"; public static final String 파랑_이름 = "파랑"; + public static final String 리버_이메일 = "leaver@email.com"; + public static final String 리버_프로필 = "/leaver.png"; + public static final String 리버_이름 = "리버"; + public static final String EMAIL = "example@email.com"; public static final String PROFILE_IMAGE_URI = "/image.png"; public static final String DISPLAY_NAME = "example"; @@ -16,4 +20,8 @@ public class MemberFixtures { public static final Member MEMBER = new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE); public static final Member CREATOR = new Member("creator@email.com", "/image.png", "creator", SocialType.GOOGLE); public static final Member CREATOR2 = new Member("creator2@eamil.com", "/image.png", "creator2", SocialType.GOOGLE); + + public static Member 파랑() { + return new Member(파랑_이메일, 파랑_프로필, 파랑_이름, SocialType.GOOGLE); + } } diff --git a/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java b/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java index e0956554..871b8018 100644 --- a/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java @@ -1,8 +1,7 @@ package com.allog.dallog.member.domain; -import static com.allog.dallog.common.fixtures.MemberFixtures.DISPLAY_NAME; -import static com.allog.dallog.common.fixtures.MemberFixtures.EMAIL; -import static com.allog.dallog.common.fixtures.MemberFixtures.PROFILE_IMAGE_URI; +import static com.allog.dallog.common.fixtures.MemberFixtures.파랑; +import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_이메일; import static org.assertj.core.api.Assertions.assertThat; import com.allog.dallog.global.config.JpaConfig; @@ -23,24 +22,22 @@ class MemberRepositoryTest { @Test void 이메일을_통해_회원을_찾는다() { // given - Member member = new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE); - Member savedMember = memberRepository.save(member); + Member 파랑 = memberRepository.save(파랑()); // when - Member foundMember = memberRepository.findByEmail(EMAIL).get(); + Member actual = memberRepository.findByEmail(파랑_이메일).get(); // then - assertThat(savedMember.getId()).isEqualTo(foundMember.getId()); + assertThat(actual.getId()).isEqualTo(파랑.getId()); } @DisplayName("중복된 이메일이 존재하는 경우 true를 반환한다.") @Test void 중복된_이메일이_존재하는_경우_true를_반환한다() { // given - Member member = new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE); - memberRepository.save(member); + memberRepository.save(파랑()); // when & then - assertThat(memberRepository.existsByEmail(EMAIL)).isTrue(); + assertThat(memberRepository.existsByEmail(파랑_이메일)).isTrue(); } } diff --git a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java b/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java index 956b9cd7..ff0466b5 100644 --- a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java @@ -1,18 +1,14 @@ package com.allog.dallog.member.service; -import static com.allog.dallog.common.fixtures.MemberFixtures.DISPLAY_NAME; -import static com.allog.dallog.common.fixtures.MemberFixtures.EMAIL; -import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; -import static com.allog.dallog.common.fixtures.MemberFixtures.PROFILE_IMAGE_URI; +import static com.allog.dallog.common.fixtures.MemberFixtures.리버_이메일; +import static com.allog.dallog.common.fixtures.MemberFixtures.파랑; +import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_이메일; import static org.assertj.core.api.Assertions.assertThat; import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.domain.SocialType; import com.allog.dallog.member.dto.MemberResponse; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.transaction.annotation.Transactional; @@ -27,55 +23,61 @@ class MemberServiceTest { @DisplayName("회원을 저장한다.") @Test void 회원을_저장한다() { - // given - Member member = new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE); - - // when - MemberResponse actual = memberService.save(member); + // given & when + MemberResponse 파랑 = memberService.save(파랑()); // then - assertThat(actual).isNotNull(); + assertThat(파랑).isNotNull(); } @DisplayName("이메일로 회원을 찾는다.") @Test void 이메일로_회원을_찾는다() { // given - Member member = new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE); - MemberResponse savedMember = memberService.save(member); + MemberResponse 파랑 = memberService.save(파랑()); // when - Member foundMember = memberService.getByEmail(EMAIL); + Member actual = memberService.getByEmail(파랑_이메일); // then - assertThat(foundMember.getId()).isEqualTo(savedMember.getId()); + assertThat(actual.getId()).isEqualTo(파랑.getId()); } @DisplayName("id를 통해 회원을 단건 조회한다.") @Test void id를_통해_회원을_단건_조회한다() { // given - MemberResponse savedMember = memberService.save(MEMBER); + MemberResponse 파랑 = memberService.save(파랑()); // when & then - assertThat(memberService.findById(savedMember.getId())) + assertThat(memberService.findById(파랑.getId())) .usingRecursiveComparison() - .isEqualTo(savedMember); + .isEqualTo(파랑); + } + + @DisplayName("주어진 이메일로 가입된 회원이 있으면 true를 반환한다.") + @Test + void 주어진_이메일로_가입된_회원이_있으면_true를_반환한다() { + // given + memberService.save(파랑()); + + // when + boolean actual = memberService.existsByEmail(파랑_이메일); + + // then + assertThat(actual).isTrue(); } - @DisplayName("주어진 이메일로 가입된 회원이 있는지 확인한다.") - @CsvSource(value = {"registerd@gmail.com,true", "notregistered@naver.com,false"}) - @ParameterizedTest - void 주어진_이메일로_가입된_회원이_있는지_확인한다(String input, boolean expected) { + @DisplayName("주어진 이메일로 가입된 회원이 없으면 false를 반환한다.") + @Test + void 주어진_이메일로_가입된_회원이_없으면_false를_반환한다() { // given - String email = "registerd@gmail.com"; - Member member = new Member(email, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE); - memberService.save(member); + memberService.save(파랑()); // when - boolean actual = memberService.existsByEmail(input); + boolean actual = memberService.existsByEmail(리버_이메일); // then - assertThat(actual).isEqualTo(expected); + assertThat(actual).isFalse(); } } From 8392cf59501f50f9878946ed4a9bcd26e9773c54 Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 26 Jul 2022 15:39:55 +0900 Subject: [PATCH 0319/1011] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=AF=B8=20?= =?UTF-8?q?=EC=A1=B4=EC=9E=AC=ED=95=98=EB=8A=94=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EC=9D=B8=EC=A7=80=20=EA=B2=80=EC=A6=9D=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20MemberService=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/allog/dallog/auth/service/AuthService.java | 4 +--- .../support/AuthenticationPrincipalArgumentResolver.java | 1 - .../java/com/allog/dallog/member/service/MemberService.java | 6 ++++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index 55fbf77b..3020457e 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -58,9 +58,7 @@ private Member generateMemberBy(final OAuthMember oAuthMember) { } public void validateExistsMember(final Long id) { - if (!memberService.existsById(id)) { - throw new NotFoundMemberException("존재하지 않는 회원 입니다."); - } + memberService.validateExistsMember(id); } public String getPayload(final String accessToken) { diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java index f16214b1..523719b3 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java @@ -32,7 +32,6 @@ public Object resolveArgument(final MethodParameter parameter, final ModelAndVie Long id = Long.parseLong(authService.getPayload(accessToken)); authService.validateExistsMember(id); - return new LoginMember(id); } } diff --git a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java index 855baf63..b8e24901 100644 --- a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java +++ b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java @@ -40,7 +40,9 @@ public boolean existsByEmail(final String email) { return memberRepository.existsByEmail(email); } - public boolean existsById(final Long id) { - return memberRepository.existsById(id); + public void validateExistsMember(final Long id) { + if (memberRepository.existsById(id)) { + throw new NoSuchMemberException("이미 존재하는 회원입니다."); + } } } From bd3814090c0fa7507be353457cd190cdfedab2cb Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 26 Jul 2022 15:49:16 +0900 Subject: [PATCH 0320/1011] =?UTF-8?q?refactor:=20MemberService.validateExi?= =?UTF-8?q?stsMember()=EC=9D=98=20=EB=A1=9C=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/exception/NotFoundMemberException.java | 12 ------------ .../com/allog/dallog/auth/service/AuthService.java | 1 - .../allog/dallog/member/service/MemberService.java | 4 ++-- .../allog/dallog/auth/service/AuthServiceTest.java | 12 ------------ .../dallog/member/service/MemberServiceTest.java | 13 +++++++++++++ 5 files changed, 15 insertions(+), 27 deletions(-) delete mode 100644 backend/src/main/java/com/allog/dallog/auth/exception/NotFoundMemberException.java diff --git a/backend/src/main/java/com/allog/dallog/auth/exception/NotFoundMemberException.java b/backend/src/main/java/com/allog/dallog/auth/exception/NotFoundMemberException.java deleted file mode 100644 index 1805ed21..00000000 --- a/backend/src/main/java/com/allog/dallog/auth/exception/NotFoundMemberException.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.allog.dallog.auth.exception; - -public class NotFoundMemberException extends RuntimeException { - - public NotFoundMemberException(final String message) { - super(message); - } - - public NotFoundMemberException() { - this("존재하지 않는 데이터 입니다."); - } -} diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index 3020457e..2b59f15f 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -2,7 +2,6 @@ import com.allog.dallog.auth.dto.OAuthMember; import com.allog.dallog.auth.dto.TokenResponse; -import com.allog.dallog.auth.exception.NotFoundMemberException; import com.allog.dallog.auth.support.JwtTokenProvider; import com.allog.dallog.auth.support.OAuthClient; import com.allog.dallog.auth.support.OAuthUri; diff --git a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java index b8e24901..68fc77cb 100644 --- a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java +++ b/backend/src/main/java/com/allog/dallog/member/service/MemberService.java @@ -41,8 +41,8 @@ public boolean existsByEmail(final String email) { } public void validateExistsMember(final Long id) { - if (memberRepository.existsById(id)) { - throw new NoSuchMemberException("이미 존재하는 회원입니다."); + if (!memberRepository.existsById(id)) { + throw new NoSuchMemberException("존재하지 않는 회원입니다."); } } } diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java index 981b2715..2564fb62 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java @@ -6,7 +6,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.allog.dallog.auth.dto.TokenResponse; -import com.allog.dallog.auth.exception.NotFoundMemberException; import com.allog.dallog.common.config.TestConfig; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; @@ -73,15 +72,4 @@ class AuthServiceTest { // then assertThat(actual).hasSize(1); } - - @DisplayName("회원이 존재하지 않으면 예외를 던진다.") - @Test - void 회원이_존재하지_않으면_예외를_던진다() { - // given - Long id = 0L; - - // when & then - assertThatThrownBy(() -> authService.validateExistsMember(id)) - .isInstanceOf(NotFoundMemberException.class); - } } diff --git a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java b/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java index ff0466b5..1e2a412b 100644 --- a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java @@ -4,9 +4,11 @@ import static com.allog.dallog.common.fixtures.MemberFixtures.파랑; import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_이메일; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.dto.MemberResponse; +import com.allog.dallog.member.exception.NoSuchMemberException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -80,4 +82,15 @@ class MemberServiceTest { // then assertThat(actual).isFalse(); } + + @DisplayName("회원이 존재하지 않으면 예외를 던진다.") + @Test + void 회원이_존재하지_않으면_예외를_던진다() { + // given + Long id = 0L; + + // when & then + assertThatThrownBy(() -> memberService.validateExistsMember(id)) + .isInstanceOf(NoSuchMemberException.class); + } } From 4b881fc38c00ddf7a29831248209eb9ab82d7bd4 Mon Sep 17 00:00:00 2001 From: koo Date: Tue, 26 Jul 2022 16:07:17 +0900 Subject: [PATCH 0321/1011] =?UTF-8?q?refactor:=20AuthService.extractMember?= =?UTF-8?q?Id()=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/allog/dallog/auth/service/AuthService.java | 11 +++++------ .../AuthenticationPrincipalArgumentResolver.java | 4 +--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java index 2b59f15f..9de17af6 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java @@ -56,12 +56,11 @@ private Member generateMemberBy(final OAuthMember oAuthMember) { SocialType.GOOGLE); } - public void validateExistsMember(final Long id) { - memberService.validateExistsMember(id); - } - - public String getPayload(final String accessToken) { + public Long extractMemberId(final String accessToken) { jwtTokenProvider.validateToken(accessToken); - return jwtTokenProvider.getPayload(accessToken); + String payload = jwtTokenProvider.getPayload(accessToken); + Long memberId = Long.valueOf(payload); + memberService.validateExistsMember(memberId); + return memberId; } } diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java index 523719b3..de19bb3f 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java +++ b/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java @@ -29,9 +29,7 @@ public Object resolveArgument(final MethodParameter parameter, final ModelAndVie final NativeWebRequest webRequest, final WebDataBinderFactory binderFactory) { HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); String accessToken = AuthorizationExtractor.extract(request); - - Long id = Long.parseLong(authService.getPayload(accessToken)); - authService.validateExistsMember(id); + Long id = authService.extractMemberId(accessToken); return new LoginMember(id); } } From 1afd9b1bc942c64d8fecedf0c03cb9cd7b7b7768 Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 26 Jul 2022 12:57:36 +0900 Subject: [PATCH 0322/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=ED=94=BD=EC=8A=A4=EC=B2=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: hyeonic --- .../common/fixtures/CategoryFixtures.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 9630065a..90e6bec2 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -5,6 +5,8 @@ import com.allog.dallog.category.domain.Category; import com.allog.dallog.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.member.domain.SocialType; public class CategoryFixtures { @@ -29,4 +31,58 @@ public class CategoryFixtures { public static final CategoryCreateRequest CATEGORY_CREATE_REQUEST_1 = new CategoryCreateRequest("BE 일정"); public static final CategoryCreateRequest CATEGORY_CREATE_REQUEST_2 = new CategoryCreateRequest("FE 일정"); public static final CategoryCreateRequest CATEGORY_CREATE_REQUEST_3 = new CategoryCreateRequest("공통 일정"); + + /* 공통 일정 카테고리 */ + public static final String 공통_일정_이름 = "공통 일정"; + public static final CategoryCreateRequest 공통_일정_생성_요청 = new CategoryCreateRequest(공통_일정_이름); + + /* BE 일정 카테고리 */ + public static final String BE_일정_이름 = "BE 일정"; + public static final CategoryCreateRequest BE_일정_생성_요청 = new CategoryCreateRequest(BE_일정_이름); + + /* FE 일정 카테고리 */ + public static final String FE_일정_이름 = "BE 일정"; + public static final CategoryCreateRequest FE_일정_생성_요청 = new CategoryCreateRequest(FE_일정_이름); + + /* 매트 아고라 카테고리 */ + public static final String 매트_아고라_이름 = "매트 아고라"; + public static final CategoryCreateRequest 매트_아고라_생성_요청 = new CategoryCreateRequest(매트_아고라_이름); + + /* 후디 JPA 스터디 카테고리 */ + public static final String 후디_JPA_스터디_이름 = "후디 JPA 스터디"; + public static final CategoryCreateRequest 후디_JPA_스터디_생성_요청 = new CategoryCreateRequest(후디_JPA_스터디_이름); + + + public static Category 공통_일정(final Member creator) { + return new Category(공통_일정_이름, creator); + } + + public static Category BE_일정(final Member creator) { + return new Category(BE_일정_이름, creator); + } + + public static Category FE_일정(final Member creator) { + return new Category(FE_일정_이름, creator); + } + + public static Category 매트_아고라(final Member creator) { + return new Category(매트_아고라_이름, creator); + } + + public static Category 후디_JPA_스터디(final Member creator) { + return new Category(후디_JPA_스터디_이름, creator); + } + + /* 임시 멤버 */ + public static Member 후디() { + return new Member("devhudi@gmail.com", "/image.png", "후디", SocialType.GOOGLE); + } + + public static Member 매트() { + return new Member("dev.hyeonic@gmail.com", "/image2.png", "매트", SocialType.GOOGLE); + } + + public static Member 관리자() { + return new Member("dallog.admin@gmail.com", "/image3.png", "관리자", SocialType.GOOGLE); + } } From 27f8e279844279d376b34f2977ab7d6281a4f57c Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 26 Jul 2022 14:43:54 +0900 Subject: [PATCH 0323/1011] =?UTF-8?q?test:=20category=20fixture=20?= =?UTF-8?q?=EB=8F=84=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: hyeonic --- .../acceptance/CategoryAcceptanceTest.java | 58 +++++---- .../fixtures/CategoryAcceptanceFixtures.java | 4 +- .../domain/CategoryRepositoryTest.java | 78 +++++++----- .../category/service/CategoryServiceTest.java | 118 +++++++++--------- .../common/fixtures/CategoryFixtures.java | 19 +-- .../SubscriptionRepositoryTest.java | 20 +-- 6 files changed, 141 insertions(+), 156 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index cb4e8413..dcc36b4d 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -12,10 +12,11 @@ import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_204가_반환된다; import static com.allog.dallog.common.fixtures.AuthFixtures.GOOGLE_PROVIDER; import static com.allog.dallog.common.fixtures.AuthFixtures.인증_코드; -import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; -import static com.allog.dallog.common.fixtures.CategoryFixtures.MODIFIED_CATEGORY_NAME; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_1; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE_2; +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.매트_아고라_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.후디_JPA_스터디_생성_요청; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @@ -36,7 +37,7 @@ public class CategoryAcceptanceTest extends AcceptanceTest { String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); // when - ExtractableResponse response = 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); + ExtractableResponse response = 새로운_카테고리를_등록한다(accessToken, 매트_아고라_생성_요청); // then 상태코드_201이_반환된다(response); @@ -47,20 +48,21 @@ public class CategoryAcceptanceTest extends AcceptanceTest { void 카테고리를_등록하고_페이징을_통해_나누어_조회한다() { // given String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); - 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); - 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); - 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); - 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); + 새로운_카테고리를_등록한다(accessToken, 공통_일정_생성_요청); + 새로운_카테고리를_등록한다(accessToken, BE_일정_생성_요청); + 새로운_카테고리를_등록한다(accessToken, FE_일정_생성_요청); + 새로운_카테고리를_등록한다(accessToken, 매트_아고라_생성_요청); + 새로운_카테고리를_등록한다(accessToken, 후디_JPA_스터디_생성_요청); // when - ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(PAGE_NUMBER_1, PAGE_SIZE_2); + ExtractableResponse response = 카테고리를_페이징을_통해_조회한다(1, 3); CategoriesResponse categoriesResponse = response.as(CategoriesResponse.class); // then assertAll(() -> { 상태코드_200이_반환된다(response); - assertThat(categoriesResponse.getPage()).isEqualTo(PAGE_NUMBER_1); - assertThat(categoriesResponse.getCategories()).hasSize(PAGE_SIZE_2); + assertThat(categoriesResponse.getPage()).isEqualTo(1); + assertThat(categoriesResponse.getCategories()).hasSize(2); }); } @@ -69,21 +71,19 @@ public class CategoryAcceptanceTest extends AcceptanceTest { void 카테고리를_등록하고_내가_등록한_카테고리를_페이징을_통해_나누어_조회한다() { // given String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); - 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); - 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); - 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME); - - int page = 0; + 새로운_카테고리를_등록한다(accessToken, 공통_일정_생성_요청); + 새로운_카테고리를_등록한다(accessToken, BE_일정_생성_요청); + 새로운_카테고리를_등록한다(accessToken, FE_일정_생성_요청); // when - ExtractableResponse response = 내가_등록한_카테고리를_페이징을_통해_조회한다(accessToken, page, PAGE_SIZE_2); + ExtractableResponse response = 내가_등록한_카테고리를_페이징을_통해_조회한다(accessToken, 0, 2); CategoriesResponse categoriesResponse = response.as(CategoriesResponse.class); // then assertAll(() -> { 상태코드_200이_반환된다(response); - assertThat(categoriesResponse.getPage()).isEqualTo(page); - assertThat(categoriesResponse.getCategories()).hasSize(PAGE_SIZE_2); + assertThat(categoriesResponse.getPage()).isEqualTo(0); + assertThat(categoriesResponse.getCategories()).hasSize(2); }); } @@ -92,18 +92,17 @@ public class CategoryAcceptanceTest extends AcceptanceTest { void 카테고리를_등록하고_내가_등록한_카테고리를_수정하면_상태코드_204를_반환한다() { // given String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); - CategoryResponse savedCategory = 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME) - .as(CategoryResponse.class); + CategoryResponse savedCategory = 새로운_카테고리를_등록한다(accessToken, 공통_일정_생성_요청).as(CategoryResponse.class); + String newCategoryName = "우테코 공통 일정"; // when - ExtractableResponse response - = 내가_등록한_카테고리를_수정한다(accessToken, savedCategory.getId(), MODIFIED_CATEGORY_NAME); + ExtractableResponse response = 내가_등록한_카테고리를_수정한다(accessToken, savedCategory.getId(), newCategoryName); CategoryResponse categoryResponse = id를_통해_카테고리를_가져온다(savedCategory.getId()).as(CategoryResponse.class); // then assertAll(() -> { 상태코드_204가_반환된다(response); - assertThat(categoryResponse.getName()).isEqualTo(MODIFIED_CATEGORY_NAME); + assertThat(categoryResponse.getName()).isEqualTo(newCategoryName); }); } @@ -112,15 +111,14 @@ public class CategoryAcceptanceTest extends AcceptanceTest { void 카테고리를_등록하고_내가_등록한_카테고리를_삭제하면_상태코드_204를_반환한다() { // given String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); - CategoryResponse savedCategory = 새로운_카테고리를_등록한다(accessToken, CATEGORY_NAME) - .as(CategoryResponse.class); + CategoryResponse savedCategory = 새로운_카테고리를_등록한다(accessToken, 공통_일정_생성_요청).as(CategoryResponse.class); // when - ExtractableResponse response - = 내가_등록한_카테고리를_삭제한다(accessToken, savedCategory.getId()); - // todo: ExceptionHandler 구현 이후 카테고리 단건 조회 응답 상태코드 404인지 확인 + ExtractableResponse response = 내가_등록한_카테고리를_삭제한다(accessToken, savedCategory.getId()); // then 상태코드_204가_반환된다(response); } + + // todo: ExceptionHandler 구현 이후 카테고리 단건 조회 응답 상태코드 404인지 확인 } diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java index 68c0a983..8dbf2b9c 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java @@ -9,8 +9,8 @@ public class CategoryAcceptanceFixtures { - public static ExtractableResponse 새로운_카테고리를_등록한다(final String accessToken, final String name) { - CategoryCreateRequest request = new CategoryCreateRequest(name); + public static ExtractableResponse 새로운_카테고리를_등록한다(final String accessToken, + final CategoryCreateRequest request) { return RestAssured.given().log().all() .auth().oauth2(accessToken) .contentType(MediaType.APPLICATION_JSON_VALUE) diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java index 62937b04..92637b5b 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java @@ -1,11 +1,16 @@ package com.allog.dallog.category.domain; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_0; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_1; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE_2; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE_8; -import static com.allog.dallog.common.fixtures.MemberFixtures.CREATOR; -import static com.allog.dallog.common.fixtures.MemberFixtures.CREATOR2; +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정; +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_이름; +import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정; +import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_이름; +import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정; +import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_이름; +import static com.allog.dallog.common.fixtures.CategoryFixtures.관리자; +import static com.allog.dallog.common.fixtures.CategoryFixtures.매트_아고라; +import static com.allog.dallog.common.fixtures.CategoryFixtures.매트_아고라_이름; +import static com.allog.dallog.common.fixtures.CategoryFixtures.후디; +import static com.allog.dallog.common.fixtures.CategoryFixtures.후디_JPA_스터디; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @@ -35,22 +40,23 @@ class CategoryRepositoryTest { @Test void 페이지와_사이즈를_받아_해당하는_구간의_카테고리를_조회한다() { // given - Member creator = memberRepository.save(CREATOR); - categoryRepository.save(new Category("BE 공식일정", creator)); - categoryRepository.save(new Category("FE 공식일정", creator)); - categoryRepository.save(new Category("알록달록 회의", creator)); - categoryRepository.save(new Category("지원플랫폼 근로", creator)); - categoryRepository.save(new Category("파랑의 코틀린 스터디", creator)); + Member 관리자 = memberRepository.save(관리자()); + categoryRepository.save(공통_일정(관리자)); + categoryRepository.save(BE_일정(관리자)); + categoryRepository.save(FE_일정(관리자)); + categoryRepository.save(매트_아고라(관리자)); + categoryRepository.save(후디_JPA_스터디(관리자)); - PageRequest pageRequest = PageRequest.of(PAGE_NUMBER_1, PAGE_SIZE_2); + PageRequest pageRequest = PageRequest.of(1, 2); // when Slice categories = categoryRepository.findSliceBy(pageRequest); // then assertAll(() -> { - assertThat(categories.getContent()).hasSize(PAGE_SIZE_2).extracting(Category::getName) - .contains("알록달록 회의", "지원플랫폼 근로"); + assertThat(categories.getContent()).hasSize(2) + .extracting(Category::getName) + .contains(FE_일정_이름, 매트_아고라_이름); assertThat( categories.getContent().stream() .map(Category::getCreatedAt) @@ -63,7 +69,7 @@ class CategoryRepositoryTest { @Test void 조회_시_데이터가_존재하지_않는_경우_빈_슬라이스가_반환된다() { // given - PageRequest pageRequest = PageRequest.of(PAGE_NUMBER_1, PAGE_SIZE_2); + PageRequest pageRequest = PageRequest.of(1, 2); // when Slice categories = categoryRepository.findSliceBy(pageRequest); @@ -76,25 +82,29 @@ class CategoryRepositoryTest { @Test void 특정_멤버가_생성한_카테고리를_페이징을_통해_조회한다() { // given - Member creator = memberRepository.save(CREATOR); - Member creator2 = memberRepository.save(CREATOR2); - categoryRepository.save(new Category("BE 공식일정", creator)); - categoryRepository.save(new Category("FE 공식일정", creator)); - categoryRepository.save(new Category("알록달록 회의", creator)); - categoryRepository.save(new Category("지원플랫폼 근로", creator2)); - categoryRepository.save(new Category("파랑의 코틀린 스터디", creator2)); + Member 관리자 = memberRepository.save(관리자()); + categoryRepository.save(공통_일정(관리자)); + categoryRepository.save(BE_일정(관리자)); + categoryRepository.save(FE_일정(관리자)); - PageRequest pageRequest = PageRequest.of(PAGE_NUMBER_0, PAGE_SIZE_8); + Member 후디 = memberRepository.save(후디()); + categoryRepository.save(후디_JPA_스터디(후디)); + + PageRequest pageRequest = PageRequest.of(0, 8); // when - Slice categories = categoryRepository.findSliceByMemberId(pageRequest, creator.getId()); + Slice categories = categoryRepository.findSliceByMemberId(pageRequest, 관리자.getId()); // then assertAll(() -> { - assertThat(categories.getContent()).hasSize(3).extracting(Category::getName) - .containsExactlyInAnyOrder("BE 공식일정", "FE 공식일정", "알록달록 회의"); + assertThat(categories.getContent()).hasSize(3) + .extracting(Category::getName) + .containsExactlyInAnyOrder(공통_일정_이름, BE_일정_이름, FE_일정_이름); assertThat( - categories.getContent().stream().map(Category::getCreatedAt).allMatch(Objects::nonNull)).isTrue(); + categories.getContent().stream() + .map(Category::getCreatedAt) + .allMatch(Objects::nonNull)) + .isTrue(); }); } @@ -102,11 +112,11 @@ class CategoryRepositoryTest { @Test void 카테고리_id와_회원의_id가_모두_일치하는_카테고리가_있으면_true를_반환한다() { // given - Member creator = memberRepository.save(CREATOR); - Category category = categoryRepository.save(new Category("BE 공식일정", creator)); + Member 관리자 = memberRepository.save(관리자()); + Category 공통_일정 = categoryRepository.save(공통_일정(관리자)); // when - boolean actual = categoryRepository.existsByIdAndMemberId(category.getId(), creator.getId()); + boolean actual = categoryRepository.existsByIdAndMemberId(공통_일정.getId(), 관리자.getId()); // then assertThat(actual).isTrue(); @@ -116,11 +126,11 @@ class CategoryRepositoryTest { @Test void 카테고리_id와_회원의_id가_모두_일치하는_카테고리가_없으면_false를_반환한다() { // given - Member creator = memberRepository.save(CREATOR); - Category category = categoryRepository.save(new Category("BE 공식일정", creator)); + Member 관리자 = memberRepository.save(관리자()); + Category 공통_일정 = categoryRepository.save(공통_일정(관리자)); // when - boolean actual = categoryRepository.existsByIdAndMemberId(category.getId(), creator.getId() + 1L); + boolean actual = categoryRepository.existsByIdAndMemberId(공통_일정.getId(), 0L); // then assertThat(actual).isFalse(); diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 990f419a..5333ed81 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -1,13 +1,15 @@ package com.allog.dallog.category.service; -import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_NAME; -import static com.allog.dallog.common.fixtures.CategoryFixtures.MODIFIED_CATEGORY_NAME; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_NUMBER_1; -import static com.allog.dallog.common.fixtures.CategoryFixtures.PAGE_SIZE_2; -import static com.allog.dallog.common.fixtures.MemberFixtures.CREATOR; -import static com.allog.dallog.common.fixtures.MemberFixtures.DISPLAY_NAME; -import static com.allog.dallog.common.fixtures.MemberFixtures.EMAIL; -import static com.allog.dallog.common.fixtures.MemberFixtures.PROFILE_IMAGE_URI; +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_이름; +import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_이름; +import static com.allog.dallog.common.fixtures.CategoryFixtures.관리자; +import static com.allog.dallog.common.fixtures.CategoryFixtures.매트; +import static com.allog.dallog.common.fixtures.CategoryFixtures.매트_아고라_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.매트_아고라_이름; +import static com.allog.dallog.common.fixtures.CategoryFixtures.후디_JPA_스터디_생성_요청; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -21,7 +23,6 @@ import com.allog.dallog.category.exception.NoSuchCategoryException; import com.allog.dallog.member.domain.Member; import com.allog.dallog.member.domain.MemberRepository; -import com.allog.dallog.member.domain.SocialType; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -45,14 +46,13 @@ class CategoryServiceTest { @Test void 새로운_카테고리를_생성한다() { // given - CategoryCreateRequest request = new CategoryCreateRequest(CATEGORY_NAME); - Member creator = memberRepository.save(CREATOR); + Member creator = memberRepository.save(관리자()); // when - CategoryResponse response = categoryService.save(creator.getId(), request); + CategoryResponse response = categoryService.save(creator.getId(), 공통_일정_생성_요청); // then - assertThat(response.getName()).isEqualTo(CATEGORY_NAME); + assertThat(response.getName()).isEqualTo(공통_일정_이름); } @DisplayName("새로운 카테고리를 생성 할 떄 이름이 공백이거나 길이가 20을 초과하는 경우 예외를 던진다.") @@ -61,7 +61,7 @@ class CategoryServiceTest { void 새로운_카테고리를_생성_할_때_이름이_공백이거나_길이가_20을_초과하는_경우_예외를_던진다(final String name) { // given CategoryCreateRequest request = new CategoryCreateRequest(name); - Member creator = memberRepository.save(CREATOR); + Member creator = memberRepository.save(관리자()); // when & then assertThatThrownBy(() -> categoryService.save(creator.getId(), request)) @@ -72,97 +72,93 @@ class CategoryServiceTest { @Test void 페이지를_받아_해당하는_구간의_카테고리를_가져온다() { // given - Member creator = memberRepository.save(CREATOR); + Member creator = memberRepository.save(관리자()); Long creatorId = creator.getId(); - categoryService.save(creatorId, new CategoryCreateRequest("BE 공식일정")); - categoryService.save(creatorId, new CategoryCreateRequest("FE 공식일정")); - categoryService.save(creatorId, new CategoryCreateRequest("알록달록 회의")); - categoryService.save(creatorId, new CategoryCreateRequest("지원플랫폼 근로")); - categoryService.save(creatorId, new CategoryCreateRequest("파랑의 코틀린 스터디")); + categoryService.save(creatorId, 공통_일정_생성_요청); + categoryService.save(creatorId, BE_일정_생성_요청); + categoryService.save(creatorId, FE_일정_생성_요청); + categoryService.save(creatorId, 매트_아고라_생성_요청); + categoryService.save(creatorId, 후디_JPA_스터디_생성_요청); - PageRequest request = PageRequest.of(PAGE_NUMBER_1, PAGE_SIZE_2); + PageRequest request = PageRequest.of(1, 2); // when CategoriesResponse response = categoryService.findAll(request); // then assertThat(response.getCategories()) - .hasSize(PAGE_SIZE_2) + .hasSize(2) .extracting(CategoryResponse::getName) - .contains("알록달록 회의", "지원플랫폼 근로"); + .contains(FE_일정_이름, 매트_아고라_이름); } @DisplayName("회원 id와 페이지를 기반으로 카테고리를 가져온다.") @Test void 회원_id와_페이지를_기반으로_카테고리를_가져온다() { // given - Member creator = memberRepository.save(CREATOR); + Member creator = memberRepository.save(관리자()); Long creatorId = creator.getId(); - categoryService.save(creatorId, new CategoryCreateRequest("BE 공식일정")); - categoryService.save(creatorId, new CategoryCreateRequest("FE 공식일정")); - categoryService.save(creatorId, new CategoryCreateRequest("알록달록 회의")); - categoryService.save(creatorId, new CategoryCreateRequest("지원플랫폼 근로")); - categoryService.save(creatorId, new CategoryCreateRequest("파랑의 코틀린 스터디")); + categoryService.save(creatorId, 공통_일정_생성_요청); + categoryService.save(creatorId, BE_일정_생성_요청); + categoryService.save(creatorId, FE_일정_생성_요청); + categoryService.save(creatorId, 매트_아고라_생성_요청); + categoryService.save(creatorId, 후디_JPA_스터디_생성_요청); - PageRequest request = PageRequest.of(PAGE_NUMBER_1, PAGE_SIZE_2); + PageRequest request = PageRequest.of(1, 2); // when CategoriesResponse response = categoryService.findMine(creatorId, request); // then assertThat(response.getCategories()) - .hasSize(PAGE_SIZE_2) + .hasSize(2) .extracting(CategoryResponse::getName) - .contains("알록달록 회의", "지원플랫폼 근로"); + .contains(FE_일정_이름, 매트_아고라_이름); } @DisplayName("id를 통해 카테고리를 단건 조회한다.") @Test void id를_통해_카테고리를_단건_조회한다() { // given - Member creator = memberRepository.save(CREATOR); - categoryService.save(creator.getId(), new CategoryCreateRequest("BE 공식일정")); - CategoryResponse savedCategory = categoryService.save(creator.getId(), new CategoryCreateRequest("FE 공식일정")); + Member creator = memberRepository.save(관리자()); + CategoryResponse 공통_일정 = categoryService.save(creator.getId(), 공통_일정_생성_요청); // when & then - assertThat(categoryService.findById(savedCategory.getId())) + assertThat(categoryService.findById(공통_일정.getId())) .usingRecursiveComparison() - .isEqualTo(savedCategory); + .isEqualTo(공통_일정); } @DisplayName("회원과 카테고리 id를 통해 카테고리를 수정한다.") @Test void 회원과_카테고리_id를_통해_카테고리를_수정한다() { // given - Member creator = memberRepository.save(CREATOR); - CategoryResponse savedCategory = categoryService.save(creator.getId(), - new CategoryCreateRequest(CATEGORY_NAME)); + Member creator = memberRepository.save(관리자()); + CategoryResponse 공통_일정 = categoryService.save(creator.getId(), 공통_일정_생성_요청); + + String 우테코_공통_일정_이름 = "우테코 공통 일정"; + CategoryUpdateRequest categoryUpdateRequest = new CategoryUpdateRequest(우테코_공통_일정_이름); // when - CategoryUpdateRequest categoryUpdateRequest = new CategoryUpdateRequest(MODIFIED_CATEGORY_NAME); - categoryService.update(creator.getId(), savedCategory.getId(), categoryUpdateRequest); + categoryService.update(creator.getId(), 공통_일정.getId(), categoryUpdateRequest); + Category category = categoryService.getCategory(공통_일정.getId()); //then - Category category = categoryService.getCategory(savedCategory.getId()); - assertThat(category.getName()) - .isEqualTo(MODIFIED_CATEGORY_NAME); + assertThat(category.getName()).isEqualTo(우테코_공통_일정_이름); } @DisplayName("자신이 만들지 않은 카테고리를 수정할 경우 예외를 던진다.") @Test void 자신이_만들지_않은_카테고리를_수정할_경우_예외를_던진다() { // given - Member member = memberRepository.save(new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE)); - Member creator = memberRepository.save( - new Member("creator@email.com", "/image.png", "creator", SocialType.GOOGLE)); - CategoryResponse savedCategory = categoryService.save(creator.getId(), - new CategoryCreateRequest(CATEGORY_NAME)); + Member 관리자 = memberRepository.save(관리자()); + Member 매트 = memberRepository.save(매트()); - CategoryUpdateRequest categoryUpdateRequest = new CategoryUpdateRequest(MODIFIED_CATEGORY_NAME); + CategoryResponse savedCategory = categoryService.save(관리자.getId(), 공통_일정_생성_요청); + CategoryUpdateRequest categoryUpdateRequest = new CategoryUpdateRequest("우테코 공통 일정"); // when & then - assertThatThrownBy( - () -> categoryService.update(member.getId(), savedCategory.getId(), categoryUpdateRequest)) + assertThatThrownBy(() -> categoryService.update(매트.getId(), savedCategory.getId(), categoryUpdateRequest)) .isInstanceOf(NoPermissionException.class); } @@ -170,12 +166,11 @@ class CategoryServiceTest { @Test void 회원과_카테고리_id를_통해_카테고리를_삭제한다() { // given - Member creator = memberRepository.save(CREATOR); - CategoryResponse savedCategory = categoryService.save(creator.getId(), - new CategoryCreateRequest(CATEGORY_NAME)); + Member 관리자 = memberRepository.save(관리자()); + CategoryResponse savedCategory = categoryService.save(관리자.getId(), 공통_일정_생성_요청); // when - categoryService.delete(creator.getId(), savedCategory.getId()); + categoryService.delete(관리자.getId(), savedCategory.getId()); //then assertThatThrownBy(() -> categoryService.getCategory(savedCategory.getId())) @@ -186,14 +181,13 @@ class CategoryServiceTest { @Test void 자신이_만들지_않은_카테고리를_삭제할_경우_예외를_던진다() { // given - Member member = memberRepository.save(new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE)); - Member creator = memberRepository.save( - new Member("creator@email.com", "/image.png", "creator", SocialType.GOOGLE)); - CategoryResponse savedCategory = categoryService.save(creator.getId(), new CategoryCreateRequest("FE 공식일정")); + Member 관리자 = memberRepository.save(관리자()); + Member 매트 = memberRepository.save(매트()); + CategoryResponse savedCategory = categoryService.save(관리자.getId(), 공통_일정_생성_요청); // when & then assertThatThrownBy( - () -> categoryService.delete(member.getId(), savedCategory.getId())) + () -> categoryService.delete(매트.getId(), savedCategory.getId())) .isInstanceOf(NoPermissionException.class); } } diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 90e6bec2..d3b06a32 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -1,6 +1,5 @@ package com.allog.dallog.common.fixtures; -import static com.allog.dallog.common.fixtures.MemberFixtures.CREATOR; import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; import com.allog.dallog.category.domain.Category; @@ -10,23 +9,7 @@ public class CategoryFixtures { - public static final String CATEGORY_NAME = "달록"; - public static final String MODIFIED_CATEGORY_NAME = "수정된 달록"; - - public static final int PAGE_NUMBER_0 = 0; - public static final int PAGE_NUMBER_1 = 1; - public static final int PAGE_SIZE_2 = 2; - public static final int PAGE_SIZE_8 = 8; - - public static final Category CATEGORY = new Category(CATEGORY_NAME, MEMBER); - - public static final String CATEGORY_1_NAME = "BE 일정"; - public static final String CATEGORY_2_NAME = "BE 일정"; - public static final String CATEGORY_3_NAME = "BE 일정"; - - public static final Category CATEGORY_1 = new Category("BE 일정", CREATOR); - public static final Category CATEGORY_2 = new Category("FE 일정", CREATOR); - public static final Category CATEGORY_3 = new Category("공통 일정", CREATOR); + public static final Category CATEGORY = new Category("달록", MEMBER); public static final CategoryCreateRequest CATEGORY_CREATE_REQUEST_1 = new CategoryCreateRequest("BE 일정"); public static final CategoryCreateRequest CATEGORY_CREATE_REQUEST_2 = new CategoryCreateRequest("FE 일정"); diff --git a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java b/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java index e8db9d96..fa1a7b58 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java @@ -1,9 +1,9 @@ package com.allog.dallog.subscription.repository; -import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_1_NAME; -import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_2_NAME; -import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_3_NAME; -import static com.allog.dallog.common.fixtures.MemberFixtures.CREATOR; +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정; +import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정; +import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정; +import static com.allog.dallog.common.fixtures.CategoryFixtures.관리자; import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.COLOR_BLUE; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.COLOR_RED; @@ -40,10 +40,10 @@ class SubscriptionRepositoryTest { @Test void 회원_정보를_기반으로_구독_정보를_조회한다() { // given - Member creator = memberRepository.save(CREATOR); - Category category1 = categoryRepository.save(new Category(CATEGORY_1_NAME, creator)); - Category category2 = categoryRepository.save(new Category(CATEGORY_2_NAME, creator)); - Category category3 = categoryRepository.save(new Category(CATEGORY_3_NAME, creator)); + Member 관리자 = memberRepository.save(관리자()); + Category category1 = categoryRepository.save(공통_일정(관리자)); + Category category2 = categoryRepository.save(BE_일정(관리자)); + Category category3 = categoryRepository.save(FE_일정(관리자)); Member member = memberRepository.save(MEMBER); Subscription subscription1 = new Subscription(member, category1, COLOR_RED); @@ -78,8 +78,8 @@ class SubscriptionRepositoryTest { @Test void 회원의_특정_구독_정보_여부를_확인한다() { // given - Member creator = memberRepository.save(CREATOR); - Category category1 = categoryRepository.save(new Category(CATEGORY_1_NAME, creator)); + Member creator = memberRepository.save(관리자()); + Category category1 = categoryRepository.save(공통_일정(creator)); Member member = memberRepository.save(MEMBER); Subscription subscription1 = new Subscription(member, category1, COLOR_RED); From 222bfd3522933574f9106b66aa49b4069def29f2 Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 26 Jul 2022 15:00:08 +0900 Subject: [PATCH 0324/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=A0=88=EA=B1=B0=EC=8B=9C=20=ED=94=BD=EC=8A=A4?= =?UTF-8?q?=EC=B2=98=EB=A5=BC=20=EA=B5=AC=EB=8F=85=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: hyeonic --- .../common/fixtures/CategoryFixtures.java | 8 ---- .../subscription/domain/SubscriptionTest.java | 16 +++---- .../service/SubscriptionServiceTest.java | 47 ++++++++++--------- 3 files changed, 32 insertions(+), 39 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index d3b06a32..9d0b49a9 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -1,7 +1,5 @@ package com.allog.dallog.common.fixtures; -import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; - import com.allog.dallog.category.domain.Category; import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.member.domain.Member; @@ -9,12 +7,6 @@ public class CategoryFixtures { - public static final Category CATEGORY = new Category("달록", MEMBER); - - public static final CategoryCreateRequest CATEGORY_CREATE_REQUEST_1 = new CategoryCreateRequest("BE 일정"); - public static final CategoryCreateRequest CATEGORY_CREATE_REQUEST_2 = new CategoryCreateRequest("FE 일정"); - public static final CategoryCreateRequest CATEGORY_CREATE_REQUEST_3 = new CategoryCreateRequest("공통 일정"); - /* 공통 일정 카테고리 */ public static final String 공통_일정_이름 = "공통 일정"; public static final CategoryCreateRequest 공통_일정_생성_요청 = new CategoryCreateRequest(공통_일정_이름); diff --git a/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java b/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java index 68db568e..575f2da2 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java @@ -1,7 +1,7 @@ package com.allog.dallog.subscription.domain; -import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY; -import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; +import static com.allog.dallog.common.fixtures.CategoryFixtures.후디; +import static com.allog.dallog.common.fixtures.CategoryFixtures.후디_JPA_스터디; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -19,12 +19,12 @@ class SubscriptionTest { @Test void 구독을_생성한다() { // given - Member member = MEMBER; - Category category = CATEGORY; + Member 후디 = 후디(); + Category 후디_JPA_스터디 = 후디_JPA_스터디(후디); String color = "#c9ad2e"; // when & then - assertDoesNotThrow(() -> new Subscription(member, category, color)); + assertDoesNotThrow(() -> new Subscription(후디, 후디_JPA_스터디, color)); } @DisplayName("색 정보 형식이 잘못된 경우 예외를 던진다.") @@ -32,11 +32,11 @@ class SubscriptionTest { @ValueSource(strings = {"#111", "#1111", "#11111", "123456", "#**1234", "##12345", "334172#"}) void 색_정보_형식이_잘못된_경우_예외를_던진다(final String color) { // given - Member member = MEMBER; - Category category = CATEGORY; + Member 후디 = 후디(); + Category 후디_JPA_스터디 = 후디_JPA_스터디(후디); // when & then - assertThatThrownBy(() -> new Subscription(member, category, color)) + assertThatThrownBy(() -> new Subscription(후디, 후디_JPA_스터디, color)) .isInstanceOf(InvalidSubscriptionException.class); } } diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java index 4ab1ee2b..739d0af9 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -1,9 +1,11 @@ package com.allog.dallog.subscription.service; -import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_CREATE_REQUEST_1; -import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_CREATE_REQUEST_2; -import static com.allog.dallog.common.fixtures.CategoryFixtures.CATEGORY_CREATE_REQUEST_3; +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.관리자; +import static com.allog.dallog.common.fixtures.CategoryFixtures.후디; import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.CREATE_REQUEST_BLUE; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.CREATE_REQUEST_RED; @@ -16,7 +18,6 @@ import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; -import com.allog.dallog.common.fixtures.MemberFixtures; import com.allog.dallog.member.dto.MemberResponse; import com.allog.dallog.member.service.MemberService; import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; @@ -110,15 +111,15 @@ class SubscriptionServiceTest { @Test void 회원_정보를_기반으로_구독_정보를_조회한다() { // given - MemberResponse creator = memberService.save(MemberFixtures.CREATOR); - CategoryResponse categoryResponse1 = categoryService.save(creator.getId(), CATEGORY_CREATE_REQUEST_1); - CategoryResponse categoryResponse2 = categoryService.save(creator.getId(), CATEGORY_CREATE_REQUEST_2); - CategoryResponse categoryResponse3 = categoryService.save(creator.getId(), CATEGORY_CREATE_REQUEST_3); + MemberResponse 관리자 = memberService.save(관리자()); + CategoryResponse 공통_일정 = categoryService.save(관리자.getId(), 공통_일정_생성_요청); + CategoryResponse BE_일정 = categoryService.save(관리자.getId(), BE_일정_생성_요청); + CategoryResponse FE_일정 = categoryService.save(관리자.getId(), FE_일정_생성_요청); MemberResponse member = memberService.save(MEMBER); - subscriptionService.save(member.getId(), categoryResponse1.getId(), CREATE_REQUEST_RED); - subscriptionService.save(member.getId(), categoryResponse2.getId(), CREATE_REQUEST_BLUE); - subscriptionService.save(member.getId(), categoryResponse3.getId(), CREATE_REQUEST_YELLOW); + subscriptionService.save(member.getId(), 공통_일정.getId(), CREATE_REQUEST_RED); + subscriptionService.save(member.getId(), BE_일정.getId(), CREATE_REQUEST_BLUE); + subscriptionService.save(member.getId(), FE_일정.getId(), CREATE_REQUEST_YELLOW); // when SubscriptionsResponse subscriptionsResponse = subscriptionService.findByMemberId(member.getId()); @@ -131,32 +132,32 @@ class SubscriptionServiceTest { @Test void 구독_정보를_삭제한다() { // given - MemberResponse creator = memberService.save(MemberFixtures.CREATOR); - CategoryResponse categoryResponse1 = categoryService.save(creator.getId(), CATEGORY_CREATE_REQUEST_1); - CategoryResponse categoryResponse2 = categoryService.save(creator.getId(), CATEGORY_CREATE_REQUEST_2); - CategoryResponse categoryResponse3 = categoryService.save(creator.getId(), CATEGORY_CREATE_REQUEST_3); + MemberResponse 관리자 = memberService.save(관리자()); + CategoryResponse 공통_일정 = categoryService.save(관리자.getId(), 공통_일정_생성_요청); + CategoryResponse BE_일정 = categoryService.save(관리자.getId(), BE_일정_생성_요청); + CategoryResponse FE_일정 = categoryService.save(관리자.getId(), FE_일정_생성_요청); - MemberResponse member = memberService.save(MEMBER); - SubscriptionResponse subscriptionResponse = subscriptionService.save(member.getId(), categoryResponse1.getId(), + MemberResponse 후디 = memberService.save(후디()); + SubscriptionResponse subscriptionResponse = subscriptionService.save(후디.getId(), 공통_일정.getId(), CREATE_REQUEST_RED); - subscriptionService.save(member.getId(), categoryResponse2.getId(), CREATE_REQUEST_BLUE); - subscriptionService.save(member.getId(), categoryResponse3.getId(), CREATE_REQUEST_YELLOW); + subscriptionService.save(후디.getId(), BE_일정.getId(), CREATE_REQUEST_BLUE); + subscriptionService.save(후디.getId(), FE_일정.getId(), CREATE_REQUEST_YELLOW); // when - subscriptionService.deleteByIdAndMemberId(subscriptionResponse.getId(), member.getId()); + subscriptionService.deleteByIdAndMemberId(subscriptionResponse.getId(), 후디.getId()); // then - assertThat(subscriptionService.findByMemberId(member.getId()).getSubscriptions()).hasSize(2); + assertThat(subscriptionService.findByMemberId(후디.getId()).getSubscriptions()).hasSize(2); } @DisplayName("자신의 구독 정보가 아닌 구독을 삭제할 경우 예외를 던진다.") @Test void 자신의_구독_정보가_아닌_구독을_삭제할_경우_예외를_던진다() { // given - MemberResponse member = memberService.save(MEMBER); + MemberResponse 관리자 = memberService.save(관리자()); // when & then - assertThatThrownBy(() -> subscriptionService.deleteByIdAndMemberId(0L, member.getId())) + assertThatThrownBy(() -> subscriptionService.deleteByIdAndMemberId(0L, 관리자.getId())) .isInstanceOf(NoPermissionException.class); } } From cc7e1162e51b5de75365449f54c1c291723dd771 Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 26 Jul 2022 15:13:36 +0900 Subject: [PATCH 0325/1011] =?UTF-8?q?test:=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=ED=94=BD=EC=8A=A4=EC=B3=90=EB=A5=BC=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: hyeonic --- .../SubscriptionAcceptanceTest.java | 41 +++++++++------- .../common/fixtures/CategoryFixtures.java | 1 - .../common/fixtures/SubscriptionFixtures.java | 31 +++++++++--- .../SubscriptionRepositoryTest.java | 49 +++++++++---------- .../service/SubscriptionServiceTest.java | 18 +++---- 5 files changed, 80 insertions(+), 60 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java index c594d825..b7ec12e5 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java @@ -4,7 +4,11 @@ import static com.allog.dallog.acceptance.fixtures.CommonAcceptanceFixtures.상태코드_201이_반환된다; import static com.allog.dallog.common.fixtures.AuthFixtures.GOOGLE_PROVIDER; import static com.allog.dallog.common.fixtures.AuthFixtures.인증_코드; -import static com.allog.dallog.common.fixtures.SubscriptionFixtures.COLOR_RED; +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_생성_요청; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.빨간색; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.빨간색_구독_생성_요청; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @@ -32,14 +36,14 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { void 인증된_회원이_카테고리를_구독하면_201을_반환한다() { // given String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); - CategoryResponse categoryResponse = 새로운_카테고리를_등록한다(accessToken, "BE 공식일정"); + CategoryResponse 공통_일정 = 새로운_카테고리를_등록한다(accessToken, 공통_일정_생성_요청); // when ExtractableResponse response = RestAssured.given().log().all() .auth().oauth2(accessToken) .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(new SubscriptionCreateRequest(COLOR_RED)) - .when().post("/api/members/me/categories/{categoryId}/subscriptions", categoryResponse.getId()) + .body(빨간색_구독_생성_요청) + .when().post("/api/members/me/categories/{categoryId}/subscriptions", 공통_일정.getId()) .then().log().all() .statusCode(HttpStatus.CREATED.value()) .extract(); @@ -53,13 +57,13 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { void 인증된_회원이_구독_목록을_조회하면_200을_반환한다() { // given String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); - CategoryResponse categoryResponse1 = 새로운_카테고리를_등록한다(accessToken, "BE 일정"); - CategoryResponse categoryResponse2 = 새로운_카테고리를_등록한다(accessToken, "FE 일정"); - CategoryResponse categoryResponse3 = 새로운_카테고리를_등록한다(accessToken, "공통 일정"); + CategoryResponse 공통_일정 = 새로운_카테고리를_등록한다(accessToken, 공통_일정_생성_요청); + CategoryResponse BE_일정 = 새로운_카테고리를_등록한다(accessToken, BE_일정_생성_요청); + CategoryResponse FE_일정 = 새로운_카테고리를_등록한다(accessToken, FE_일정_생성_요청); - 카테고리를_구독한다(accessToken, categoryResponse1); - 카테고리를_구독한다(accessToken, categoryResponse2); - 카테고리를_구독한다(accessToken, categoryResponse3); + 카테고리를_구독한다(accessToken, 공통_일정); + 카테고리를_구독한다(accessToken, BE_일정); + 카테고리를_구독한다(accessToken, FE_일정); // when ExtractableResponse response = 구독_목록을_조회한다(accessToken); @@ -77,13 +81,13 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { void 구독을_취소할_경우_204를_반환한다() { // given String accessToken = 자체_토큰을_생성하고_토큰을_반환한다(GOOGLE_PROVIDER, 인증_코드); - CategoryResponse categoryResponse1 = 새로운_카테고리를_등록한다(accessToken, "BE 일정"); - CategoryResponse categoryResponse2 = 새로운_카테고리를_등록한다(accessToken, "FE 일정"); - CategoryResponse categoryResponse3 = 새로운_카테고리를_등록한다(accessToken, "공통 일정"); + CategoryResponse 공통_일정 = 새로운_카테고리를_등록한다(accessToken, 공통_일정_생성_요청); + CategoryResponse BE_일정 = 새로운_카테고리를_등록한다(accessToken, BE_일정_생성_요청); + CategoryResponse FE_일정 = 새로운_카테고리를_등록한다(accessToken, FE_일정_생성_요청); - SubscriptionResponse subscriptionResponse = 카테고리를_구독한다(accessToken, categoryResponse1); - 카테고리를_구독한다(accessToken, categoryResponse2); - 카테고리를_구독한다(accessToken, categoryResponse3); + SubscriptionResponse subscriptionResponse = 카테고리를_구독한다(accessToken, 공통_일정); + 카테고리를_구독한다(accessToken, BE_일정); + 카테고리를_구독한다(accessToken, FE_일정); // when ExtractableResponse response = RestAssured.given().log().all() @@ -98,8 +102,7 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { assertThat(response.statusCode()).isEqualTo(HttpStatus.NO_CONTENT.value()); } - private CategoryResponse 새로운_카테고리를_등록한다(final String accessToken, final String name) { - CategoryCreateRequest request = new CategoryCreateRequest(name); + private CategoryResponse 새로운_카테고리를_등록한다(final String accessToken, final CategoryCreateRequest request) { return RestAssured.given().log().all() .auth().oauth2(accessToken) .contentType(MediaType.APPLICATION_JSON_VALUE) @@ -114,7 +117,7 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { return RestAssured.given().log().all() .auth().oauth2(accessToken) .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(new SubscriptionCreateRequest(COLOR_RED)) + .body(new SubscriptionCreateRequest(빨간색)) .when().post("/api/members/me/categories/{categoryId}/subscriptions", categoryResponse.getId()) .then().log().all() .statusCode(HttpStatus.CREATED.value()) diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 9d0b49a9..8cf2556b 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -27,7 +27,6 @@ public class CategoryFixtures { public static final String 후디_JPA_스터디_이름 = "후디 JPA 스터디"; public static final CategoryCreateRequest 후디_JPA_스터디_생성_요청 = new CategoryCreateRequest(후디_JPA_스터디_이름); - public static Category 공통_일정(final Member creator) { return new Category(공통_일정_이름, creator); } diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java index 658b254b..922b4263 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java @@ -1,14 +1,33 @@ package com.allog.dallog.common.fixtures; +import com.allog.dallog.category.domain.Category; +import com.allog.dallog.member.domain.Member; +import com.allog.dallog.subscription.domain.Subscription; import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; public class SubscriptionFixtures { - public static final String COLOR_RED = "#FF0000"; - public static final String COLOR_BLUE = "#0000FF"; - public static final String COLOR_YELLOW = "#FFFF00"; + /* 빨간색 구독 */ + public static final String 빨간색 = "#FF0000"; + public static final SubscriptionCreateRequest 빨간색_구독_생성_요청 = new SubscriptionCreateRequest(빨간색); - public static final SubscriptionCreateRequest CREATE_REQUEST_RED = new SubscriptionCreateRequest(COLOR_RED); - public static final SubscriptionCreateRequest CREATE_REQUEST_BLUE = new SubscriptionCreateRequest(COLOR_BLUE); - public static final SubscriptionCreateRequest CREATE_REQUEST_YELLOW = new SubscriptionCreateRequest(COLOR_YELLOW); + /* 빨간색 구독 */ + public static final String 파란색 = "#0000FF"; + public static final SubscriptionCreateRequest 파란색_구독_생성_요청 = new SubscriptionCreateRequest(파란색); + + /* 빨간색 구독 */ + public static final String 노란색 = "#FFFF00"; + public static final SubscriptionCreateRequest 노란색_구독_생성_요청 = new SubscriptionCreateRequest(노란색); + + public static Subscription 빨간색_구독(final Member member, final Category category) { + return new Subscription(member, category, 빨간색); + } + + public static Subscription 파란색_구독(final Member member, final Category category) { + return new Subscription(member, category, 파란색); + } + + public static Subscription 노란색_구독(final Member member, final Category category) { + return new Subscription(member, category, 노란색); + } } diff --git a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java b/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java index fa1a7b58..b2d4907b 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java @@ -4,10 +4,10 @@ import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정; import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정; import static com.allog.dallog.common.fixtures.CategoryFixtures.관리자; -import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; -import static com.allog.dallog.common.fixtures.SubscriptionFixtures.COLOR_BLUE; -import static com.allog.dallog.common.fixtures.SubscriptionFixtures.COLOR_RED; -import static com.allog.dallog.common.fixtures.SubscriptionFixtures.COLOR_YELLOW; +import static com.allog.dallog.common.fixtures.CategoryFixtures.후디; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.노란색_구독; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.빨간색_구독; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.파란색_구독; import static org.assertj.core.api.Assertions.assertThat; import com.allog.dallog.category.domain.Category; @@ -41,21 +41,21 @@ class SubscriptionRepositoryTest { void 회원_정보를_기반으로_구독_정보를_조회한다() { // given Member 관리자 = memberRepository.save(관리자()); - Category category1 = categoryRepository.save(공통_일정(관리자)); - Category category2 = categoryRepository.save(BE_일정(관리자)); - Category category3 = categoryRepository.save(FE_일정(관리자)); + Category 공통_일정 = categoryRepository.save(공통_일정(관리자)); + Category BE_일정 = categoryRepository.save(BE_일정(관리자)); + Category FE_일정 = categoryRepository.save(FE_일정(관리자)); - Member member = memberRepository.save(MEMBER); - Subscription subscription1 = new Subscription(member, category1, COLOR_RED); - Subscription subscription2 = new Subscription(member, category2, COLOR_BLUE); - Subscription subscription3 = new Subscription(member, category3, COLOR_YELLOW); + Member 후디 = memberRepository.save(후디()); + Subscription 빨간색_구독 = 빨간색_구독(후디, 공통_일정); + Subscription 파란색_구독 = 파란색_구독(후디, BE_일정); + Subscription 노란색_구독 = 노란색_구독(후디, FE_일정); - subscriptionRepository.save(subscription1); - subscriptionRepository.save(subscription2); - subscriptionRepository.save(subscription3); + subscriptionRepository.save(빨간색_구독); + subscriptionRepository.save(파란색_구독); + subscriptionRepository.save(노란색_구독); // when - List subscriptions = subscriptionRepository.findByMemberId(member.getId()); + List subscriptions = subscriptionRepository.findByMemberId(후디.getId()); // then assertThat(subscriptions).hasSize(3); @@ -65,10 +65,10 @@ class SubscriptionRepositoryTest { @Test void 회원의_구독_정보가_존재하지_않는_경우_빈_리스트가_조회된다() { // given - Member member = memberRepository.save(MEMBER); + Member 관리자 = memberRepository.save(관리자()); // when - List subscriptions = subscriptionRepository.findByMemberId(member.getId()); + List subscriptions = subscriptionRepository.findByMemberId(관리자.getId()); // then assertThat(subscriptions).isEmpty(); @@ -78,16 +78,15 @@ class SubscriptionRepositoryTest { @Test void 회원의_특정_구독_정보_여부를_확인한다() { // given - Member creator = memberRepository.save(관리자()); - Category category1 = categoryRepository.save(공통_일정(creator)); - - Member member = memberRepository.save(MEMBER); - Subscription subscription1 = new Subscription(member, category1, COLOR_RED); + Member 관리자 = memberRepository.save(관리자()); + Category 공통_일정 = categoryRepository.save(공통_일정(관리자)); - subscriptionRepository.save(subscription1); + Member 후디 = memberRepository.save(후디()); + Subscription 빨간색_구독 = 빨간색_구독(후디, 공통_일정); + subscriptionRepository.save(빨간색_구독); // when - boolean actual = subscriptionRepository.existsByIdAndMemberId(subscription1.getId(), member.getId()); + boolean actual = subscriptionRepository.existsByIdAndMemberId(빨간색_구독.getId(), 후디.getId()); // then assertThat(actual).isTrue(); @@ -97,7 +96,7 @@ class SubscriptionRepositoryTest { @Test void 회원의_존재하지_않는_구독_정보_여부를_확인한다() { // given - Member member = memberRepository.save(MEMBER); + Member member = memberRepository.save(관리자()); // when boolean actual = subscriptionRepository.existsByIdAndMemberId(0L, member.getId()); diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java index 739d0af9..f2d55a1d 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -7,9 +7,9 @@ import static com.allog.dallog.common.fixtures.CategoryFixtures.관리자; import static com.allog.dallog.common.fixtures.CategoryFixtures.후디; import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; -import static com.allog.dallog.common.fixtures.SubscriptionFixtures.CREATE_REQUEST_BLUE; -import static com.allog.dallog.common.fixtures.SubscriptionFixtures.CREATE_REQUEST_RED; -import static com.allog.dallog.common.fixtures.SubscriptionFixtures.CREATE_REQUEST_YELLOW; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.노란색_구독_생성_요청; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.빨간색_구독_생성_요청; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.파란색_구독_생성_요청; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; @@ -117,9 +117,9 @@ class SubscriptionServiceTest { CategoryResponse FE_일정 = categoryService.save(관리자.getId(), FE_일정_생성_요청); MemberResponse member = memberService.save(MEMBER); - subscriptionService.save(member.getId(), 공통_일정.getId(), CREATE_REQUEST_RED); - subscriptionService.save(member.getId(), BE_일정.getId(), CREATE_REQUEST_BLUE); - subscriptionService.save(member.getId(), FE_일정.getId(), CREATE_REQUEST_YELLOW); + subscriptionService.save(member.getId(), 공통_일정.getId(), 빨간색_구독_생성_요청); + subscriptionService.save(member.getId(), BE_일정.getId(), 파란색_구독_생성_요청); + subscriptionService.save(member.getId(), FE_일정.getId(), 노란색_구독_생성_요청); // when SubscriptionsResponse subscriptionsResponse = subscriptionService.findByMemberId(member.getId()); @@ -139,9 +139,9 @@ class SubscriptionServiceTest { MemberResponse 후디 = memberService.save(후디()); SubscriptionResponse subscriptionResponse = subscriptionService.save(후디.getId(), 공통_일정.getId(), - CREATE_REQUEST_RED); - subscriptionService.save(후디.getId(), BE_일정.getId(), CREATE_REQUEST_BLUE); - subscriptionService.save(후디.getId(), FE_일정.getId(), CREATE_REQUEST_YELLOW); + 빨간색_구독_생성_요청); + subscriptionService.save(후디.getId(), BE_일정.getId(), 파란색_구독_생성_요청); + subscriptionService.save(후디.getId(), FE_일정.getId(), 노란색_구독_생성_요청); // when subscriptionService.deleteByIdAndMemberId(subscriptionResponse.getId(), 후디.getId()); From 6e6da4fc03edc026d3b28db48ab34db594371731 Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 26 Jul 2022 16:18:56 +0900 Subject: [PATCH 0326/1011] =?UTF-8?q?test:=20=EC=98=A4=ED=83=80=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: hyeonic --- .../allog/dallog/common/fixtures/SubscriptionFixtures.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java index 922b4263..a29d9c72 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java @@ -11,11 +11,11 @@ public class SubscriptionFixtures { public static final String 빨간색 = "#FF0000"; public static final SubscriptionCreateRequest 빨간색_구독_생성_요청 = new SubscriptionCreateRequest(빨간색); - /* 빨간색 구독 */ + /* 파란색 구독 */ public static final String 파란색 = "#0000FF"; public static final SubscriptionCreateRequest 파란색_구독_생성_요청 = new SubscriptionCreateRequest(파란색); - /* 빨간색 구독 */ + /* 노란색 구독 */ public static final String 노란색 = "#FFFF00"; public static final SubscriptionCreateRequest 노란색_구독_생성_요청 = new SubscriptionCreateRequest(노란색); From cc7fcce2f943e2dfd11dd919758c8556403bdafe Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 26 Jul 2022 16:29:30 +0900 Subject: [PATCH 0327/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=EB=A5=BC=5F=EA=B5=AC=EB=8F=85=ED=95=9C=EB=8B=A4=20?= =?UTF-8?q?=EB=A9=94=EC=86=8C=EB=93=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: hyeonic --- .../SubscriptionAcceptanceTest.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java index b7ec12e5..b84e94d1 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java @@ -7,7 +7,6 @@ import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_생성_요청; import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_생성_요청; import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_생성_요청; -import static com.allog.dallog.common.fixtures.SubscriptionFixtures.빨간색; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.빨간색_구독_생성_요청; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; @@ -61,9 +60,9 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { CategoryResponse BE_일정 = 새로운_카테고리를_등록한다(accessToken, BE_일정_생성_요청); CategoryResponse FE_일정 = 새로운_카테고리를_등록한다(accessToken, FE_일정_생성_요청); - 카테고리를_구독한다(accessToken, 공통_일정); - 카테고리를_구독한다(accessToken, BE_일정); - 카테고리를_구독한다(accessToken, FE_일정); + 카테고리를_구독한다(accessToken, 공통_일정.getId(), 빨간색_구독_생성_요청); + 카테고리를_구독한다(accessToken, BE_일정.getId(), 빨간색_구독_생성_요청); + 카테고리를_구독한다(accessToken, FE_일정.getId(), 빨간색_구독_생성_요청); // when ExtractableResponse response = 구독_목록을_조회한다(accessToken); @@ -85,9 +84,9 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { CategoryResponse BE_일정 = 새로운_카테고리를_등록한다(accessToken, BE_일정_생성_요청); CategoryResponse FE_일정 = 새로운_카테고리를_등록한다(accessToken, FE_일정_생성_요청); - SubscriptionResponse subscriptionResponse = 카테고리를_구독한다(accessToken, 공통_일정); - 카테고리를_구독한다(accessToken, BE_일정); - 카테고리를_구독한다(accessToken, FE_일정); + SubscriptionResponse subscriptionResponse = 카테고리를_구독한다(accessToken, 공통_일정.getId(), 빨간색_구독_생성_요청); + 카테고리를_구독한다(accessToken, BE_일정.getId(), 빨간색_구독_생성_요청); + 카테고리를_구독한다(accessToken, FE_일정.getId(), 빨간색_구독_생성_요청); // when ExtractableResponse response = RestAssured.given().log().all() @@ -113,12 +112,13 @@ public class SubscriptionAcceptanceTest extends AcceptanceTest { .as(CategoryResponse.class); } - private SubscriptionResponse 카테고리를_구독한다(final String accessToken, final CategoryResponse categoryResponse) { + private SubscriptionResponse 카테고리를_구독한다(final String accessToken, final Long categoryId, + final SubscriptionCreateRequest request) { return RestAssured.given().log().all() .auth().oauth2(accessToken) .contentType(MediaType.APPLICATION_JSON_VALUE) - .body(new SubscriptionCreateRequest(빨간색)) - .when().post("/api/members/me/categories/{categoryId}/subscriptions", categoryResponse.getId()) + .body(request) + .when().post("/api/members/me/categories/{categoryId}/subscriptions", categoryId) .then().log().all() .statusCode(HttpStatus.CREATED.value()) .extract() From 7794027b9e2297145378d7b4ae23b4c58264c463 Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 26 Jul 2022 16:50:56 +0900 Subject: [PATCH 0328/1011] =?UTF-8?q?test:=20Member=20=ED=94=BD=EC=8A=A4?= =?UTF-8?q?=EC=B2=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: hyeonic --- .../domain/CategoryRepositoryTest.java | 4 +- .../dallog/category/domain/CategoryTest.java | 8 +-- .../category/service/CategoryServiceTest.java | 4 +- .../common/fixtures/CategoryFixtures.java | 16 +----- .../common/fixtures/MemberFixtures.java | 37 ++++++++++--- .../subscription/domain/SubscriptionTest.java | 2 +- .../SubscriptionRepositoryTest.java | 4 +- .../service/SubscriptionServiceTest.java | 52 +++++++++---------- 8 files changed, 67 insertions(+), 60 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java index 92637b5b..d0436df5 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java @@ -6,11 +6,11 @@ import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_이름; import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정; import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_이름; -import static com.allog.dallog.common.fixtures.CategoryFixtures.관리자; import static com.allog.dallog.common.fixtures.CategoryFixtures.매트_아고라; import static com.allog.dallog.common.fixtures.CategoryFixtures.매트_아고라_이름; -import static com.allog.dallog.common.fixtures.CategoryFixtures.후디; import static com.allog.dallog.common.fixtures.CategoryFixtures.후디_JPA_스터디; +import static com.allog.dallog.common.fixtures.MemberFixtures.관리자; +import static com.allog.dallog.common.fixtures.MemberFixtures.후디; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java b/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java index 9045507c..6f2f58f8 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java +++ b/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java @@ -1,6 +1,6 @@ package com.allog.dallog.category.domain; -import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; +import static com.allog.dallog.common.fixtures.MemberFixtures.후디; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @@ -19,7 +19,7 @@ class CategoryTest { String name = "BE 공식일정"; // when & then - assertDoesNotThrow(() -> new Category(name, MEMBER)); + assertDoesNotThrow(() -> new Category(name, 후디())); } @DisplayName("카테고리 이름이 공백인 경우 예외를 던진다.") @@ -29,7 +29,7 @@ class CategoryTest { String name = ""; // when & then - assertThatThrownBy(() -> new Category(name, MEMBER)) + assertThatThrownBy(() -> new Category(name, 후디())) .isInstanceOf(InvalidCategoryException.class); } @@ -39,7 +39,7 @@ class CategoryTest { "알록달록 알록달록 알록달록 알록달록 알록달록 알록달록 카테고리"}) void 카테고리_이름의_길이가_20을_초과하는_경우_예외를_던진다(final String name) { // given & when & then - assertThatThrownBy(() -> new Category(name, MEMBER)) + assertThatThrownBy(() -> new Category(name, 후디())) .isInstanceOf(InvalidCategoryException.class); } } diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java index 5333ed81..83c9f3b0 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java @@ -5,11 +5,11 @@ import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_이름; import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_생성_요청; import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_이름; -import static com.allog.dallog.common.fixtures.CategoryFixtures.관리자; -import static com.allog.dallog.common.fixtures.CategoryFixtures.매트; import static com.allog.dallog.common.fixtures.CategoryFixtures.매트_아고라_생성_요청; import static com.allog.dallog.common.fixtures.CategoryFixtures.매트_아고라_이름; import static com.allog.dallog.common.fixtures.CategoryFixtures.후디_JPA_스터디_생성_요청; +import static com.allog.dallog.common.fixtures.MemberFixtures.관리자; +import static com.allog.dallog.common.fixtures.MemberFixtures.매트; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 8cf2556b..8d3e9e61 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -3,7 +3,6 @@ import com.allog.dallog.category.domain.Category; import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.domain.SocialType; public class CategoryFixtures { @@ -16,7 +15,7 @@ public class CategoryFixtures { public static final CategoryCreateRequest BE_일정_생성_요청 = new CategoryCreateRequest(BE_일정_이름); /* FE 일정 카테고리 */ - public static final String FE_일정_이름 = "BE 일정"; + public static final String FE_일정_이름 = "FE 일정"; public static final CategoryCreateRequest FE_일정_생성_요청 = new CategoryCreateRequest(FE_일정_이름); /* 매트 아고라 카테고리 */ @@ -46,17 +45,4 @@ public class CategoryFixtures { public static Category 후디_JPA_스터디(final Member creator) { return new Category(후디_JPA_스터디_이름, creator); } - - /* 임시 멤버 */ - public static Member 후디() { - return new Member("devhudi@gmail.com", "/image.png", "후디", SocialType.GOOGLE); - } - - public static Member 매트() { - return new Member("dev.hyeonic@gmail.com", "/image2.png", "매트", SocialType.GOOGLE); - } - - public static Member 관리자() { - return new Member("dallog.admin@gmail.com", "/image3.png", "관리자", SocialType.GOOGLE); - } } diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java index 6eee6e6e..ef572790 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java @@ -5,23 +5,48 @@ public class MemberFixtures { + /* 관리자 */ + public static final String 관리자_이메일 = "dallog.admin@gmail.com"; + public static final String 관리자_프로필 = "/admin.png"; + public static final String 관리자_이름 = "관리자"; + + /* 파랑 */ public static final String 파랑_이메일 = "parang@email.com"; public static final String 파랑_프로필 = "/parang.png"; public static final String 파랑_이름 = "파랑"; + /* 리버 */ public static final String 리버_이메일 = "leaver@email.com"; public static final String 리버_프로필 = "/leaver.png"; public static final String 리버_이름 = "리버"; - public static final String EMAIL = "example@email.com"; - public static final String PROFILE_IMAGE_URI = "/image.png"; - public static final String DISPLAY_NAME = "example"; + /* 후디 */ + public static final String 후디_이메일 = "devhudi@gmail.com"; + public static final String 후디_프로필 = "/hudi.png"; + public static final String 후디_이름 = "후디"; + + /* 매트 */ + public static final String 매트_이메일 = "dev.hyeonic@gmail.com"; + public static final String 매트_프로필 = "/mat.png"; + public static final String 매트_이름 = "매트"; - public static final Member MEMBER = new Member(EMAIL, PROFILE_IMAGE_URI, DISPLAY_NAME, SocialType.GOOGLE); - public static final Member CREATOR = new Member("creator@email.com", "/image.png", "creator", SocialType.GOOGLE); - public static final Member CREATOR2 = new Member("creator2@eamil.com", "/image.png", "creator2", SocialType.GOOGLE); + public static Member 관리자() { + return new Member(관리자_이메일, 관리자_프로필, 관리자_이름, SocialType.GOOGLE); + } public static Member 파랑() { return new Member(파랑_이메일, 파랑_프로필, 파랑_이름, SocialType.GOOGLE); } + + public static Member 리버() { + return new Member(리버_이메일, 리버_프로필, 리버_이름, SocialType.GOOGLE); + } + + public static Member 후디() { + return new Member(후디_이메일, 후디_프로필, 후디_이름, SocialType.GOOGLE); + } + + public static Member 매트() { + return new Member(매트_이메일, 매트_프로필, 매트_이름, SocialType.GOOGLE); + } } diff --git a/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java b/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java index 575f2da2..90ac551c 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java @@ -1,7 +1,7 @@ package com.allog.dallog.subscription.domain; -import static com.allog.dallog.common.fixtures.CategoryFixtures.후디; import static com.allog.dallog.common.fixtures.CategoryFixtures.후디_JPA_스터디; +import static com.allog.dallog.common.fixtures.MemberFixtures.후디; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; diff --git a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java b/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java index b2d4907b..cb85b9f8 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java @@ -3,8 +3,8 @@ import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정; import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정; import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정; -import static com.allog.dallog.common.fixtures.CategoryFixtures.관리자; -import static com.allog.dallog.common.fixtures.CategoryFixtures.후디; +import static com.allog.dallog.common.fixtures.MemberFixtures.관리자; +import static com.allog.dallog.common.fixtures.MemberFixtures.후디; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.노란색_구독; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.빨간색_구독; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.파란색_구독; diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java index f2d55a1d..502c9444 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java @@ -2,12 +2,13 @@ import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_이름; import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_생성_요청; import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_생성_요청; -import static com.allog.dallog.common.fixtures.CategoryFixtures.관리자; -import static com.allog.dallog.common.fixtures.CategoryFixtures.후디; -import static com.allog.dallog.common.fixtures.MemberFixtures.MEMBER; +import static com.allog.dallog.common.fixtures.MemberFixtures.관리자; +import static com.allog.dallog.common.fixtures.MemberFixtures.후디; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.노란색_구독_생성_요청; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.빨간색; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.빨간색_구독_생성_요청; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.파란색_구독_생성_요청; import static org.assertj.core.api.Assertions.assertThat; @@ -15,7 +16,6 @@ import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.auth.exception.NoPermissionException; -import com.allog.dallog.category.dto.request.CategoryCreateRequest; import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.category.service.CategoryService; import com.allog.dallog.member.dto.MemberResponse; @@ -50,18 +50,16 @@ class SubscriptionServiceTest { @Test void 새로운_구독을_생성한다() { // given - MemberResponse member = memberService.save(MEMBER); - CategoryResponse categoryResponse = categoryService.save(member.getId(), new CategoryCreateRequest("BE 일정")); - String color = "#ffffff"; + MemberResponse 후디 = memberService.save(후디()); + CategoryResponse BE_일정 = categoryService.save(후디.getId(), BE_일정_생성_요청); // when - SubscriptionResponse response = subscriptionService.save(member.getId(), categoryResponse.getId(), - new SubscriptionCreateRequest(color)); + SubscriptionResponse response = subscriptionService.save(후디.getId(), BE_일정.getId(), 빨간색_구독_생성_요청); // then assertAll(() -> { - assertThat(response.getCategory().getName()).isEqualTo("BE 일정"); - assertThat(response.getColor()).isEqualTo(color); + assertThat(response.getCategory().getName()).isEqualTo(BE_일정_이름); + assertThat(response.getColor()).isEqualTo(빨간색); }); } @@ -70,11 +68,11 @@ class SubscriptionServiceTest { @ValueSource(strings = {"#111", "#1111", "#11111", "123456", "#**1234", "##12345", "334172#"}) void 색_정보_형식이_잘못된_경우_예외를_던진다(final String color) { // given - MemberResponse member = memberService.save(MEMBER); - CategoryResponse categoryResponse = categoryService.save(member.getId(), new CategoryCreateRequest("BE 일정")); + MemberResponse 후디 = memberService.save(후디()); + CategoryResponse categoryResponse = categoryService.save(후디.getId(), BE_일정_생성_요청); // when & then - assertThatThrownBy(() -> subscriptionService.save(member.getId(), categoryResponse.getId(), + assertThatThrownBy(() -> subscriptionService.save(후디.getId(), categoryResponse.getId(), new SubscriptionCreateRequest(color))).isInstanceOf(InvalidSubscriptionException.class); } @@ -82,20 +80,18 @@ class SubscriptionServiceTest { @Test void 구독_id를_기반으로_단건_조회한다() { // given - MemberResponse member = memberService.save(MEMBER); - CategoryResponse categoryResponse = categoryService.save(member.getId(), new CategoryCreateRequest("BE 일정")); - String color = "#ffffff"; - SubscriptionResponse subscriptionResponse = subscriptionService.save(member.getId(), categoryResponse.getId(), - new SubscriptionCreateRequest(color)); + MemberResponse 후디 = memberService.save(후디()); + CategoryResponse BE_일정 = categoryService.save(후디.getId(), BE_일정_생성_요청); + SubscriptionResponse 빨간색_구독 = subscriptionService.save(후디.getId(), BE_일정.getId(), 빨간색_구독_생성_요청); // when - SubscriptionResponse foundResponse = subscriptionService.findById(subscriptionResponse.getId()); + SubscriptionResponse foundResponse = subscriptionService.findById(빨간색_구독.getId()); // then assertAll(() -> { - assertThat(foundResponse.getId()).isEqualTo(subscriptionResponse.getId()); - assertThat(foundResponse.getCategory().getId()).isEqualTo(categoryResponse.getId()); - assertThat(foundResponse.getColor()).isEqualTo(color); + assertThat(foundResponse.getId()).isEqualTo(빨간색_구독.getId()); + assertThat(foundResponse.getCategory().getId()).isEqualTo(BE_일정.getId()); + assertThat(foundResponse.getColor()).isEqualTo(빨간색); }); } @@ -116,13 +112,13 @@ class SubscriptionServiceTest { CategoryResponse BE_일정 = categoryService.save(관리자.getId(), BE_일정_생성_요청); CategoryResponse FE_일정 = categoryService.save(관리자.getId(), FE_일정_생성_요청); - MemberResponse member = memberService.save(MEMBER); - subscriptionService.save(member.getId(), 공통_일정.getId(), 빨간색_구독_생성_요청); - subscriptionService.save(member.getId(), BE_일정.getId(), 파란색_구독_생성_요청); - subscriptionService.save(member.getId(), FE_일정.getId(), 노란색_구독_생성_요청); + MemberResponse 후디 = memberService.save(후디()); + subscriptionService.save(후디.getId(), 공통_일정.getId(), 빨간색_구독_생성_요청); + subscriptionService.save(후디.getId(), BE_일정.getId(), 파란색_구독_생성_요청); + subscriptionService.save(후디.getId(), FE_일정.getId(), 노란색_구독_생성_요청); // when - SubscriptionsResponse subscriptionsResponse = subscriptionService.findByMemberId(member.getId()); + SubscriptionsResponse subscriptionsResponse = subscriptionService.findByMemberId(후디.getId()); // then assertThat(subscriptionsResponse.getSubscriptions()).hasSize(3); From b5e0bf18dade0f22f88d8efd0710a44aeb68ef55 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Tue, 26 Jul 2022 17:26:48 +0900 Subject: [PATCH 0329/1011] =?UTF-8?q?refactor:=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/application}/AuthService.java | 15 +++++------- .../auth/application}/JwtTokenProvider.java | 4 ++-- .../auth/application}/OAuthClient.java | 4 ++-- .../auth/application}/OAuthUri.java | 2 +- .../{ => domain}/auth/dto/LoginMember.java | 2 +- .../{ => domain}/auth/dto/OAuthMember.java | 2 +- .../auth/dto/OAuthUriResponse.java | 2 +- .../{ => domain}/auth/dto/TokenRequest.java | 2 +- .../{ => domain}/auth/dto/TokenResponse.java | 2 +- .../EmptyAuthorizationHeaderException.java | 2 +- .../auth/exception/InvalidTokenException.java | 2 +- .../auth/exception/NoPermissionException.java | 2 +- .../auth/presentation}/AuthController.java | 10 ++++---- .../AuthenticationPrincipal.java | 2 +- ...thenticationPrincipalArgumentResolver.java | 6 ++--- .../presentation}/AuthorizationExtractor.java | 6 ++--- .../application}/CategoryService.java | 24 +++++++++---------- .../category/domain/Category.java | 6 ++--- .../category/domain/CategoryRepository.java | 2 +- .../dto/request/CategoryCreateRequest.java | 2 +- .../dto/request/CategoryUpdateRequest.java | 2 +- .../dto/response/CategoriesResponse.java | 4 ++-- .../dto/response/CategoryResponse.java | 6 ++--- .../exception/InvalidCategoryException.java | 2 +- .../exception/NoSuchCategoryException.java | 2 +- .../presentation}/CategoryController.java | 16 ++++++------- .../member/application}/MemberService.java | 10 ++++---- .../{ => domain}/member/domain/Member.java | 4 ++-- .../member/domain/MemberRepository.java | 2 +- .../member/domain/SocialType.java | 2 +- .../member/dto/MemberResponse.java | 6 ++--- .../exception/InvalidMemberException.java | 2 +- .../exception/NoSuchMemberException.java | 2 +- .../presentation}/MemberController.java | 10 ++++---- .../application}/ScheduleService.java | 10 ++++---- .../{ => domain}/schedule/domain/Period.java | 4 ++-- .../schedule/domain/Schedule.java | 4 ++-- .../schedule/domain/ScheduleRepository.java | 6 ++--- .../dto/request/ScheduleCreateRequest.java | 4 ++-- .../dto/response/ScheduleResponse.java | 4 ++-- .../dto/response/SchedulesResponse.java | 2 +- .../exception/InvalidScheduleException.java | 2 +- .../presentation}/ScheduleController.java | 10 ++++---- .../application}/SubscriptionService.java | 24 +++++++++---------- .../subscription/domain/Subscription.java | 8 +++---- .../request/SubscriptionCreateRequest.java | 2 +- .../dto/response/SubscriptionResponse.java | 6 ++--- .../dto/response/SubscriptionsResponse.java | 2 +- .../InvalidSubscriptionException.java | 2 +- .../NoSuchSubscriptionException.java | 2 +- .../presentation}/SubscriptionController.java | 14 +++++------ .../repository/SubscriptionRepository.java | 4 ++-- .../allog/dallog/global/config/WebConfig.java | 2 +- .../oauth/client/GoogleOAuthClient.java | 4 ++-- .../oauth/uri/GoogleOAuthUri.java | 2 +- .../dallog/acceptance/AuthAcceptanceTest.java | 4 ++-- .../acceptance/CategoryAcceptanceTest.java | 4 ++-- .../acceptance/MemberAcceptanceTest.java | 2 +- .../SubscriptionAcceptanceTest.java | 10 ++++---- .../fixtures/AuthAcceptanceFixtures.java | 4 ++-- .../fixtures/CategoryAcceptanceFixtures.java | 4 ++-- .../dallog/common/config/TestConfig.java | 2 +- .../common/fixtures/CategoryFixtures.java | 6 ++--- .../common/fixtures/MemberFixtures.java | 4 ++-- .../common/fixtures/SubscriptionFixtures.java | 8 +++---- .../auth/application}/AuthServiceTest.java | 8 +++---- .../application}/JwtTokenProviderTest.java | 4 ++-- .../application}/CategoryServiceTest.java | 22 ++++++++--------- .../domain/CategoryRepositoryTest.java | 8 ++++--- .../category/domain/CategoryTest.java | 5 ++-- .../application}/MemberServiceTest.java | 8 +++---- .../member/domain/MemberRepositoryTest.java | 4 +++- .../member/domain/MemberTest.java | 6 +++-- .../application}/ScheduleServiceTest.java | 8 +++---- .../schedule/domain/PeriodTest.java | 5 ++-- .../domain/ScheduleRepositoryTest.java | 4 +++- .../schedule/domain/ScheduleTest.java | 5 ++-- .../presentation}/ScheduleControllerTest.java | 10 ++++---- .../application}/SubscriptionServiceTest.java | 22 ++++++++--------- .../subscription/domain/SubscriptionTest.java | 9 +++---- .../SubscriptionRepositoryTest.java | 13 +++++----- .../oauth/client/StubOAuthClient.java | 4 ++-- 82 files changed, 245 insertions(+), 235 deletions(-) rename backend/src/main/java/com/allog/dallog/{auth/service => domain/auth/application}/AuthService.java (82%) rename backend/src/main/java/com/allog/dallog/{auth/support => domain/auth/application}/JwtTokenProvider.java (94%) rename backend/src/main/java/com/allog/dallog/{auth/support => domain/auth/application}/OAuthClient.java (51%) rename backend/src/main/java/com/allog/dallog/{auth/support => domain/auth/application}/OAuthUri.java (60%) rename backend/src/main/java/com/allog/dallog/{ => domain}/auth/dto/LoginMember.java (83%) rename backend/src/main/java/com/allog/dallog/{ => domain}/auth/dto/OAuthMember.java (93%) rename backend/src/main/java/com/allog/dallog/{ => domain}/auth/dto/OAuthUriResponse.java (88%) rename backend/src/main/java/com/allog/dallog/{ => domain}/auth/dto/TokenRequest.java (84%) rename backend/src/main/java/com/allog/dallog/{ => domain}/auth/dto/TokenResponse.java (86%) rename backend/src/main/java/com/allog/dallog/{ => domain}/auth/exception/EmptyAuthorizationHeaderException.java (86%) rename backend/src/main/java/com/allog/dallog/{ => domain}/auth/exception/InvalidTokenException.java (83%) rename backend/src/main/java/com/allog/dallog/{ => domain}/auth/exception/NoPermissionException.java (83%) rename backend/src/main/java/com/allog/dallog/{auth/controller => domain/auth/presentation}/AuthController.java (82%) rename backend/src/main/java/com/allog/dallog/{auth/support => domain/auth/presentation}/AuthenticationPrincipal.java (84%) rename backend/src/main/java/com/allog/dallog/{auth/support => domain/auth/presentation}/AuthenticationPrincipalArgumentResolver.java (89%) rename backend/src/main/java/com/allog/dallog/{auth/support => domain/auth/presentation}/AuthorizationExtractor.java (81%) rename backend/src/main/java/com/allog/dallog/{category/service => domain/category/application}/CategoryService.java (77%) rename backend/src/main/java/com/allog/dallog/{ => domain}/category/domain/Category.java (90%) rename backend/src/main/java/com/allog/dallog/{ => domain}/category/domain/CategoryRepository.java (90%) rename backend/src/main/java/com/allog/dallog/{ => domain}/category/dto/request/CategoryCreateRequest.java (85%) rename backend/src/main/java/com/allog/dallog/{ => domain}/category/dto/request/CategoryUpdateRequest.java (85%) rename backend/src/main/java/com/allog/dallog/{ => domain}/category/dto/response/CategoriesResponse.java (86%) rename backend/src/main/java/com/allog/dallog/{ => domain}/category/dto/response/CategoryResponse.java (84%) rename backend/src/main/java/com/allog/dallog/{ => domain}/category/exception/InvalidCategoryException.java (83%) rename backend/src/main/java/com/allog/dallog/{ => domain}/category/exception/NoSuchCategoryException.java (83%) rename backend/src/main/java/com/allog/dallog/{category/controller => domain/category/presentation}/CategoryController.java (83%) rename backend/src/main/java/com/allog/dallog/{member/service => domain/member/application}/MemberService.java (80%) rename backend/src/main/java/com/allog/dallog/{ => domain}/member/domain/Member.java (95%) rename backend/src/main/java/com/allog/dallog/{ => domain}/member/domain/MemberRepository.java (85%) rename backend/src/main/java/com/allog/dallog/{ => domain}/member/domain/SocialType.java (51%) rename backend/src/main/java/com/allog/dallog/{ => domain}/member/dto/MemberResponse.java (87%) rename backend/src/main/java/com/allog/dallog/{ => domain}/member/exception/InvalidMemberException.java (83%) rename backend/src/main/java/com/allog/dallog/{ => domain}/member/exception/NoSuchMemberException.java (83%) rename backend/src/main/java/com/allog/dallog/{member/controller => domain/member/presentation}/MemberController.java (70%) rename backend/src/main/java/com/allog/dallog/{schedule/service => domain/schedule/application}/ScheduleService.java (79%) rename backend/src/main/java/com/allog/dallog/{ => domain}/schedule/domain/Period.java (92%) rename backend/src/main/java/com/allog/dallog/{ => domain}/schedule/domain/Schedule.java (94%) rename backend/src/main/java/com/allog/dallog/{ => domain}/schedule/domain/ScheduleRepository.java (67%) rename backend/src/main/java/com/allog/dallog/{ => domain}/schedule/dto/request/ScheduleCreateRequest.java (91%) rename backend/src/main/java/com/allog/dallog/{ => domain}/schedule/dto/response/ScheduleResponse.java (91%) rename backend/src/main/java/com/allog/dallog/{ => domain}/schedule/dto/response/SchedulesResponse.java (86%) rename backend/src/main/java/com/allog/dallog/{ => domain}/schedule/exception/InvalidScheduleException.java (82%) rename backend/src/main/java/com/allog/dallog/{schedule/controller => domain/schedule/presentation}/ScheduleController.java (80%) rename backend/src/main/java/com/allog/dallog/{subscription/service => domain/subscription/application}/SubscriptionService.java (72%) rename backend/src/main/java/com/allog/dallog/{ => domain}/subscription/domain/Subscription.java (88%) rename backend/src/main/java/com/allog/dallog/{ => domain}/subscription/dto/request/SubscriptionCreateRequest.java (82%) rename backend/src/main/java/com/allog/dallog/{ => domain}/subscription/dto/response/SubscriptionResponse.java (79%) rename backend/src/main/java/com/allog/dallog/{ => domain}/subscription/dto/response/SubscriptionsResponse.java (86%) rename backend/src/main/java/com/allog/dallog/{ => domain}/subscription/exception/InvalidSubscriptionException.java (83%) rename backend/src/main/java/com/allog/dallog/{ => domain}/subscription/exception/NoSuchSubscriptionException.java (83%) rename backend/src/main/java/com/allog/dallog/{subscription/controller => domain/subscription/presentation}/SubscriptionController.java (80%) rename backend/src/main/java/com/allog/dallog/{ => domain}/subscription/repository/SubscriptionRepository.java (75%) rename backend/src/test/java/com/allog/dallog/{auth/service => domain/auth/application}/AuthServiceTest.java (92%) rename backend/src/test/java/com/allog/dallog/{auth/support => domain/auth/application}/JwtTokenProviderTest.java (94%) rename backend/src/test/java/com/allog/dallog/{category/service => domain/category/application}/CategoryServiceTest.java (91%) rename backend/src/test/java/com/allog/dallog/{ => domain}/category/domain/CategoryRepositoryTest.java (95%) rename backend/src/test/java/com/allog/dallog/{ => domain}/category/domain/CategoryTest.java (89%) rename backend/src/test/java/com/allog/dallog/{member/service => domain/member/application}/MemberServiceTest.java (92%) rename backend/src/test/java/com/allog/dallog/{ => domain}/member/domain/MemberRepositoryTest.java (89%) rename backend/src/test/java/com/allog/dallog/{ => domain}/member/domain/MemberTest.java (89%) rename backend/src/test/java/com/allog/dallog/{schedule/service => domain/schedule/application}/ScheduleServiceTest.java (93%) rename backend/src/test/java/com/allog/dallog/{ => domain}/schedule/domain/PeriodTest.java (79%) rename backend/src/test/java/com/allog/dallog/{ => domain}/schedule/domain/ScheduleRepositoryTest.java (97%) rename backend/src/test/java/com/allog/dallog/{ => domain}/schedule/domain/ScheduleTest.java (93%) rename backend/src/test/java/com/allog/dallog/{schedule/controller => domain/schedule/presentation}/ScheduleControllerTest.java (92%) rename backend/src/test/java/com/allog/dallog/{subscription/service => domain/subscription/application}/SubscriptionServiceTest.java (89%) rename backend/src/test/java/com/allog/dallog/{ => domain}/subscription/domain/SubscriptionTest.java (82%) rename backend/src/test/java/com/allog/dallog/{ => domain}/subscription/repository/SubscriptionRepositoryTest.java (90%) diff --git a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java b/backend/src/main/java/com/allog/dallog/domain/auth/application/AuthService.java similarity index 82% rename from backend/src/main/java/com/allog/dallog/auth/service/AuthService.java rename to backend/src/main/java/com/allog/dallog/domain/auth/application/AuthService.java index 9de17af6..d16932db 100644 --- a/backend/src/main/java/com/allog/dallog/auth/service/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/application/AuthService.java @@ -1,13 +1,10 @@ -package com.allog.dallog.auth.service; +package com.allog.dallog.domain.auth.application; -import com.allog.dallog.auth.dto.OAuthMember; -import com.allog.dallog.auth.dto.TokenResponse; -import com.allog.dallog.auth.support.JwtTokenProvider; -import com.allog.dallog.auth.support.OAuthClient; -import com.allog.dallog.auth.support.OAuthUri; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.domain.SocialType; -import com.allog.dallog.member.service.MemberService; +import com.allog.dallog.domain.auth.dto.OAuthMember; +import com.allog.dallog.domain.auth.dto.TokenResponse; +import com.allog.dallog.domain.member.application.MemberService; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.member.domain.SocialType; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java b/backend/src/main/java/com/allog/dallog/domain/auth/application/JwtTokenProvider.java similarity index 94% rename from backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java rename to backend/src/main/java/com/allog/dallog/domain/auth/application/JwtTokenProvider.java index df31dbb3..80096d17 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/JwtTokenProvider.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/application/JwtTokenProvider.java @@ -1,6 +1,6 @@ -package com.allog.dallog.auth.support; +package com.allog.dallog.domain.auth.application; -import com.allog.dallog.auth.exception.InvalidTokenException; +import com.allog.dallog.domain.auth.exception.InvalidTokenException; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.JwtException; diff --git a/backend/src/main/java/com/allog/dallog/auth/support/OAuthClient.java b/backend/src/main/java/com/allog/dallog/domain/auth/application/OAuthClient.java similarity index 51% rename from backend/src/main/java/com/allog/dallog/auth/support/OAuthClient.java rename to backend/src/main/java/com/allog/dallog/domain/auth/application/OAuthClient.java index ac718657..e7ecac33 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/OAuthClient.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/application/OAuthClient.java @@ -1,6 +1,6 @@ -package com.allog.dallog.auth.support; +package com.allog.dallog.domain.auth.application; -import com.allog.dallog.auth.dto.OAuthMember; +import com.allog.dallog.domain.auth.dto.OAuthMember; @FunctionalInterface public interface OAuthClient { diff --git a/backend/src/main/java/com/allog/dallog/auth/support/OAuthUri.java b/backend/src/main/java/com/allog/dallog/domain/auth/application/OAuthUri.java similarity index 60% rename from backend/src/main/java/com/allog/dallog/auth/support/OAuthUri.java rename to backend/src/main/java/com/allog/dallog/domain/auth/application/OAuthUri.java index 769c99d8..b229ea6d 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/OAuthUri.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/application/OAuthUri.java @@ -1,4 +1,4 @@ -package com.allog.dallog.auth.support; +package com.allog.dallog.domain.auth.application; @FunctionalInterface public interface OAuthUri { diff --git a/backend/src/main/java/com/allog/dallog/auth/dto/LoginMember.java b/backend/src/main/java/com/allog/dallog/domain/auth/dto/LoginMember.java similarity index 83% rename from backend/src/main/java/com/allog/dallog/auth/dto/LoginMember.java rename to backend/src/main/java/com/allog/dallog/domain/auth/dto/LoginMember.java index 93eb6227..c414adca 100644 --- a/backend/src/main/java/com/allog/dallog/auth/dto/LoginMember.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/dto/LoginMember.java @@ -1,4 +1,4 @@ -package com.allog.dallog.auth.dto; +package com.allog.dallog.domain.auth.dto; public class LoginMember { diff --git a/backend/src/main/java/com/allog/dallog/auth/dto/OAuthMember.java b/backend/src/main/java/com/allog/dallog/domain/auth/dto/OAuthMember.java similarity index 93% rename from backend/src/main/java/com/allog/dallog/auth/dto/OAuthMember.java rename to backend/src/main/java/com/allog/dallog/domain/auth/dto/OAuthMember.java index be09ce6b..e0c487d1 100644 --- a/backend/src/main/java/com/allog/dallog/auth/dto/OAuthMember.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/dto/OAuthMember.java @@ -1,4 +1,4 @@ -package com.allog.dallog.auth.dto; +package com.allog.dallog.domain.auth.dto; public class OAuthMember { diff --git a/backend/src/main/java/com/allog/dallog/auth/dto/OAuthUriResponse.java b/backend/src/main/java/com/allog/dallog/domain/auth/dto/OAuthUriResponse.java similarity index 88% rename from backend/src/main/java/com/allog/dallog/auth/dto/OAuthUriResponse.java rename to backend/src/main/java/com/allog/dallog/domain/auth/dto/OAuthUriResponse.java index c318507e..68aaff05 100644 --- a/backend/src/main/java/com/allog/dallog/auth/dto/OAuthUriResponse.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/dto/OAuthUriResponse.java @@ -1,4 +1,4 @@ -package com.allog.dallog.auth.dto; +package com.allog.dallog.domain.auth.dto; // OAuth 인증 URI(소셜 로그인 링크)를 전달하는 DTO public class OAuthUriResponse { diff --git a/backend/src/main/java/com/allog/dallog/auth/dto/TokenRequest.java b/backend/src/main/java/com/allog/dallog/domain/auth/dto/TokenRequest.java similarity index 84% rename from backend/src/main/java/com/allog/dallog/auth/dto/TokenRequest.java rename to backend/src/main/java/com/allog/dallog/domain/auth/dto/TokenRequest.java index c8a20113..4d6e2350 100644 --- a/backend/src/main/java/com/allog/dallog/auth/dto/TokenRequest.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/dto/TokenRequest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.auth.dto; +package com.allog.dallog.domain.auth.dto; public class TokenRequest { diff --git a/backend/src/main/java/com/allog/dallog/auth/dto/TokenResponse.java b/backend/src/main/java/com/allog/dallog/domain/auth/dto/TokenResponse.java similarity index 86% rename from backend/src/main/java/com/allog/dallog/auth/dto/TokenResponse.java rename to backend/src/main/java/com/allog/dallog/domain/auth/dto/TokenResponse.java index c3e2417a..ea852972 100644 --- a/backend/src/main/java/com/allog/dallog/auth/dto/TokenResponse.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/dto/TokenResponse.java @@ -1,4 +1,4 @@ -package com.allog.dallog.auth.dto; +package com.allog.dallog.domain.auth.dto; public class TokenResponse { diff --git a/backend/src/main/java/com/allog/dallog/auth/exception/EmptyAuthorizationHeaderException.java b/backend/src/main/java/com/allog/dallog/domain/auth/exception/EmptyAuthorizationHeaderException.java similarity index 86% rename from backend/src/main/java/com/allog/dallog/auth/exception/EmptyAuthorizationHeaderException.java rename to backend/src/main/java/com/allog/dallog/domain/auth/exception/EmptyAuthorizationHeaderException.java index b1eaa72d..af2611f8 100644 --- a/backend/src/main/java/com/allog/dallog/auth/exception/EmptyAuthorizationHeaderException.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/exception/EmptyAuthorizationHeaderException.java @@ -1,4 +1,4 @@ -package com.allog.dallog.auth.exception; +package com.allog.dallog.domain.auth.exception; public class EmptyAuthorizationHeaderException extends RuntimeException { diff --git a/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenException.java b/backend/src/main/java/com/allog/dallog/domain/auth/exception/InvalidTokenException.java similarity index 83% rename from backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenException.java rename to backend/src/main/java/com/allog/dallog/domain/auth/exception/InvalidTokenException.java index 20977fd0..db514ee4 100644 --- a/backend/src/main/java/com/allog/dallog/auth/exception/InvalidTokenException.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/exception/InvalidTokenException.java @@ -1,4 +1,4 @@ -package com.allog.dallog.auth.exception; +package com.allog.dallog.domain.auth.exception; public class InvalidTokenException extends RuntimeException { diff --git a/backend/src/main/java/com/allog/dallog/auth/exception/NoPermissionException.java b/backend/src/main/java/com/allog/dallog/domain/auth/exception/NoPermissionException.java similarity index 83% rename from backend/src/main/java/com/allog/dallog/auth/exception/NoPermissionException.java rename to backend/src/main/java/com/allog/dallog/domain/auth/exception/NoPermissionException.java index 81fd0a3a..52f85e18 100644 --- a/backend/src/main/java/com/allog/dallog/auth/exception/NoPermissionException.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/exception/NoPermissionException.java @@ -1,4 +1,4 @@ -package com.allog.dallog.auth.exception; +package com.allog.dallog.domain.auth.exception; public class NoPermissionException extends RuntimeException { diff --git a/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java b/backend/src/main/java/com/allog/dallog/domain/auth/presentation/AuthController.java similarity index 82% rename from backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java rename to backend/src/main/java/com/allog/dallog/domain/auth/presentation/AuthController.java index 1e204643..2faece84 100644 --- a/backend/src/main/java/com/allog/dallog/auth/controller/AuthController.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/presentation/AuthController.java @@ -1,9 +1,9 @@ -package com.allog.dallog.auth.controller; +package com.allog.dallog.domain.auth.presentation; -import com.allog.dallog.auth.dto.OAuthUriResponse; -import com.allog.dallog.auth.dto.TokenRequest; -import com.allog.dallog.auth.dto.TokenResponse; -import com.allog.dallog.auth.service.AuthService; +import com.allog.dallog.domain.auth.application.AuthService; +import com.allog.dallog.domain.auth.dto.OAuthUriResponse; +import com.allog.dallog.domain.auth.dto.TokenRequest; +import com.allog.dallog.domain.auth.dto.TokenResponse; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipal.java b/backend/src/main/java/com/allog/dallog/domain/auth/presentation/AuthenticationPrincipal.java similarity index 84% rename from backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipal.java rename to backend/src/main/java/com/allog/dallog/domain/auth/presentation/AuthenticationPrincipal.java index afa08f2c..e7a17b29 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipal.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/presentation/AuthenticationPrincipal.java @@ -1,4 +1,4 @@ -package com.allog.dallog.auth.support; +package com.allog.dallog.domain.auth.presentation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java b/backend/src/main/java/com/allog/dallog/domain/auth/presentation/AuthenticationPrincipalArgumentResolver.java similarity index 89% rename from backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java rename to backend/src/main/java/com/allog/dallog/domain/auth/presentation/AuthenticationPrincipalArgumentResolver.java index de19bb3f..cedd23cc 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/AuthenticationPrincipalArgumentResolver.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/presentation/AuthenticationPrincipalArgumentResolver.java @@ -1,7 +1,7 @@ -package com.allog.dallog.auth.support; +package com.allog.dallog.domain.auth.presentation; -import com.allog.dallog.auth.dto.LoginMember; -import com.allog.dallog.auth.service.AuthService; +import com.allog.dallog.domain.auth.application.AuthService; +import com.allog.dallog.domain.auth.dto.LoginMember; import javax.servlet.http.HttpServletRequest; import org.springframework.core.MethodParameter; import org.springframework.stereotype.Component; diff --git a/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java b/backend/src/main/java/com/allog/dallog/domain/auth/presentation/AuthorizationExtractor.java similarity index 81% rename from backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java rename to backend/src/main/java/com/allog/dallog/domain/auth/presentation/AuthorizationExtractor.java index b262812a..0856cbb0 100644 --- a/backend/src/main/java/com/allog/dallog/auth/support/AuthorizationExtractor.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/presentation/AuthorizationExtractor.java @@ -1,7 +1,7 @@ -package com.allog.dallog.auth.support; +package com.allog.dallog.domain.auth.presentation; -import com.allog.dallog.auth.exception.EmptyAuthorizationHeaderException; -import com.allog.dallog.auth.exception.InvalidTokenException; +import com.allog.dallog.domain.auth.exception.EmptyAuthorizationHeaderException; +import com.allog.dallog.domain.auth.exception.InvalidTokenException; import java.util.Objects; import javax.servlet.http.HttpServletRequest; import org.springframework.http.HttpHeaders; diff --git a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java b/backend/src/main/java/com/allog/dallog/domain/category/application/CategoryService.java similarity index 77% rename from backend/src/main/java/com/allog/dallog/category/service/CategoryService.java rename to backend/src/main/java/com/allog/dallog/domain/category/application/CategoryService.java index 88738661..49e560ac 100644 --- a/backend/src/main/java/com/allog/dallog/category/service/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/application/CategoryService.java @@ -1,15 +1,15 @@ -package com.allog.dallog.category.service; - -import com.allog.dallog.auth.exception.NoPermissionException; -import com.allog.dallog.category.domain.Category; -import com.allog.dallog.category.domain.CategoryRepository; -import com.allog.dallog.category.dto.request.CategoryCreateRequest; -import com.allog.dallog.category.dto.request.CategoryUpdateRequest; -import com.allog.dallog.category.dto.response.CategoriesResponse; -import com.allog.dallog.category.dto.response.CategoryResponse; -import com.allog.dallog.category.exception.NoSuchCategoryException; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.service.MemberService; +package com.allog.dallog.domain.category.application; + +import com.allog.dallog.domain.auth.exception.NoPermissionException; +import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.category.domain.CategoryRepository; +import com.allog.dallog.domain.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.domain.category.dto.request.CategoryUpdateRequest; +import com.allog.dallog.domain.category.dto.response.CategoriesResponse; +import com.allog.dallog.domain.category.dto.response.CategoryResponse; +import com.allog.dallog.domain.category.exception.NoSuchCategoryException; +import com.allog.dallog.domain.member.application.MemberService; +import com.allog.dallog.domain.member.domain.Member; import java.util.List; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; diff --git a/backend/src/main/java/com/allog/dallog/category/domain/Category.java b/backend/src/main/java/com/allog/dallog/domain/category/domain/Category.java similarity index 90% rename from backend/src/main/java/com/allog/dallog/category/domain/Category.java rename to backend/src/main/java/com/allog/dallog/domain/category/domain/Category.java index 780a42d4..03ffa3f2 100644 --- a/backend/src/main/java/com/allog/dallog/category/domain/Category.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/domain/Category.java @@ -1,8 +1,8 @@ -package com.allog.dallog.category.domain; +package com.allog.dallog.domain.category.domain; -import com.allog.dallog.category.exception.InvalidCategoryException; +import com.allog.dallog.domain.category.exception.InvalidCategoryException; +import com.allog.dallog.domain.member.domain.Member; import com.allog.dallog.global.domain.BaseEntity; -import com.allog.dallog.member.domain.Member; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; diff --git a/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java b/backend/src/main/java/com/allog/dallog/domain/category/domain/CategoryRepository.java similarity index 90% rename from backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java rename to backend/src/main/java/com/allog/dallog/domain/category/domain/CategoryRepository.java index 40157213..dc4ec098 100644 --- a/backend/src/main/java/com/allog/dallog/category/domain/CategoryRepository.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/domain/CategoryRepository.java @@ -1,4 +1,4 @@ -package com.allog.dallog.category.domain; +package com.allog.dallog.domain.category.domain; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; diff --git a/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java b/backend/src/main/java/com/allog/dallog/domain/category/dto/request/CategoryCreateRequest.java similarity index 85% rename from backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java rename to backend/src/main/java/com/allog/dallog/domain/category/dto/request/CategoryCreateRequest.java index 378c63fc..f266da67 100644 --- a/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryCreateRequest.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/dto/request/CategoryCreateRequest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.category.dto.request; +package com.allog.dallog.domain.category.dto.request; import javax.validation.constraints.NotBlank; diff --git a/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryUpdateRequest.java b/backend/src/main/java/com/allog/dallog/domain/category/dto/request/CategoryUpdateRequest.java similarity index 85% rename from backend/src/main/java/com/allog/dallog/category/dto/request/CategoryUpdateRequest.java rename to backend/src/main/java/com/allog/dallog/domain/category/dto/request/CategoryUpdateRequest.java index 961b7b61..8cc494ca 100644 --- a/backend/src/main/java/com/allog/dallog/category/dto/request/CategoryUpdateRequest.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/dto/request/CategoryUpdateRequest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.category.dto.request; +package com.allog.dallog.domain.category.dto.request; import javax.validation.constraints.NotBlank; diff --git a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java b/backend/src/main/java/com/allog/dallog/domain/category/dto/response/CategoriesResponse.java similarity index 86% rename from backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java rename to backend/src/main/java/com/allog/dallog/domain/category/dto/response/CategoriesResponse.java index 7fdddb35..71e99893 100644 --- a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoriesResponse.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/dto/response/CategoriesResponse.java @@ -1,6 +1,6 @@ -package com.allog.dallog.category.dto.response; +package com.allog.dallog.domain.category.dto.response; -import com.allog.dallog.category.domain.Category; +import com.allog.dallog.domain.category.domain.Category; import java.util.List; import java.util.stream.Collectors; diff --git a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java b/backend/src/main/java/com/allog/dallog/domain/category/dto/response/CategoryResponse.java similarity index 84% rename from backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java rename to backend/src/main/java/com/allog/dallog/domain/category/dto/response/CategoryResponse.java index 91a1abc8..e8316b74 100644 --- a/backend/src/main/java/com/allog/dallog/category/dto/response/CategoryResponse.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/dto/response/CategoryResponse.java @@ -1,7 +1,7 @@ -package com.allog.dallog.category.dto.response; +package com.allog.dallog.domain.category.dto.response; -import com.allog.dallog.category.domain.Category; -import com.allog.dallog.member.dto.MemberResponse; +import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.member.dto.MemberResponse; import java.time.LocalDateTime; public class CategoryResponse { diff --git a/backend/src/main/java/com/allog/dallog/category/exception/InvalidCategoryException.java b/backend/src/main/java/com/allog/dallog/domain/category/exception/InvalidCategoryException.java similarity index 83% rename from backend/src/main/java/com/allog/dallog/category/exception/InvalidCategoryException.java rename to backend/src/main/java/com/allog/dallog/domain/category/exception/InvalidCategoryException.java index f1ff2b85..d133cd9f 100644 --- a/backend/src/main/java/com/allog/dallog/category/exception/InvalidCategoryException.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/exception/InvalidCategoryException.java @@ -1,4 +1,4 @@ -package com.allog.dallog.category.exception; +package com.allog.dallog.domain.category.exception; public class InvalidCategoryException extends RuntimeException { diff --git a/backend/src/main/java/com/allog/dallog/category/exception/NoSuchCategoryException.java b/backend/src/main/java/com/allog/dallog/domain/category/exception/NoSuchCategoryException.java similarity index 83% rename from backend/src/main/java/com/allog/dallog/category/exception/NoSuchCategoryException.java rename to backend/src/main/java/com/allog/dallog/domain/category/exception/NoSuchCategoryException.java index 0934bb6b..0f08a63f 100644 --- a/backend/src/main/java/com/allog/dallog/category/exception/NoSuchCategoryException.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/exception/NoSuchCategoryException.java @@ -1,4 +1,4 @@ -package com.allog.dallog.category.exception; +package com.allog.dallog.domain.category.exception; public class NoSuchCategoryException extends RuntimeException { diff --git a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java b/backend/src/main/java/com/allog/dallog/domain/category/presentation/CategoryController.java similarity index 83% rename from backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java rename to backend/src/main/java/com/allog/dallog/domain/category/presentation/CategoryController.java index f2f543f0..e4cefb29 100644 --- a/backend/src/main/java/com/allog/dallog/category/controller/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/presentation/CategoryController.java @@ -1,12 +1,12 @@ -package com.allog.dallog.category.controller; +package com.allog.dallog.domain.category.presentation; -import com.allog.dallog.auth.dto.LoginMember; -import com.allog.dallog.auth.support.AuthenticationPrincipal; -import com.allog.dallog.category.dto.request.CategoryCreateRequest; -import com.allog.dallog.category.dto.request.CategoryUpdateRequest; -import com.allog.dallog.category.dto.response.CategoriesResponse; -import com.allog.dallog.category.dto.response.CategoryResponse; -import com.allog.dallog.category.service.CategoryService; +import com.allog.dallog.domain.auth.dto.LoginMember; +import com.allog.dallog.domain.auth.presentation.AuthenticationPrincipal; +import com.allog.dallog.domain.category.application.CategoryService; +import com.allog.dallog.domain.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.domain.category.dto.request.CategoryUpdateRequest; +import com.allog.dallog.domain.category.dto.response.CategoriesResponse; +import com.allog.dallog.domain.category.dto.response.CategoryResponse; import java.net.URI; import javax.validation.Valid; import org.springframework.data.domain.Pageable; diff --git a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java b/backend/src/main/java/com/allog/dallog/domain/member/application/MemberService.java similarity index 80% rename from backend/src/main/java/com/allog/dallog/member/service/MemberService.java rename to backend/src/main/java/com/allog/dallog/domain/member/application/MemberService.java index 68fc77cb..3fad6acf 100644 --- a/backend/src/main/java/com/allog/dallog/member/service/MemberService.java +++ b/backend/src/main/java/com/allog/dallog/domain/member/application/MemberService.java @@ -1,9 +1,9 @@ -package com.allog.dallog.member.service; +package com.allog.dallog.domain.member.application; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.domain.MemberRepository; -import com.allog.dallog.member.dto.MemberResponse; -import com.allog.dallog.member.exception.NoSuchMemberException; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.member.domain.MemberRepository; +import com.allog.dallog.domain.member.dto.MemberResponse; +import com.allog.dallog.domain.member.exception.NoSuchMemberException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/backend/src/main/java/com/allog/dallog/member/domain/Member.java b/backend/src/main/java/com/allog/dallog/domain/member/domain/Member.java similarity index 95% rename from backend/src/main/java/com/allog/dallog/member/domain/Member.java rename to backend/src/main/java/com/allog/dallog/domain/member/domain/Member.java index 990c32f7..6d78833e 100644 --- a/backend/src/main/java/com/allog/dallog/member/domain/Member.java +++ b/backend/src/main/java/com/allog/dallog/domain/member/domain/Member.java @@ -1,7 +1,7 @@ -package com.allog.dallog.member.domain; +package com.allog.dallog.domain.member.domain; +import com.allog.dallog.domain.member.exception.InvalidMemberException; import com.allog.dallog.global.domain.BaseEntity; -import com.allog.dallog.member.exception.InvalidMemberException; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.persistence.Column; diff --git a/backend/src/main/java/com/allog/dallog/member/domain/MemberRepository.java b/backend/src/main/java/com/allog/dallog/domain/member/domain/MemberRepository.java similarity index 85% rename from backend/src/main/java/com/allog/dallog/member/domain/MemberRepository.java rename to backend/src/main/java/com/allog/dallog/domain/member/domain/MemberRepository.java index 07dd2b2b..602d671b 100644 --- a/backend/src/main/java/com/allog/dallog/member/domain/MemberRepository.java +++ b/backend/src/main/java/com/allog/dallog/domain/member/domain/MemberRepository.java @@ -1,4 +1,4 @@ -package com.allog.dallog.member.domain; +package com.allog.dallog.domain.member.domain; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/backend/src/main/java/com/allog/dallog/member/domain/SocialType.java b/backend/src/main/java/com/allog/dallog/domain/member/domain/SocialType.java similarity index 51% rename from backend/src/main/java/com/allog/dallog/member/domain/SocialType.java rename to backend/src/main/java/com/allog/dallog/domain/member/domain/SocialType.java index f199cb1f..4dcb0249 100644 --- a/backend/src/main/java/com/allog/dallog/member/domain/SocialType.java +++ b/backend/src/main/java/com/allog/dallog/domain/member/domain/SocialType.java @@ -1,4 +1,4 @@ -package com.allog.dallog.member.domain; +package com.allog.dallog.domain.member.domain; public enum SocialType { diff --git a/backend/src/main/java/com/allog/dallog/member/dto/MemberResponse.java b/backend/src/main/java/com/allog/dallog/domain/member/dto/MemberResponse.java similarity index 87% rename from backend/src/main/java/com/allog/dallog/member/dto/MemberResponse.java rename to backend/src/main/java/com/allog/dallog/domain/member/dto/MemberResponse.java index cef1837c..84038b9e 100644 --- a/backend/src/main/java/com/allog/dallog/member/dto/MemberResponse.java +++ b/backend/src/main/java/com/allog/dallog/domain/member/dto/MemberResponse.java @@ -1,7 +1,7 @@ -package com.allog.dallog.member.dto; +package com.allog.dallog.domain.member.dto; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.domain.SocialType; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.member.domain.SocialType; public class MemberResponse { diff --git a/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java b/backend/src/main/java/com/allog/dallog/domain/member/exception/InvalidMemberException.java similarity index 83% rename from backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java rename to backend/src/main/java/com/allog/dallog/domain/member/exception/InvalidMemberException.java index fcce6fed..e7dc859c 100644 --- a/backend/src/main/java/com/allog/dallog/member/exception/InvalidMemberException.java +++ b/backend/src/main/java/com/allog/dallog/domain/member/exception/InvalidMemberException.java @@ -1,4 +1,4 @@ -package com.allog.dallog.member.exception; +package com.allog.dallog.domain.member.exception; public class InvalidMemberException extends RuntimeException { diff --git a/backend/src/main/java/com/allog/dallog/member/exception/NoSuchMemberException.java b/backend/src/main/java/com/allog/dallog/domain/member/exception/NoSuchMemberException.java similarity index 83% rename from backend/src/main/java/com/allog/dallog/member/exception/NoSuchMemberException.java rename to backend/src/main/java/com/allog/dallog/domain/member/exception/NoSuchMemberException.java index 2e80ad89..11193954 100644 --- a/backend/src/main/java/com/allog/dallog/member/exception/NoSuchMemberException.java +++ b/backend/src/main/java/com/allog/dallog/domain/member/exception/NoSuchMemberException.java @@ -1,4 +1,4 @@ -package com.allog.dallog.member.exception; +package com.allog.dallog.domain.member.exception; public class NoSuchMemberException extends RuntimeException { diff --git a/backend/src/main/java/com/allog/dallog/member/controller/MemberController.java b/backend/src/main/java/com/allog/dallog/domain/member/presentation/MemberController.java similarity index 70% rename from backend/src/main/java/com/allog/dallog/member/controller/MemberController.java rename to backend/src/main/java/com/allog/dallog/domain/member/presentation/MemberController.java index 13b6455f..6055001b 100644 --- a/backend/src/main/java/com/allog/dallog/member/controller/MemberController.java +++ b/backend/src/main/java/com/allog/dallog/domain/member/presentation/MemberController.java @@ -1,9 +1,9 @@ -package com.allog.dallog.member.controller; +package com.allog.dallog.domain.member.presentation; -import com.allog.dallog.auth.dto.LoginMember; -import com.allog.dallog.auth.support.AuthenticationPrincipal; -import com.allog.dallog.member.dto.MemberResponse; -import com.allog.dallog.member.service.MemberService; +import com.allog.dallog.domain.auth.dto.LoginMember; +import com.allog.dallog.domain.auth.presentation.AuthenticationPrincipal; +import com.allog.dallog.domain.member.application.MemberService; +import com.allog.dallog.domain.member.dto.MemberResponse; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java b/backend/src/main/java/com/allog/dallog/domain/schedule/application/ScheduleService.java similarity index 79% rename from backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java rename to backend/src/main/java/com/allog/dallog/domain/schedule/application/ScheduleService.java index b9d91861..fbdd3466 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/service/ScheduleService.java +++ b/backend/src/main/java/com/allog/dallog/domain/schedule/application/ScheduleService.java @@ -1,9 +1,9 @@ -package com.allog.dallog.schedule.service; +package com.allog.dallog.domain.schedule.application; -import com.allog.dallog.schedule.domain.Schedule; -import com.allog.dallog.schedule.domain.ScheduleRepository; -import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; -import com.allog.dallog.schedule.dto.response.ScheduleResponse; +import com.allog.dallog.domain.schedule.domain.Schedule; +import com.allog.dallog.domain.schedule.domain.ScheduleRepository; +import com.allog.dallog.domain.schedule.dto.request.ScheduleCreateRequest; +import com.allog.dallog.domain.schedule.dto.response.ScheduleResponse; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java b/backend/src/main/java/com/allog/dallog/domain/schedule/domain/Period.java similarity index 92% rename from backend/src/main/java/com/allog/dallog/schedule/domain/Period.java rename to backend/src/main/java/com/allog/dallog/domain/schedule/domain/Period.java index aa39fbb1..6ec3c52d 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Period.java +++ b/backend/src/main/java/com/allog/dallog/domain/schedule/domain/Period.java @@ -1,6 +1,6 @@ -package com.allog.dallog.schedule.domain; +package com.allog.dallog.domain.schedule.domain; -import com.allog.dallog.schedule.exception.InvalidScheduleException; +import com.allog.dallog.domain.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; import java.util.Objects; import javax.persistence.Column; diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java b/backend/src/main/java/com/allog/dallog/domain/schedule/domain/Schedule.java similarity index 94% rename from backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java rename to backend/src/main/java/com/allog/dallog/domain/schedule/domain/Schedule.java index d852cd01..8b5c9d02 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/Schedule.java +++ b/backend/src/main/java/com/allog/dallog/domain/schedule/domain/Schedule.java @@ -1,7 +1,7 @@ -package com.allog.dallog.schedule.domain; +package com.allog.dallog.domain.schedule.domain; +import com.allog.dallog.domain.schedule.exception.InvalidScheduleException; import com.allog.dallog.global.domain.BaseEntity; -import com.allog.dallog.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; import javax.persistence.Column; import javax.persistence.Embedded; diff --git a/backend/src/main/java/com/allog/dallog/schedule/domain/ScheduleRepository.java b/backend/src/main/java/com/allog/dallog/domain/schedule/domain/ScheduleRepository.java similarity index 67% rename from backend/src/main/java/com/allog/dallog/schedule/domain/ScheduleRepository.java rename to backend/src/main/java/com/allog/dallog/domain/schedule/domain/ScheduleRepository.java index 6bd3472e..2b433d99 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/domain/ScheduleRepository.java +++ b/backend/src/main/java/com/allog/dallog/domain/schedule/domain/ScheduleRepository.java @@ -1,4 +1,4 @@ -package com.allog.dallog.schedule.domain; +package com.allog.dallog.domain.schedule.domain; import java.time.LocalDateTime; import java.util.List; @@ -8,7 +8,7 @@ public interface ScheduleRepository extends JpaRepository { @Query("SELECT s " - + "FROM Schedule s " - + "WHERE s.period.startDateTime <= :endDate AND s.period.endDateTime >= :startDate") + + "FROM Schedule s " + + "WHERE s.period.startDateTime <= :endDate AND s.period.endDateTime >= :startDate") List findByBetween(final LocalDateTime startDate, final LocalDateTime endDate); } diff --git a/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java b/backend/src/main/java/com/allog/dallog/domain/schedule/dto/request/ScheduleCreateRequest.java similarity index 91% rename from backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java rename to backend/src/main/java/com/allog/dallog/domain/schedule/dto/request/ScheduleCreateRequest.java index 5afb66bc..20602dbc 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/dto/request/ScheduleCreateRequest.java +++ b/backend/src/main/java/com/allog/dallog/domain/schedule/dto/request/ScheduleCreateRequest.java @@ -1,6 +1,6 @@ -package com.allog.dallog.schedule.dto.request; +package com.allog.dallog.domain.schedule.dto.request; -import com.allog.dallog.schedule.domain.Schedule; +import com.allog.dallog.domain.schedule.domain.Schedule; import java.time.LocalDateTime; import javax.validation.constraints.NotBlank; import org.springframework.format.annotation.DateTimeFormat; diff --git a/backend/src/main/java/com/allog/dallog/schedule/dto/response/ScheduleResponse.java b/backend/src/main/java/com/allog/dallog/domain/schedule/dto/response/ScheduleResponse.java similarity index 91% rename from backend/src/main/java/com/allog/dallog/schedule/dto/response/ScheduleResponse.java rename to backend/src/main/java/com/allog/dallog/domain/schedule/dto/response/ScheduleResponse.java index 554e807b..a118f9e5 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/dto/response/ScheduleResponse.java +++ b/backend/src/main/java/com/allog/dallog/domain/schedule/dto/response/ScheduleResponse.java @@ -1,6 +1,6 @@ -package com.allog.dallog.schedule.dto.response; +package com.allog.dallog.domain.schedule.dto.response; -import com.allog.dallog.schedule.domain.Schedule; +import com.allog.dallog.domain.schedule.domain.Schedule; import java.time.LocalDateTime; public class ScheduleResponse { diff --git a/backend/src/main/java/com/allog/dallog/schedule/dto/response/SchedulesResponse.java b/backend/src/main/java/com/allog/dallog/domain/schedule/dto/response/SchedulesResponse.java similarity index 86% rename from backend/src/main/java/com/allog/dallog/schedule/dto/response/SchedulesResponse.java rename to backend/src/main/java/com/allog/dallog/domain/schedule/dto/response/SchedulesResponse.java index 72c8dea2..f8f45baf 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/dto/response/SchedulesResponse.java +++ b/backend/src/main/java/com/allog/dallog/domain/schedule/dto/response/SchedulesResponse.java @@ -1,4 +1,4 @@ -package com.allog.dallog.schedule.dto.response; +package com.allog.dallog.domain.schedule.dto.response; import java.util.List; diff --git a/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidScheduleException.java b/backend/src/main/java/com/allog/dallog/domain/schedule/exception/InvalidScheduleException.java similarity index 82% rename from backend/src/main/java/com/allog/dallog/schedule/exception/InvalidScheduleException.java rename to backend/src/main/java/com/allog/dallog/domain/schedule/exception/InvalidScheduleException.java index 70c24d59..ac5c6a39 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/exception/InvalidScheduleException.java +++ b/backend/src/main/java/com/allog/dallog/domain/schedule/exception/InvalidScheduleException.java @@ -1,4 +1,4 @@ -package com.allog.dallog.schedule.exception; +package com.allog.dallog.domain.schedule.exception; public class InvalidScheduleException extends RuntimeException { diff --git a/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java b/backend/src/main/java/com/allog/dallog/domain/schedule/presentation/ScheduleController.java similarity index 80% rename from backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java rename to backend/src/main/java/com/allog/dallog/domain/schedule/presentation/ScheduleController.java index 1af7d90e..fd42c118 100644 --- a/backend/src/main/java/com/allog/dallog/schedule/controller/ScheduleController.java +++ b/backend/src/main/java/com/allog/dallog/domain/schedule/presentation/ScheduleController.java @@ -1,9 +1,9 @@ -package com.allog.dallog.schedule.controller; +package com.allog.dallog.domain.schedule.presentation; -import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; -import com.allog.dallog.schedule.dto.response.ScheduleResponse; -import com.allog.dallog.schedule.dto.response.SchedulesResponse; -import com.allog.dallog.schedule.service.ScheduleService; +import com.allog.dallog.domain.schedule.application.ScheduleService; +import com.allog.dallog.domain.schedule.dto.request.ScheduleCreateRequest; +import com.allog.dallog.domain.schedule.dto.response.ScheduleResponse; +import com.allog.dallog.domain.schedule.dto.response.SchedulesResponse; import java.net.URI; import java.util.List; import javax.validation.Valid; diff --git a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java b/backend/src/main/java/com/allog/dallog/domain/subscription/application/SubscriptionService.java similarity index 72% rename from backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java rename to backend/src/main/java/com/allog/dallog/domain/subscription/application/SubscriptionService.java index 35d54184..873173c1 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/service/SubscriptionService.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/application/SubscriptionService.java @@ -1,16 +1,16 @@ -package com.allog.dallog.subscription.service; +package com.allog.dallog.domain.subscription.application; -import com.allog.dallog.auth.exception.NoPermissionException; -import com.allog.dallog.category.domain.Category; -import com.allog.dallog.category.service.CategoryService; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.service.MemberService; -import com.allog.dallog.subscription.domain.Subscription; -import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; -import com.allog.dallog.subscription.dto.response.SubscriptionResponse; -import com.allog.dallog.subscription.dto.response.SubscriptionsResponse; -import com.allog.dallog.subscription.exception.NoSuchSubscriptionException; -import com.allog.dallog.subscription.repository.SubscriptionRepository; +import com.allog.dallog.domain.auth.exception.NoPermissionException; +import com.allog.dallog.domain.category.application.CategoryService; +import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.member.application.MemberService; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.subscription.domain.Subscription; +import com.allog.dallog.domain.subscription.dto.request.SubscriptionCreateRequest; +import com.allog.dallog.domain.subscription.dto.response.SubscriptionResponse; +import com.allog.dallog.domain.subscription.dto.response.SubscriptionsResponse; +import com.allog.dallog.domain.subscription.exception.NoSuchSubscriptionException; +import com.allog.dallog.domain.subscription.repository.SubscriptionRepository; import java.util.List; import java.util.stream.Collectors; import org.springframework.stereotype.Service; diff --git a/backend/src/main/java/com/allog/dallog/subscription/domain/Subscription.java b/backend/src/main/java/com/allog/dallog/domain/subscription/domain/Subscription.java similarity index 88% rename from backend/src/main/java/com/allog/dallog/subscription/domain/Subscription.java rename to backend/src/main/java/com/allog/dallog/domain/subscription/domain/Subscription.java index 737cb69a..22eacc3f 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/domain/Subscription.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/domain/Subscription.java @@ -1,9 +1,9 @@ -package com.allog.dallog.subscription.domain; +package com.allog.dallog.domain.subscription.domain; -import com.allog.dallog.category.domain.Category; +import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.subscription.exception.InvalidSubscriptionException; import com.allog.dallog.global.domain.BaseEntity; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.subscription.exception.InvalidSubscriptionException; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.persistence.Column; diff --git a/backend/src/main/java/com/allog/dallog/subscription/dto/request/SubscriptionCreateRequest.java b/backend/src/main/java/com/allog/dallog/domain/subscription/dto/request/SubscriptionCreateRequest.java similarity index 82% rename from backend/src/main/java/com/allog/dallog/subscription/dto/request/SubscriptionCreateRequest.java rename to backend/src/main/java/com/allog/dallog/domain/subscription/dto/request/SubscriptionCreateRequest.java index 316d8b3e..6eff25cf 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/dto/request/SubscriptionCreateRequest.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/dto/request/SubscriptionCreateRequest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.subscription.dto.request; +package com.allog.dallog.domain.subscription.dto.request; public class SubscriptionCreateRequest { diff --git a/backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionResponse.java b/backend/src/main/java/com/allog/dallog/domain/subscription/dto/response/SubscriptionResponse.java similarity index 79% rename from backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionResponse.java rename to backend/src/main/java/com/allog/dallog/domain/subscription/dto/response/SubscriptionResponse.java index 0c67b43d..4b25b654 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionResponse.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/dto/response/SubscriptionResponse.java @@ -1,7 +1,7 @@ -package com.allog.dallog.subscription.dto.response; +package com.allog.dallog.domain.subscription.dto.response; -import com.allog.dallog.category.dto.response.CategoryResponse; -import com.allog.dallog.subscription.domain.Subscription; +import com.allog.dallog.domain.category.dto.response.CategoryResponse; +import com.allog.dallog.domain.subscription.domain.Subscription; public class SubscriptionResponse { diff --git a/backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionsResponse.java b/backend/src/main/java/com/allog/dallog/domain/subscription/dto/response/SubscriptionsResponse.java similarity index 86% rename from backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionsResponse.java rename to backend/src/main/java/com/allog/dallog/domain/subscription/dto/response/SubscriptionsResponse.java index 2878c8a8..25487189 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/dto/response/SubscriptionsResponse.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/dto/response/SubscriptionsResponse.java @@ -1,4 +1,4 @@ -package com.allog.dallog.subscription.dto.response; +package com.allog.dallog.domain.subscription.dto.response; import java.util.List; diff --git a/backend/src/main/java/com/allog/dallog/subscription/exception/InvalidSubscriptionException.java b/backend/src/main/java/com/allog/dallog/domain/subscription/exception/InvalidSubscriptionException.java similarity index 83% rename from backend/src/main/java/com/allog/dallog/subscription/exception/InvalidSubscriptionException.java rename to backend/src/main/java/com/allog/dallog/domain/subscription/exception/InvalidSubscriptionException.java index d37817cf..f6677b69 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/exception/InvalidSubscriptionException.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/exception/InvalidSubscriptionException.java @@ -1,4 +1,4 @@ -package com.allog.dallog.subscription.exception; +package com.allog.dallog.domain.subscription.exception; public class InvalidSubscriptionException extends RuntimeException { diff --git a/backend/src/main/java/com/allog/dallog/subscription/exception/NoSuchSubscriptionException.java b/backend/src/main/java/com/allog/dallog/domain/subscription/exception/NoSuchSubscriptionException.java similarity index 83% rename from backend/src/main/java/com/allog/dallog/subscription/exception/NoSuchSubscriptionException.java rename to backend/src/main/java/com/allog/dallog/domain/subscription/exception/NoSuchSubscriptionException.java index 1fcc1b85..054aaf18 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/exception/NoSuchSubscriptionException.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/exception/NoSuchSubscriptionException.java @@ -1,4 +1,4 @@ -package com.allog.dallog.subscription.exception; +package com.allog.dallog.domain.subscription.exception; public class NoSuchSubscriptionException extends RuntimeException { diff --git a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java b/backend/src/main/java/com/allog/dallog/domain/subscription/presentation/SubscriptionController.java similarity index 80% rename from backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java rename to backend/src/main/java/com/allog/dallog/domain/subscription/presentation/SubscriptionController.java index 822c457b..9630fedf 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/controller/SubscriptionController.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/presentation/SubscriptionController.java @@ -1,11 +1,11 @@ -package com.allog.dallog.subscription.controller; +package com.allog.dallog.domain.subscription.presentation; -import com.allog.dallog.auth.dto.LoginMember; -import com.allog.dallog.auth.support.AuthenticationPrincipal; -import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; -import com.allog.dallog.subscription.dto.response.SubscriptionResponse; -import com.allog.dallog.subscription.dto.response.SubscriptionsResponse; -import com.allog.dallog.subscription.service.SubscriptionService; +import com.allog.dallog.domain.auth.dto.LoginMember; +import com.allog.dallog.domain.auth.presentation.AuthenticationPrincipal; +import com.allog.dallog.domain.subscription.application.SubscriptionService; +import com.allog.dallog.domain.subscription.dto.request.SubscriptionCreateRequest; +import com.allog.dallog.domain.subscription.dto.response.SubscriptionResponse; +import com.allog.dallog.domain.subscription.dto.response.SubscriptionsResponse; import java.net.URI; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; diff --git a/backend/src/main/java/com/allog/dallog/subscription/repository/SubscriptionRepository.java b/backend/src/main/java/com/allog/dallog/domain/subscription/repository/SubscriptionRepository.java similarity index 75% rename from backend/src/main/java/com/allog/dallog/subscription/repository/SubscriptionRepository.java rename to backend/src/main/java/com/allog/dallog/domain/subscription/repository/SubscriptionRepository.java index e7460eaf..ceba97dd 100644 --- a/backend/src/main/java/com/allog/dallog/subscription/repository/SubscriptionRepository.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/repository/SubscriptionRepository.java @@ -1,6 +1,6 @@ -package com.allog.dallog.subscription.repository; +package com.allog.dallog.domain.subscription.repository; -import com.allog.dallog.subscription.domain.Subscription; +import com.allog.dallog.domain.subscription.domain.Subscription; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/backend/src/main/java/com/allog/dallog/global/config/WebConfig.java b/backend/src/main/java/com/allog/dallog/global/config/WebConfig.java index 3a4dba3b..afa83716 100644 --- a/backend/src/main/java/com/allog/dallog/global/config/WebConfig.java +++ b/backend/src/main/java/com/allog/dallog/global/config/WebConfig.java @@ -1,6 +1,6 @@ package com.allog.dallog.global.config; -import com.allog.dallog.auth.support.AuthenticationPrincipalArgumentResolver; +import com.allog.dallog.domain.auth.presentation.AuthenticationPrincipalArgumentResolver; import java.util.List; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java index 3cacf0a8..64ba6662 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java @@ -1,7 +1,7 @@ package com.allog.dallog.infrastructure.oauth.client; -import com.allog.dallog.auth.dto.OAuthMember; -import com.allog.dallog.auth.support.OAuthClient; +import com.allog.dallog.domain.auth.application.OAuthClient; +import com.allog.dallog.domain.auth.dto.OAuthMember; import com.allog.dallog.infrastructure.oauth.dto.GoogleTokenResponse; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java index 967cdacd..381450d8 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java @@ -1,6 +1,6 @@ package com.allog.dallog.infrastructure.oauth.uri; -import com.allog.dallog.auth.support.OAuthUri; +import com.allog.dallog.domain.auth.application.OAuthUri; import java.util.List; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java index 34bea5f5..5c589021 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AuthAcceptanceTest.java @@ -8,9 +8,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; -import com.allog.dallog.auth.dto.OAuthUriResponse; -import com.allog.dallog.auth.dto.TokenResponse; import com.allog.dallog.common.config.TestConfig; +import com.allog.dallog.domain.auth.dto.OAuthUriResponse; +import com.allog.dallog.domain.auth.dto.TokenResponse; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.junit.jupiter.api.DisplayName; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java index dcc36b4d..2b886815 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/CategoryAcceptanceTest.java @@ -20,8 +20,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; -import com.allog.dallog.category.dto.response.CategoriesResponse; -import com.allog.dallog.category.dto.response.CategoryResponse; +import com.allog.dallog.domain.category.dto.response.CategoriesResponse; +import com.allog.dallog.domain.category.dto.response.CategoryResponse; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.junit.jupiter.api.DisplayName; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java index 36c0c940..6e1213f9 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/MemberAcceptanceTest.java @@ -12,7 +12,7 @@ import static org.junit.jupiter.api.Assertions.assertAll; import com.allog.dallog.common.config.TestConfig; -import com.allog.dallog.member.dto.MemberResponse; +import com.allog.dallog.domain.member.dto.MemberResponse; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; import org.junit.jupiter.api.DisplayName; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java index b84e94d1..b270efdb 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/SubscriptionAcceptanceTest.java @@ -11,12 +11,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; -import com.allog.dallog.category.dto.request.CategoryCreateRequest; -import com.allog.dallog.category.dto.response.CategoryResponse; import com.allog.dallog.common.config.TestConfig; -import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; -import com.allog.dallog.subscription.dto.response.SubscriptionResponse; -import com.allog.dallog.subscription.dto.response.SubscriptionsResponse; +import com.allog.dallog.domain.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.domain.category.dto.response.CategoryResponse; +import com.allog.dallog.domain.subscription.dto.request.SubscriptionCreateRequest; +import com.allog.dallog.domain.subscription.dto.response.SubscriptionResponse; +import com.allog.dallog.domain.subscription.dto.response.SubscriptionsResponse; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/AuthAcceptanceFixtures.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/AuthAcceptanceFixtures.java index 78f61766..6307e98b 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/AuthAcceptanceFixtures.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/AuthAcceptanceFixtures.java @@ -1,7 +1,7 @@ package com.allog.dallog.acceptance.fixtures; -import com.allog.dallog.auth.dto.TokenRequest; -import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.domain.auth.dto.TokenRequest; +import com.allog.dallog.domain.auth.dto.TokenResponse; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; diff --git a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java index 8dbf2b9c..e40f3a88 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/fixtures/CategoryAcceptanceFixtures.java @@ -1,7 +1,7 @@ package com.allog.dallog.acceptance.fixtures; -import com.allog.dallog.category.dto.request.CategoryCreateRequest; -import com.allog.dallog.category.dto.request.CategoryUpdateRequest; +import com.allog.dallog.domain.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.domain.category.dto.request.CategoryUpdateRequest; import io.restassured.RestAssured; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; diff --git a/backend/src/test/java/com/allog/dallog/common/config/TestConfig.java b/backend/src/test/java/com/allog/dallog/common/config/TestConfig.java index 9cf8aae3..185e9b75 100644 --- a/backend/src/test/java/com/allog/dallog/common/config/TestConfig.java +++ b/backend/src/test/java/com/allog/dallog/common/config/TestConfig.java @@ -1,6 +1,6 @@ package com.allog.dallog.common.config; -import com.allog.dallog.auth.support.OAuthClient; +import com.allog.dallog.domain.auth.application.OAuthClient; import com.allog.dallog.infrastructure.oauth.client.StubOAuthClient; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 8d3e9e61..5322132c 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -1,8 +1,8 @@ package com.allog.dallog.common.fixtures; -import com.allog.dallog.category.domain.Category; -import com.allog.dallog.category.dto.request.CategoryCreateRequest; -import com.allog.dallog.member.domain.Member; +import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.domain.member.domain.Member; public class CategoryFixtures { diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java index ef572790..66173b45 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java @@ -1,7 +1,7 @@ package com.allog.dallog.common.fixtures; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.domain.SocialType; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.member.domain.SocialType; public class MemberFixtures { diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java index a29d9c72..48430180 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java @@ -1,9 +1,9 @@ package com.allog.dallog.common.fixtures; -import com.allog.dallog.category.domain.Category; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.subscription.domain.Subscription; -import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; +import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.subscription.domain.Subscription; +import com.allog.dallog.domain.subscription.dto.request.SubscriptionCreateRequest; public class SubscriptionFixtures { diff --git a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java b/backend/src/test/java/com/allog/dallog/domain/auth/application/AuthServiceTest.java similarity index 92% rename from backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java rename to backend/src/test/java/com/allog/dallog/domain/auth/application/AuthServiceTest.java index 2564fb62..9a5fe36a 100644 --- a/backend/src/test/java/com/allog/dallog/auth/service/AuthServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/auth/application/AuthServiceTest.java @@ -1,14 +1,14 @@ -package com.allog.dallog.auth.service; +package com.allog.dallog.domain.auth.application; import static com.allog.dallog.common.fixtures.AuthFixtures.STUB_이메일; import static com.allog.dallog.common.fixtures.AuthFixtures.인증_코드; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.allog.dallog.auth.dto.TokenResponse; +import com.allog.dallog.domain.auth.dto.TokenResponse; import com.allog.dallog.common.config.TestConfig; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.domain.MemberRepository; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.member.domain.MemberRepository; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java b/backend/src/test/java/com/allog/dallog/domain/auth/application/JwtTokenProviderTest.java similarity index 94% rename from backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java rename to backend/src/test/java/com/allog/dallog/domain/auth/application/JwtTokenProviderTest.java index 51d4e25a..3b5a9e88 100644 --- a/backend/src/test/java/com/allog/dallog/auth/support/JwtTokenProviderTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/auth/application/JwtTokenProviderTest.java @@ -1,9 +1,9 @@ -package com.allog.dallog.auth.support; +package com.allog.dallog.domain.auth.application; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.allog.dallog.auth.exception.InvalidTokenException; +import com.allog.dallog.domain.auth.exception.InvalidTokenException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java similarity index 91% rename from backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java rename to backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java index 83c9f3b0..4616b27a 100644 --- a/backend/src/test/java/com/allog/dallog/category/service/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.category.service; +package com.allog.dallog.domain.category.application; import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_생성_요청; import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_생성_요청; @@ -13,16 +13,16 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.allog.dallog.auth.exception.NoPermissionException; -import com.allog.dallog.category.domain.Category; -import com.allog.dallog.category.dto.request.CategoryCreateRequest; -import com.allog.dallog.category.dto.request.CategoryUpdateRequest; -import com.allog.dallog.category.dto.response.CategoriesResponse; -import com.allog.dallog.category.dto.response.CategoryResponse; -import com.allog.dallog.category.exception.InvalidCategoryException; -import com.allog.dallog.category.exception.NoSuchCategoryException; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.domain.MemberRepository; +import com.allog.dallog.domain.auth.exception.NoPermissionException; +import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.domain.category.dto.request.CategoryUpdateRequest; +import com.allog.dallog.domain.category.dto.response.CategoriesResponse; +import com.allog.dallog.domain.category.dto.response.CategoryResponse; +import com.allog.dallog.domain.category.exception.InvalidCategoryException; +import com.allog.dallog.domain.category.exception.NoSuchCategoryException; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.member.domain.MemberRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java b/backend/src/test/java/com/allog/dallog/domain/category/domain/CategoryRepositoryTest.java similarity index 95% rename from backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java rename to backend/src/test/java/com/allog/dallog/domain/category/domain/CategoryRepositoryTest.java index d0436df5..edd6e946 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/domain/CategoryRepositoryTest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.category.domain; +package com.allog.dallog.domain.category.domain; import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정; import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_이름; @@ -14,9 +14,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; +import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.category.domain.CategoryRepository; import com.allog.dallog.global.config.JpaConfig; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.domain.MemberRepository; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.member.domain.MemberRepository; import java.util.Objects; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java b/backend/src/test/java/com/allog/dallog/domain/category/domain/CategoryTest.java similarity index 89% rename from backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java rename to backend/src/test/java/com/allog/dallog/domain/category/domain/CategoryTest.java index 6f2f58f8..af971187 100644 --- a/backend/src/test/java/com/allog/dallog/category/domain/CategoryTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/domain/CategoryTest.java @@ -1,10 +1,11 @@ -package com.allog.dallog.category.domain; +package com.allog.dallog.domain.category.domain; import static com.allog.dallog.common.fixtures.MemberFixtures.후디; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import com.allog.dallog.category.exception.InvalidCategoryException; +import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.category.exception.InvalidCategoryException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; diff --git a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java b/backend/src/test/java/com/allog/dallog/domain/member/application/MemberServiceTest.java similarity index 92% rename from backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java rename to backend/src/test/java/com/allog/dallog/domain/member/application/MemberServiceTest.java index 1e2a412b..5ccde34d 100644 --- a/backend/src/test/java/com/allog/dallog/member/service/MemberServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/member/application/MemberServiceTest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.member.service; +package com.allog.dallog.domain.member.application; import static com.allog.dallog.common.fixtures.MemberFixtures.리버_이메일; import static com.allog.dallog.common.fixtures.MemberFixtures.파랑; @@ -6,9 +6,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.dto.MemberResponse; -import com.allog.dallog.member.exception.NoSuchMemberException; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.member.dto.MemberResponse; +import com.allog.dallog.domain.member.exception.NoSuchMemberException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; diff --git a/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java b/backend/src/test/java/com/allog/dallog/domain/member/domain/MemberRepositoryTest.java similarity index 89% rename from backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java rename to backend/src/test/java/com/allog/dallog/domain/member/domain/MemberRepositoryTest.java index 871b8018..b87299a1 100644 --- a/backend/src/test/java/com/allog/dallog/member/domain/MemberRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/member/domain/MemberRepositoryTest.java @@ -1,9 +1,11 @@ -package com.allog.dallog.member.domain; +package com.allog.dallog.domain.member.domain; import static com.allog.dallog.common.fixtures.MemberFixtures.파랑; import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_이메일; import static org.assertj.core.api.Assertions.assertThat; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.member.domain.MemberRepository; import com.allog.dallog.global.config.JpaConfig; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/backend/src/test/java/com/allog/dallog/member/domain/MemberTest.java b/backend/src/test/java/com/allog/dallog/domain/member/domain/MemberTest.java similarity index 89% rename from backend/src/test/java/com/allog/dallog/member/domain/MemberTest.java rename to backend/src/test/java/com/allog/dallog/domain/member/domain/MemberTest.java index 614fd558..8f6cc9c7 100644 --- a/backend/src/test/java/com/allog/dallog/member/domain/MemberTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/member/domain/MemberTest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.member.domain; +package com.allog.dallog.domain.member.domain; import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_이름; import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_이메일; @@ -6,7 +6,9 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import com.allog.dallog.member.exception.InvalidMemberException; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.member.domain.SocialType; +import com.allog.dallog.domain.member.exception.InvalidMemberException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; diff --git a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java b/backend/src/test/java/com/allog/dallog/domain/schedule/application/ScheduleServiceTest.java similarity index 93% rename from backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java rename to backend/src/test/java/com/allog/dallog/domain/schedule/application/ScheduleServiceTest.java index 86a89bb4..4d5ea82b 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/service/ScheduleServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/schedule/application/ScheduleServiceTest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.schedule.service; +package com.allog.dallog.domain.schedule.application; import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE_TIME; import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; @@ -9,9 +9,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; -import com.allog.dallog.schedule.dto.response.ScheduleResponse; -import com.allog.dallog.schedule.exception.InvalidScheduleException; +import com.allog.dallog.domain.schedule.dto.request.ScheduleCreateRequest; +import com.allog.dallog.domain.schedule.dto.response.ScheduleResponse; +import com.allog.dallog.domain.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; import java.util.List; import org.junit.jupiter.api.DisplayName; diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java b/backend/src/test/java/com/allog/dallog/domain/schedule/domain/PeriodTest.java similarity index 79% rename from backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java rename to backend/src/test/java/com/allog/dallog/domain/schedule/domain/PeriodTest.java index 7c4e6eb7..9912b0e5 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/PeriodTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/schedule/domain/PeriodTest.java @@ -1,8 +1,9 @@ -package com.allog.dallog.schedule.domain; +package com.allog.dallog.domain.schedule.domain; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import com.allog.dallog.schedule.exception.InvalidScheduleException; +import com.allog.dallog.domain.schedule.domain.Period; +import com.allog.dallog.domain.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java b/backend/src/test/java/com/allog/dallog/domain/schedule/domain/ScheduleRepositoryTest.java similarity index 97% rename from backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java rename to backend/src/test/java/com/allog/dallog/domain/schedule/domain/ScheduleRepositoryTest.java index 1da9ed25..4bb0dec1 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/schedule/domain/ScheduleRepositoryTest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.schedule.domain; +package com.allog.dallog.domain.schedule.domain; import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DAY_OF_MONTH; import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; @@ -6,6 +6,8 @@ import static com.allog.dallog.common.fixtures.ScheduleFixtures.TITLE; import static org.assertj.core.api.Assertions.assertThat; +import com.allog.dallog.domain.schedule.domain.Schedule; +import com.allog.dallog.domain.schedule.domain.ScheduleRepository; import com.allog.dallog.global.config.JpaConfig; import java.time.LocalDateTime; import java.util.List; diff --git a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java b/backend/src/test/java/com/allog/dallog/domain/schedule/domain/ScheduleTest.java similarity index 93% rename from backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java rename to backend/src/test/java/com/allog/dallog/domain/schedule/domain/ScheduleTest.java index fafdf91e..1e14b3f8 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/domain/ScheduleTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/schedule/domain/ScheduleTest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.schedule.domain; +package com.allog.dallog.domain.schedule.domain; import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE_TIME; import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; @@ -7,7 +7,8 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import com.allog.dallog.schedule.exception.InvalidScheduleException; +import com.allog.dallog.domain.schedule.domain.Schedule; +import com.allog.dallog.domain.schedule.exception.InvalidScheduleException; import java.time.LocalDateTime; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/schedule/presentation/ScheduleControllerTest.java similarity index 92% rename from backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java rename to backend/src/test/java/com/allog/dallog/domain/schedule/presentation/ScheduleControllerTest.java index 8c16b967..856a06c7 100644 --- a/backend/src/test/java/com/allog/dallog/schedule/controller/ScheduleControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/schedule/presentation/ScheduleControllerTest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.schedule.controller; +package com.allog.dallog.domain.schedule.presentation; import static com.allog.dallog.common.fixtures.ScheduleFixtures.END_DATE_TIME; import static com.allog.dallog.common.fixtures.ScheduleFixtures.MEMO; @@ -18,10 +18,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import com.allog.dallog.auth.service.AuthService; -import com.allog.dallog.schedule.dto.request.ScheduleCreateRequest; -import com.allog.dallog.schedule.dto.response.ScheduleResponse; -import com.allog.dallog.schedule.service.ScheduleService; +import com.allog.dallog.domain.auth.application.AuthService; +import com.allog.dallog.domain.schedule.dto.request.ScheduleCreateRequest; +import com.allog.dallog.domain.schedule.dto.response.ScheduleResponse; +import com.allog.dallog.domain.schedule.application.ScheduleService; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import org.junit.jupiter.api.DisplayName; diff --git a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/domain/subscription/application/SubscriptionServiceTest.java similarity index 89% rename from backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java rename to backend/src/test/java/com/allog/dallog/domain/subscription/application/SubscriptionServiceTest.java index 502c9444..f87df71d 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/service/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/subscription/application/SubscriptionServiceTest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.subscription.service; +package com.allog.dallog.domain.subscription.application; import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_생성_요청; @@ -15,16 +15,16 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertAll; -import com.allog.dallog.auth.exception.NoPermissionException; -import com.allog.dallog.category.dto.response.CategoryResponse; -import com.allog.dallog.category.service.CategoryService; -import com.allog.dallog.member.dto.MemberResponse; -import com.allog.dallog.member.service.MemberService; -import com.allog.dallog.subscription.dto.request.SubscriptionCreateRequest; -import com.allog.dallog.subscription.dto.response.SubscriptionResponse; -import com.allog.dallog.subscription.dto.response.SubscriptionsResponse; -import com.allog.dallog.subscription.exception.InvalidSubscriptionException; -import com.allog.dallog.subscription.exception.NoSuchSubscriptionException; +import com.allog.dallog.domain.auth.exception.NoPermissionException; +import com.allog.dallog.domain.category.application.CategoryService; +import com.allog.dallog.domain.category.dto.response.CategoryResponse; +import com.allog.dallog.domain.member.application.MemberService; +import com.allog.dallog.domain.member.dto.MemberResponse; +import com.allog.dallog.domain.subscription.dto.request.SubscriptionCreateRequest; +import com.allog.dallog.domain.subscription.dto.response.SubscriptionResponse; +import com.allog.dallog.domain.subscription.dto.response.SubscriptionsResponse; +import com.allog.dallog.domain.subscription.exception.InvalidSubscriptionException; +import com.allog.dallog.domain.subscription.exception.NoSuchSubscriptionException; import javax.transaction.Transactional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java b/backend/src/test/java/com/allog/dallog/domain/subscription/domain/SubscriptionTest.java similarity index 82% rename from backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java rename to backend/src/test/java/com/allog/dallog/domain/subscription/domain/SubscriptionTest.java index 90ac551c..d1ede28e 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/domain/SubscriptionTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/subscription/domain/SubscriptionTest.java @@ -1,13 +1,14 @@ -package com.allog.dallog.subscription.domain; +package com.allog.dallog.domain.subscription.domain; import static com.allog.dallog.common.fixtures.CategoryFixtures.후디_JPA_스터디; import static com.allog.dallog.common.fixtures.MemberFixtures.후디; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import com.allog.dallog.category.domain.Category; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.subscription.exception.InvalidSubscriptionException; +import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.subscription.domain.Subscription; +import com.allog.dallog.domain.subscription.exception.InvalidSubscriptionException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; diff --git a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java b/backend/src/test/java/com/allog/dallog/domain/subscription/repository/SubscriptionRepositoryTest.java similarity index 90% rename from backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java rename to backend/src/test/java/com/allog/dallog/domain/subscription/repository/SubscriptionRepositoryTest.java index cb85b9f8..9ccdee9e 100644 --- a/backend/src/test/java/com/allog/dallog/subscription/repository/SubscriptionRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/subscription/repository/SubscriptionRepositoryTest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.subscription.repository; +package com.allog.dallog.domain.subscription.repository; import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정; import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정; @@ -10,12 +10,13 @@ import static com.allog.dallog.common.fixtures.SubscriptionFixtures.파란색_구독; import static org.assertj.core.api.Assertions.assertThat; -import com.allog.dallog.category.domain.Category; -import com.allog.dallog.category.domain.CategoryRepository; +import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.category.domain.CategoryRepository; +import com.allog.dallog.domain.subscription.repository.SubscriptionRepository; import com.allog.dallog.global.config.JpaConfig; -import com.allog.dallog.member.domain.Member; -import com.allog.dallog.member.domain.MemberRepository; -import com.allog.dallog.subscription.domain.Subscription; +import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.member.domain.MemberRepository; +import com.allog.dallog.domain.subscription.domain.Subscription; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java index 64031aa1..f082eea6 100644 --- a/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java +++ b/backend/src/test/java/com/allog/dallog/infrastructure/oauth/client/StubOAuthClient.java @@ -4,8 +4,8 @@ import static com.allog.dallog.common.fixtures.AuthFixtures.STUB_이메일; import static com.allog.dallog.common.fixtures.AuthFixtures.STUB_프로필; -import com.allog.dallog.auth.dto.OAuthMember; -import com.allog.dallog.auth.support.OAuthClient; +import com.allog.dallog.domain.auth.application.OAuthClient; +import com.allog.dallog.domain.auth.dto.OAuthMember; public class StubOAuthClient implements OAuthClient { From 1906610814531b3318dbef10730810de2c827db0 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 26 Jul 2022 16:42:09 +0900 Subject: [PATCH 0330/1011] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EB=AA=A8=EB=8B=AC=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- frontend/src/App.tsx | 16 ++-- .../@common/PageLayout/PageLayout.styles.ts | 1 + .../CategoryAddModal.styles.ts | 1 + .../src/components/LoginModal/LoginModal.tsx | 75 ------------------- .../src/components/NavBar/NavBar.stories.tsx | 2 +- frontend/src/components/NavBar/NavBar.tsx | 12 +-- frontend/src/constants/index.ts | 1 + .../LoginPage/LoginPage.styles.ts} | 15 ++-- frontend/src/pages/LoginPage/LoginPage.tsx | 74 ++++++++++++++++++ frontend/src/pages/MainPage/MainPage.tsx | 9 +-- frontend/src/pages/StartPage/StartPage.tsx | 16 +--- 11 files changed, 103 insertions(+), 119 deletions(-) delete mode 100644 frontend/src/components/LoginModal/LoginModal.tsx rename frontend/src/{components/LoginModal/LoginModal.styles.ts => pages/LoginPage/LoginPage.styles.ts} (89%) create mode 100644 frontend/src/pages/LoginPage/LoginPage.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 92e53308..a88cfd7f 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,7 +1,5 @@ import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'; -import useToggle from '@/hooks/useToggle'; - import NavBar from '@/components/NavBar/NavBar'; import ProtectRoute from '@/components/ProtectRoute'; import SideBar from '@/components/SideBar/SideBar'; @@ -12,21 +10,17 @@ import MyPage from '@/pages/MyPage/MyPage'; import { PATH } from '@/constants'; -function App() { - const { state: isLoginModalOpen, toggleState: toggleLoginModalOpen } = useToggle(); +import LoginPage from './pages/LoginPage/LoginPage'; +function App() { return ( - + - - } - /> + } /> } /> + } /> }> } /> } /> diff --git a/frontend/src/components/@common/PageLayout/PageLayout.styles.ts b/frontend/src/components/@common/PageLayout/PageLayout.styles.ts index fc14ac18..4e368bad 100644 --- a/frontend/src/components/@common/PageLayout/PageLayout.styles.ts +++ b/frontend/src/components/@common/PageLayout/PageLayout.styles.ts @@ -2,6 +2,7 @@ import { css } from '@emotion/react'; const pageLayout = (isSideBarOpen: boolean) => css` overflow-y: auto; + position: relative; height: calc(100vh - 16rem); margin-top: 16rem; diff --git a/frontend/src/components/CategoryAddModal/CategoryAddModal.styles.ts b/frontend/src/components/CategoryAddModal/CategoryAddModal.styles.ts index 3e0755f5..3cec6a84 100644 --- a/frontend/src/components/CategoryAddModal/CategoryAddModal.styles.ts +++ b/frontend/src/components/CategoryAddModal/CategoryAddModal.styles.ts @@ -31,6 +31,7 @@ const content = ({ flex }: Theme) => css` width: 100%; height: 100%; + justify-content: center; `; diff --git a/frontend/src/components/LoginModal/LoginModal.tsx b/frontend/src/components/LoginModal/LoginModal.tsx deleted file mode 100644 index 9333507d..00000000 --- a/frontend/src/components/LoginModal/LoginModal.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { useTheme } from '@emotion/react'; -import { useQuery } from 'react-query'; - -import Button from '@/components/@common/Button/Button'; - -import { CACHE_KEY } from '@/constants'; - -import loginApi from '@/api/login'; - -import { FaGithub } from 'react-icons/fa'; -import { FcGoogle } from 'react-icons/fc'; -import { RiKakaoTalkFill } from 'react-icons/ri'; -import { SiNaver } from 'react-icons/si'; - -import { - content, - githubLoginButton, - googleLoginButton, - kakaoLoginButton, - loginModal, - loginText, - naverLoginButton, - title, -} from './LoginModal.styles'; - -function LoginModal() { - const theme = useTheme(); - - const { error, refetch } = useQuery(CACHE_KEY.ENTER, loginApi.getUrl, { - enabled: false, - onSuccess: (data) => onSuccessGetLoginUrl(data), - }); - - const onSuccessGetLoginUrl = (loginUrl: string) => { - location.href = loginUrl; - }; - - const handleClickLoginModal = (e: React.MouseEvent) => { - e.stopPropagation(); - }; - - const handleClickGoogleLoginButton = () => { - refetch(); - }; - - if (error) { - return <>Error; - } - - return ( -
-

로그인

-
- - - - -
-
- ); -} - -export default LoginModal; diff --git a/frontend/src/components/NavBar/NavBar.stories.tsx b/frontend/src/components/NavBar/NavBar.stories.tsx index 12d1362b..9c4dd234 100644 --- a/frontend/src/components/NavBar/NavBar.stories.tsx +++ b/frontend/src/components/NavBar/NavBar.stories.tsx @@ -7,6 +7,6 @@ export default { component: NavBar, } as ComponentMeta; -const Template: ComponentStory = (args) => ; +const Template: ComponentStory = () => ; export const Primary = Template.bind({}); diff --git a/frontend/src/components/NavBar/NavBar.tsx b/frontend/src/components/NavBar/NavBar.tsx index 3c487a44..c5ec5bdd 100644 --- a/frontend/src/components/NavBar/NavBar.tsx +++ b/frontend/src/components/NavBar/NavBar.tsx @@ -16,11 +16,7 @@ import { HiChevronDoubleLeft, HiMenu } from 'react-icons/hi'; import { loginButton, logo, menu, menus, menuTitle, navBar } from './NavBar.styles'; -interface NavBarProps { - openLoginModal: () => void; -} - -function NavBar({ openLoginModal }: NavBarProps) { +function NavBar() { const [isSideBarOpen, toggleSideBarOpen] = useRecoilState(sideBarSelector); const { accessToken } = useRecoilValue(userState); const theme = useTheme(); @@ -42,6 +38,10 @@ function NavBar({ openLoginModal }: NavBarProps) { navigate(PATH.PROFILE); }; + const handleClickLoginButton = () => { + navigate(PATH.LOGIN); + }; + return (
@@ -55,7 +55,7 @@ function NavBar({ openLoginModal }: NavBarProps) {
{!accessToken && ( - )} diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 18b3371f..291f0a54 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -36,6 +36,7 @@ const PATH = { MAIN: '/', AUTH: '/oauth', CATEGORY: '/category', + LOGIN: '/login', PROFILE: '/profile', }; diff --git a/frontend/src/components/LoginModal/LoginModal.styles.ts b/frontend/src/pages/LoginPage/LoginPage.styles.ts similarity index 89% rename from frontend/src/components/LoginModal/LoginModal.styles.ts rename to frontend/src/pages/LoginPage/LoginPage.styles.ts index 4bfa7059..5dd7fb7e 100644 --- a/frontend/src/components/LoginModal/LoginModal.styles.ts +++ b/frontend/src/pages/LoginPage/LoginPage.styles.ts @@ -1,14 +1,17 @@ import { css, Theme } from '@emotion/react'; -const loginModal = ({ colors, flex }: Theme) => css` +const login = ({ flex }: Theme) => css` ${flex.column} + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 105rem; height: 140rem; padding: 12.5rem; border-radius: 12px; - - background: ${colors.WHITE}; `; const title = ({ colors }: Theme) => css` @@ -17,12 +20,14 @@ const title = ({ colors }: Theme) => css` color: ${colors.GRAY_700}; `; -const content = ({ flex }: Theme) => css` +const content = ({ colors, flex }: Theme) => css` ${flex.column} gap: 3rem; height: 100%; + + background: ${colors.WHITE}; `; const loginButton = ({ colors, flex }: Theme) => css` @@ -85,8 +90,8 @@ export { githubLoginButton, googleLoginButton, kakaoLoginButton, + login, loginButton, - loginModal, loginText, naverLoginButton, title, diff --git a/frontend/src/pages/LoginPage/LoginPage.tsx b/frontend/src/pages/LoginPage/LoginPage.tsx new file mode 100644 index 00000000..23e21662 --- /dev/null +++ b/frontend/src/pages/LoginPage/LoginPage.tsx @@ -0,0 +1,74 @@ +import { useTheme } from '@emotion/react'; +import { useQuery } from 'react-query'; + +import Button from '@/components/@common/Button/Button'; +import PageLayout from '@/components/@common/PageLayout/PageLayout'; + +import { CACHE_KEY } from '@/constants'; + +import loginApi from '@/api/login'; + +import { FaGithub } from 'react-icons/fa'; +import { FcGoogle } from 'react-icons/fc'; +import { RiKakaoTalkFill } from 'react-icons/ri'; +import { SiNaver } from 'react-icons/si'; + +import { + content, + githubLoginButton, + googleLoginButton, + kakaoLoginButton, + login, + loginText, + naverLoginButton, + title, +} from './LoginPage.styles'; + +function LoginPage() { + const theme = useTheme(); + + const { error, refetch } = useQuery(CACHE_KEY.ENTER, loginApi.getUrl, { + enabled: false, + onSuccess: (data) => onSuccessGetLoginUrl(data), + }); + + const onSuccessGetLoginUrl = (loginUrl: string) => { + location.href = loginUrl; + }; + + const handleClickGoogleLoginButton = () => { + refetch(); + }; + + if (error) { + return <>Error; + } + + return ( + +
+

로그인

+
+ + + + +
+
+
+ ); +} + +export default LoginPage; diff --git a/frontend/src/pages/MainPage/MainPage.tsx b/frontend/src/pages/MainPage/MainPage.tsx index b783e9ef..31c76a04 100644 --- a/frontend/src/pages/MainPage/MainPage.tsx +++ b/frontend/src/pages/MainPage/MainPage.tsx @@ -8,12 +8,7 @@ import StartPage from '@/pages/StartPage/StartPage'; import { getAccessToken } from '@/utils'; -interface MainPageProps { - isLoginModalOpen: boolean; - closeLoginModal: () => void; -} - -function MainPage({ isLoginModalOpen, closeLoginModal }: MainPageProps) { +function MainPage() { const [user, setUser] = useRecoilState(userState); useEffect(() => { @@ -21,7 +16,7 @@ function MainPage({ isLoginModalOpen, closeLoginModal }: MainPageProps) { }, []); if (!user.accessToken) { - return ; + return ; } return ; diff --git a/frontend/src/pages/StartPage/StartPage.tsx b/frontend/src/pages/StartPage/StartPage.tsx index c8367e13..effc1a2c 100644 --- a/frontend/src/pages/StartPage/StartPage.tsx +++ b/frontend/src/pages/StartPage/StartPage.tsx @@ -1,17 +1,5 @@ -import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; -import LoginModal from '@/components/LoginModal/LoginModal'; - -interface StartPageProps { - isLoginModalOpen: boolean; - closeLoginModal: () => void; -} - -function StartPage({ isLoginModalOpen, closeLoginModal }: StartPageProps) { - return ( - - - - ); +function StartPage() { + return <>달력에 기록을 공유할 때, 달록 입니다.; } export default StartPage; From 9bdef0e0a050e6c5e2847864d12d7c80b79c8ca8 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 26 Jul 2022 21:34:03 +0900 Subject: [PATCH 0331/1011] =?UTF-8?q?refactor:=20=EC=A0=88=EB=8C=80=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=20=EC=88=98=EC=A0=95=20Co-authored-by:=20Day?= =?UTF-8?q?e=20Lee=20<508yeah@gmail.com>?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index a88cfd7f..e6154ca3 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -5,13 +5,12 @@ import ProtectRoute from '@/components/ProtectRoute'; import SideBar from '@/components/SideBar/SideBar'; import AuthPage from '@/pages/AuthPage/AuthPage'; import CategoryPage from '@/pages/CategoryPage/CategoryPage'; +import LoginPage from '@/pages/LoginPage/LoginPage'; import MainPage from '@/pages/MainPage/MainPage'; import MyPage from '@/pages/MyPage/MyPage'; import { PATH } from '@/constants'; -import LoginPage from './pages/LoginPage/LoginPage'; - function App() { return ( From 640bf37e19cc7b87844c6820b4ad2602412f900b Mon Sep 17 00:00:00 2001 From: hyeonic Date: Tue, 26 Jul 2022 19:42:46 +0900 Subject: [PATCH 0332/1011] =?UTF-8?q?feat:=20=EC=84=A4=EC=A0=95=EA=B0=92?= =?UTF-8?q?=20=EC=B6=94=EC=B6=9C=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EB=B0=8F=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/PropertiesConfig.java | 10 +++ .../config/properties/GoogleProperties.java | 65 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/global/config/PropertiesConfig.java create mode 100644 backend/src/main/java/com/allog/dallog/global/config/properties/GoogleProperties.java diff --git a/backend/src/main/java/com/allog/dallog/global/config/PropertiesConfig.java b/backend/src/main/java/com/allog/dallog/global/config/PropertiesConfig.java new file mode 100644 index 00000000..f2160bb6 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/global/config/PropertiesConfig.java @@ -0,0 +1,10 @@ +package com.allog.dallog.global.config; + +import com.allog.dallog.global.config.properties.GoogleProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(GoogleProperties.class) +public class PropertiesConfig { +} diff --git a/backend/src/main/java/com/allog/dallog/global/config/properties/GoogleProperties.java b/backend/src/main/java/com/allog/dallog/global/config/properties/GoogleProperties.java new file mode 100644 index 00000000..0ccfc750 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/global/config/properties/GoogleProperties.java @@ -0,0 +1,65 @@ +package com.allog.dallog.global.config.properties; + +import java.util.List; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.ConstructorBinding; + +@ConfigurationProperties("oauth.google") +@ConstructorBinding +public class GoogleProperties { + + private final String clientId; + private final String clientSecret; + private final String redirectUri; + private final String oAuthEndPoint; + private final String responseType; + private final List scopes; + private final String tokenUri; + private final String grantType; + + public GoogleProperties(final String clientId, final String clientSecret, final String redirectUri, + final String oAuthEndPoint, + final String responseType, final List scopes, final String tokenUri, + final String grantType) { + this.clientId = clientId; + this.clientSecret = clientSecret; + this.redirectUri = redirectUri; + this.oAuthEndPoint = oAuthEndPoint; + this.responseType = responseType; + this.scopes = scopes; + this.tokenUri = tokenUri; + this.grantType = grantType; + } + + public String getClientId() { + return clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public String getRedirectUri() { + return redirectUri; + } + + public String getoAuthEndPoint() { + return oAuthEndPoint; + } + + public String getResponseType() { + return responseType; + } + + public List getScopes() { + return scopes; + } + + public String getTokenUri() { + return tokenUri; + } + + public String getGrantType() { + return grantType; + } +} From 6701ca9b1b1cb15c28b6990d0d6ee1c3fee44321 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Tue, 26 Jul 2022 19:56:13 +0900 Subject: [PATCH 0333/1011] =?UTF-8?q?feat:=20GoogleProperties=20=ED=99=9C?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/properties/GoogleProperties.java | 5 ++- .../oauth/client/GoogleOAuthClient.java | 32 ++++++------------- .../oauth/uri/GoogleOAuthUri.java | 26 +++++---------- backend/src/main/resources/application.yml | 4 ++- backend/src/test/resources/application.yml | 4 ++- 5 files changed, 26 insertions(+), 45 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/global/config/properties/GoogleProperties.java b/backend/src/main/java/com/allog/dallog/global/config/properties/GoogleProperties.java index 0ccfc750..c7dcf1e7 100644 --- a/backend/src/main/java/com/allog/dallog/global/config/properties/GoogleProperties.java +++ b/backend/src/main/java/com/allog/dallog/global/config/properties/GoogleProperties.java @@ -18,9 +18,8 @@ public class GoogleProperties { private final String grantType; public GoogleProperties(final String clientId, final String clientSecret, final String redirectUri, - final String oAuthEndPoint, - final String responseType, final List scopes, final String tokenUri, - final String grantType) { + final String oAuthEndPoint, final String responseType, final List scopes, + final String tokenUri, final String grantType) { this.clientId = clientId; this.clientSecret = clientSecret; this.redirectUri = redirectUri; diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java index 64ba6662..faea5afa 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java @@ -2,6 +2,7 @@ import com.allog.dallog.domain.auth.application.OAuthClient; import com.allog.dallog.domain.auth.dto.OAuthMember; +import com.allog.dallog.global.config.properties.GoogleProperties; import com.allog.dallog.infrastructure.oauth.dto.GoogleTokenResponse; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -9,7 +10,6 @@ import java.util.Base64; import java.util.HashMap; import java.util.Map; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -24,25 +24,13 @@ public class GoogleOAuthClient implements OAuthClient { private static final String JWT_DELIMITER = "\\."; - private final String clientId; - private final String clientSecret; - private final String grantType; - private final String redirectUri; - private final String tokenUri; + private final GoogleProperties googleProperties; private final RestTemplate restTemplate; private final ObjectMapper objectMapper; - public GoogleOAuthClient(@Value("${oauth.google.client-id}") final String clientId, - @Value("${oauth.google.client-secret}") final String clientSecret, - @Value("oauth.google.grant-type") final String grantType, - @Value("${oauth.google.redirect-uri}") final String redirectUri, - @Value("${oauth.google.token-uri}") final String tokenUri, - final RestTemplateBuilder restTemplateBuilder, final ObjectMapper objectMapper) { - this.clientId = clientId; - this.clientSecret = clientSecret; - this.grantType = grantType; - this.redirectUri = redirectUri; - this.tokenUri = tokenUri; + public GoogleOAuthClient(final GoogleProperties googleProperties, final RestTemplateBuilder restTemplateBuilder, + final ObjectMapper objectMapper) { + this.googleProperties = googleProperties; this.restTemplate = restTemplateBuilder.build(); this.objectMapper = objectMapper; } @@ -66,16 +54,16 @@ private GoogleTokenResponse requestGoogleToken(final String code) { MultiValueMap params = generateRequestParams(code); HttpEntity> request = new HttpEntity<>(params, headers); - return restTemplate.postForEntity(tokenUri, request, GoogleTokenResponse.class).getBody(); + return restTemplate.postForEntity(googleProperties.getTokenUri(), request, GoogleTokenResponse.class).getBody(); } private MultiValueMap generateRequestParams(final String code) { MultiValueMap params = new LinkedMultiValueMap<>(); - params.add("client_id", clientId); - params.add("client_secret", clientSecret); + params.add("client_id", googleProperties.getClientId()); + params.add("client_secret", googleProperties.getClientSecret()); params.add("code", code); - params.add("grant_type", grantType); - params.add("redirect_uri", redirectUri); + params.add("grant_type", googleProperties.getGrantType()); + params.add("redirect_uri", googleProperties.getRedirectUri()); return params; } diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java index 381450d8..12024f25 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/uri/GoogleOAuthUri.java @@ -1,34 +1,24 @@ package com.allog.dallog.infrastructure.oauth.uri; import com.allog.dallog.domain.auth.application.OAuthUri; -import java.util.List; -import org.springframework.beans.factory.annotation.Value; +import com.allog.dallog.global.config.properties.GoogleProperties; import org.springframework.stereotype.Component; @Component public class GoogleOAuthUri implements OAuthUri { - private final String oauthEndPoint; - private final String clientId; - private final String redirectUri; - private final List scopes; + private final GoogleProperties googleProperties; - public GoogleOAuthUri(@Value("${oauth.google.oauth-end-point}") final String oauthEndPoint, - @Value("${oauth.google.client-id}") final String clientId, - @Value("${oauth.google.redirect-uri}") final String redirectUri, - @Value("${oauth.google.scopes}") final List scopes) { - this.oauthEndPoint = oauthEndPoint; - this.clientId = clientId; - this.redirectUri = redirectUri; - this.scopes = scopes; + public GoogleOAuthUri(final GoogleProperties googleProperties) { + this.googleProperties = googleProperties; } @Override public String generate() { - return oauthEndPoint + "?" - + "client_id=" + clientId + "&" - + "redirect_uri=" + redirectUri + "&" + return googleProperties.getoAuthEndPoint() + "?" + + "client_id=" + googleProperties.getClientId() + "&" + + "redirect_uri=" + googleProperties.getRedirectUri() + "&" + "response_type=code&" - + "scope=" + String.join(" ", scopes); + + "scope=" + String.join(" ", googleProperties.getScopes()); } } diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 9a2d4f3e..c4f6fff4 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -28,7 +28,9 @@ oauth: redirect-uri: ${GOOGLE_REDIRECT_URI} oauth-end-point: https://accounts.google.com/o/oauth2/v2/auth response-type: code - scopes: https://www.googleapis.com/auth/userinfo.profile, https://www.googleapis.com/auth/userinfo.email + scopes: + - https://www.googleapis.com/auth/userinfo.profile + - https://www.googleapis.com/auth/userinfo.email token-uri: ${GOOGLE_TOKEN_URI} grant-type: authorization_code diff --git a/backend/src/test/resources/application.yml b/backend/src/test/resources/application.yml index a03967c5..9541b43b 100644 --- a/backend/src/test/resources/application.yml +++ b/backend/src/test/resources/application.yml @@ -30,7 +30,9 @@ oauth: redirect-uri: http://localhost:3000 oauth-end-point: https://accounts.google.com/o/oauth2/v2/auth response-type: code - scopes: https://www.googleapis.com/auth/userinfo.profile, https://www.googleapis.com/auth/userinfo.email + scopes: + - https://www.googleapis.com/auth/userinfo.profile + - https://www.googleapis.com/auth/userinfo.email token-uri: https://oauth2.googleapis.com/token grant-type: authorization_code From 24e487124fb21b949a3a950c0193d212660ab350 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Tue, 26 Jul 2022 19:55:43 +0900 Subject: [PATCH 0334/1011] =?UTF-8?q?refactor:=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SubscribeButton.stories.tsx | 15 ------------- .../SubscribeButton/SubscribeButton.styles.ts | 16 -------------- .../SubscribeButton/SubscribeButton.tsx | 22 ------------------- 3 files changed, 53 deletions(-) delete mode 100644 frontend/src/components/SubscribeButton/SubscribeButton.stories.tsx delete mode 100644 frontend/src/components/SubscribeButton/SubscribeButton.styles.ts delete mode 100644 frontend/src/components/SubscribeButton/SubscribeButton.tsx diff --git a/frontend/src/components/SubscribeButton/SubscribeButton.stories.tsx b/frontend/src/components/SubscribeButton/SubscribeButton.stories.tsx deleted file mode 100644 index 2fc7f66f..00000000 --- a/frontend/src/components/SubscribeButton/SubscribeButton.stories.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; - -import SubscribeButton from './SubscribeButton'; - -export default { - title: 'Components/SubscribeButton', - component: SubscribeButton, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ; - -export const Primary = Template.bind({}); -Primary.args = { - isSubscribing: true, -}; diff --git a/frontend/src/components/SubscribeButton/SubscribeButton.styles.ts b/frontend/src/components/SubscribeButton/SubscribeButton.styles.ts deleted file mode 100644 index d33b6460..00000000 --- a/frontend/src/components/SubscribeButton/SubscribeButton.styles.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -const subscribeButton = ({ colors }: Theme, isSubscribing: boolean) => css` - width: 15rem; - height: 8rem; - border-radius: 3px; - - background-color: ${isSubscribing ? colors.GRAY_500 : colors.YELLOW_500}; - - font-size: 3.5rem; - font-weight: 700; - line-height: 3.5rem; - color: ${colors.WHITE}; -`; - -export { subscribeButton }; diff --git a/frontend/src/components/SubscribeButton/SubscribeButton.tsx b/frontend/src/components/SubscribeButton/SubscribeButton.tsx deleted file mode 100644 index e9f96b46..00000000 --- a/frontend/src/components/SubscribeButton/SubscribeButton.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { useTheme } from '@emotion/react'; - -import Button from '@/components/@common/Button/Button'; - -import { subscribeButton } from './SubscribeButton.styles'; - -interface SubscribeButtonProps { - isSubscribing: boolean; - handleClickSubscribeButton: () => void; -} - -function SubscribeButton({ isSubscribing, handleClickSubscribeButton }: SubscribeButtonProps) { - const theme = useTheme(); - - return ( - - ); -} - -export default SubscribeButton; From 9326fbe99a78763ddfd15ab97e0193b96e7513b0 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 27 Jul 2022 12:32:44 +0900 Subject: [PATCH 0335/1011] =?UTF-8?q?refactor:=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=95=84=EC=9D=B4=ED=85=9C=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../CategoryItem/CategoryItem.stories.tsx | 17 ---- .../CategoryItem/CategoryItem.styles.ts | 19 ----- .../components/CategoryItem/CategoryItem.tsx | 78 ------------------- 3 files changed, 114 deletions(-) delete mode 100644 frontend/src/components/CategoryItem/CategoryItem.stories.tsx delete mode 100644 frontend/src/components/CategoryItem/CategoryItem.styles.ts delete mode 100644 frontend/src/components/CategoryItem/CategoryItem.tsx diff --git a/frontend/src/components/CategoryItem/CategoryItem.stories.tsx b/frontend/src/components/CategoryItem/CategoryItem.stories.tsx deleted file mode 100644 index 477f9f01..00000000 --- a/frontend/src/components/CategoryItem/CategoryItem.stories.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { ComponentMeta, ComponentStory } from '@storybook/react'; - -import { profileDB } from '@/mocks/data'; - -import CategoryItem from './CategoryItem'; - -export default { - title: 'Components/CategoryItem', - component: CategoryItem, -} as ComponentMeta; - -const Template: ComponentStory = (args) => ; - -export const Primary = Template.bind({}); -Primary.args = { - category: { id: 1, name: '달록 공식 일정', createdAt: '2022-07-04T13:00:00', creator: profileDB }, -}; diff --git a/frontend/src/components/CategoryItem/CategoryItem.styles.ts b/frontend/src/components/CategoryItem/CategoryItem.styles.ts deleted file mode 100644 index 37a15b49..00000000 --- a/frontend/src/components/CategoryItem/CategoryItem.styles.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { css, Theme } from '@emotion/react'; - -const categoryItem = ({ colors, flex }: Theme) => css` - ${flex.row} - - justify-content:space-around; - - height: 20rem; - border-bottom: 1px solid ${colors.GRAY_400}; - - font-size: 4rem; -`; - -const item = css` - flex: 1 1 0; - text-align: center; -`; - -export { categoryItem, item }; diff --git a/frontend/src/components/CategoryItem/CategoryItem.tsx b/frontend/src/components/CategoryItem/CategoryItem.tsx deleted file mode 100644 index edfff5b0..00000000 --- a/frontend/src/components/CategoryItem/CategoryItem.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { useTheme } from '@emotion/react'; -import { AxiosError, AxiosResponse } from 'axios'; -import { useMutation, useQueryClient } from 'react-query'; -import { useRecoilValue } from 'recoil'; - -import { CategoryType } from '@/@types/category'; -import { SubscriptionType } from '@/@types/subscription'; - -import { userState } from '@/recoil/atoms'; - -import SubscribeButton from '@/components/SubscribeButton/SubscribeButton'; - -import { CACHE_KEY, CONFIRM_MESSAGE } from '@/constants'; - -import subscriptionApi from '@/api/subscription'; - -import { categoryItem, item } from './CategoryItem.styles'; - -interface CategoryItemProps { - category: CategoryType; - subscriptionId: number; -} - -function CategoryItem({ category, subscriptionId }: CategoryItemProps) { - const theme = useTheme(); - const queryClient = useQueryClient(); - - const { accessToken } = useRecoilValue(userState); - - const body = { - color: '#ffffff', - }; - - const { mutate: postSubscription } = useMutation< - AxiosResponse>, - AxiosError, - Pick, - unknown - >(() => subscriptionApi.post(accessToken, category.id, body), { - onSuccess: () => { - queryClient.invalidateQueries(CACHE_KEY.SUBSCRIPTIONS); - }, - }); - - const { mutate: deleteSubscription } = useMutation( - () => subscriptionApi.delete(accessToken, subscriptionId), - { - onSuccess: () => { - queryClient.invalidateQueries(CACHE_KEY.SUBSCRIPTIONS); - }, - } - ); - - const unsubscribe = () => { - if (window.confirm(CONFIRM_MESSAGE.UNSUBSCRIBE)) { - deleteSubscription(); - } - }; - - const handleClickSubscribeButton = () => { - subscriptionId > 0 ? unsubscribe() : postSubscription(body); - }; - - return ( -
- {category.createdAt.split('T')[0]} - {category.name} -
- 0} - handleClickSubscribeButton={handleClickSubscribeButton} - > -
-
- ); -} - -export default CategoryItem; From 906dd05b47fadbb8cc027e2d3e23e8bf5e2acfce Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 27 Jul 2022 12:34:48 +0900 Subject: [PATCH 0336/1011] =?UTF-8?q?feat:=20=EA=B5=AC=EB=8F=85=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=EB=B3=84=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../SubscribedCategoryItem.styles.ts | 32 ++++++++++ .../SubscribedCategoryItem.tsx | 53 ++++++++++++++++ .../UnsubscribedCategoryItem.styles.ts | 32 ++++++++++ .../UnsubscribedCategoryItem.tsx | 61 +++++++++++++++++++ 4 files changed, 178 insertions(+) create mode 100644 frontend/src/components/SubscribedCategoryItem/SubscribedCategoryItem.styles.ts create mode 100644 frontend/src/components/SubscribedCategoryItem/SubscribedCategoryItem.tsx create mode 100644 frontend/src/components/UnsubscribedCategoryItem/UnsubscribedCategoryItem.styles.ts create mode 100644 frontend/src/components/UnsubscribedCategoryItem/UnsubscribedCategoryItem.tsx diff --git a/frontend/src/components/SubscribedCategoryItem/SubscribedCategoryItem.styles.ts b/frontend/src/components/SubscribedCategoryItem/SubscribedCategoryItem.styles.ts new file mode 100644 index 00000000..3efc53c1 --- /dev/null +++ b/frontend/src/components/SubscribedCategoryItem/SubscribedCategoryItem.styles.ts @@ -0,0 +1,32 @@ +import { css, Theme } from '@emotion/react'; + +const categoryItem = ({ colors, flex }: Theme) => css` + ${flex.row} + + justify-content:space-around; + + height: 20rem; + border-bottom: 1px solid ${colors.GRAY_400}; + + font-size: 4rem; +`; + +const item = css` + flex: 1 1 0; + text-align: center; +`; + +const unsubscribeButton = ({ colors }: Theme) => css` + width: 15rem; + height: 8rem; + border-radius: 3px; + + background-color: ${colors.GRAY_500}; + + font-size: 3.5rem; + font-weight: 700; + line-height: 3.5rem; + color: ${colors.WHITE}; +`; + +export { categoryItem, item, unsubscribeButton }; diff --git a/frontend/src/components/SubscribedCategoryItem/SubscribedCategoryItem.tsx b/frontend/src/components/SubscribedCategoryItem/SubscribedCategoryItem.tsx new file mode 100644 index 00000000..b6746970 --- /dev/null +++ b/frontend/src/components/SubscribedCategoryItem/SubscribedCategoryItem.tsx @@ -0,0 +1,53 @@ +import { useTheme } from '@emotion/react'; +import { useMutation, useQueryClient } from 'react-query'; +import { useRecoilValue } from 'recoil'; + +import { CategoryType } from '@/@types/category'; + +import { userState } from '@/recoil/atoms'; + +import Button from '@/components/@common/Button/Button'; + +import { CACHE_KEY, CONFIRM_MESSAGE } from '@/constants'; + +import subscriptionApi from '@/api/subscription'; + +import { categoryItem, item, unsubscribeButton } from './SubscribedCategoryItem.styles'; + +interface SubscribedCategoryItemProps { + category: CategoryType; + subscriptionId: number; +} + +function SubscribedCategoryItem({ category, subscriptionId }: SubscribedCategoryItemProps) { + const theme = useTheme(); + + const { accessToken } = useRecoilValue(userState); + + const queryClient = useQueryClient(); + const { mutate } = useMutation(() => subscriptionApi.delete(accessToken, subscriptionId), { + onSuccess: () => { + queryClient.invalidateQueries(CACHE_KEY.SUBSCRIPTIONS); + }, + }); + + const handleClickUnsubscribeButton = () => { + if (window.confirm(CONFIRM_MESSAGE.UNSUBSCRIBE)) { + mutate(); + } + }; + + return ( +
+ {category.createdAt.split('T')[0]} + {category.name} +
+ +
+
+ ); +} + +export default SubscribedCategoryItem; diff --git a/frontend/src/components/UnsubscribedCategoryItem/UnsubscribedCategoryItem.styles.ts b/frontend/src/components/UnsubscribedCategoryItem/UnsubscribedCategoryItem.styles.ts new file mode 100644 index 00000000..3a4f8d13 --- /dev/null +++ b/frontend/src/components/UnsubscribedCategoryItem/UnsubscribedCategoryItem.styles.ts @@ -0,0 +1,32 @@ +import { css, Theme } from '@emotion/react'; + +const categoryItem = ({ colors, flex }: Theme) => css` + ${flex.row} + + justify-content:space-around; + + height: 20rem; + border-bottom: 1px solid ${colors.GRAY_400}; + + font-size: 4rem; +`; + +const item = css` + flex: 1 1 0; + text-align: center; +`; + +const subscribeButton = ({ colors }: Theme) => css` + width: 15rem; + height: 8rem; + border-radius: 3px; + + background-color: ${colors.YELLOW_500}; + + font-size: 3.5rem; + font-weight: 700; + line-height: 3.5rem; + color: ${colors.WHITE}; +`; + +export { categoryItem, item, subscribeButton }; diff --git a/frontend/src/components/UnsubscribedCategoryItem/UnsubscribedCategoryItem.tsx b/frontend/src/components/UnsubscribedCategoryItem/UnsubscribedCategoryItem.tsx new file mode 100644 index 00000000..396a4f56 --- /dev/null +++ b/frontend/src/components/UnsubscribedCategoryItem/UnsubscribedCategoryItem.tsx @@ -0,0 +1,61 @@ +import { useTheme } from '@emotion/react'; +import { AxiosError, AxiosResponse } from 'axios'; +import { useMutation, useQueryClient } from 'react-query'; +import { useRecoilValue } from 'recoil'; + +import { CategoryType } from '@/@types/category'; +import { SubscriptionType } from '@/@types/subscription'; + +import { userState } from '@/recoil/atoms'; + +import Button from '@/components/@common/Button/Button'; + +import { CACHE_KEY } from '@/constants'; + +import subscriptionApi from '@/api/subscription'; + +import { categoryItem, item, subscribeButton } from './UnsubscribedCategoryItem.styles'; + +interface UnsubscribedCategoryItemProps { + category: CategoryType; +} + +function UnsubscribedCategoryItem({ category }: UnsubscribedCategoryItemProps) { + const theme = useTheme(); + + const { accessToken } = useRecoilValue(userState); + + const body = { + color: '#ffffff', + }; + + const queryClient = useQueryClient(); + const { mutate } = useMutation< + AxiosResponse>, + AxiosError, + Pick, + unknown + >(() => subscriptionApi.post(accessToken, category.id, body), { + onSuccess: () => { + queryClient.invalidateQueries(CACHE_KEY.SUBSCRIPTIONS); + }, + }); + + const handleClickSubscribeButton = () => { + mutate(body); + }; + + return ( +
+ {category.createdAt.split('T')[0]} + {category.name} +
+ +
+
+ ); +} + +export default UnsubscribedCategoryItem; From 3367cd4eaaa44f69a4e5d0536e04446e32982ab3 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 27 Jul 2022 12:36:03 +0900 Subject: [PATCH 0337/1011] =?UTF-8?q?refactor:=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=A1=B0=ED=9A=8C=20api=20=ED=98=B8?= =?UTF-8?q?=EC=B6=9C=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Daye Lee <508yeah@gmail.com> --- .../CategoryList/CategoryList.stories.tsx | 2 +- .../components/CategoryList/CategoryList.tsx | 68 ++++++++++++------- .../src/pages/CategoryPage/CategoryPage.tsx | 43 +----------- 3 files changed, 47 insertions(+), 66 deletions(-) diff --git a/frontend/src/components/CategoryList/CategoryList.stories.tsx b/frontend/src/components/CategoryList/CategoryList.stories.tsx index 9bd630f9..c3ae1306 100644 --- a/frontend/src/components/CategoryList/CategoryList.stories.tsx +++ b/frontend/src/components/CategoryList/CategoryList.stories.tsx @@ -9,7 +9,7 @@ export default { component: CategoryList, } as ComponentMeta; -const Template: ComponentStory = (args) => ; +const Template: ComponentStory = () => ; export const Primary = Template.bind({}); Primary.args = { diff --git a/frontend/src/components/CategoryList/CategoryList.tsx b/frontend/src/components/CategoryList/CategoryList.tsx index f4005b3e..30f36481 100644 --- a/frontend/src/components/CategoryList/CategoryList.tsx +++ b/frontend/src/components/CategoryList/CategoryList.tsx @@ -1,46 +1,62 @@ import { AxiosError, AxiosResponse } from 'axios'; -import { FetchNextPageOptions, InfiniteQueryObserverResult, useQuery } from 'react-query'; +import { useInfiniteQuery, useQuery } from 'react-query'; import { useRecoilValue } from 'recoil'; import useIntersect from '@/hooks/useIntersect'; -import { CategoriesGetResponseType, CategoryType } from '@/@types/category'; +import { CategoriesGetResponseType } from '@/@types/category'; import { SubscriptionType } from '@/@types/subscription'; import { userState } from '@/recoil/atoms'; -import CategoryItem from '@/components/CategoryItem/CategoryItem'; +import SubscribedCategoryItem from '@/components/SubscribedCategoryItem/SubscribedCategoryItem'; +import UnsubscribedCategoryItem from '@/components/UnsubscribedCategoryItem/UnsubscribedCategoryItem'; -import { CACHE_KEY } from '@/constants'; +import { API, CACHE_KEY } from '@/constants'; +import categoryApi from '@/api/category'; import subscriptionApi from '@/api/subscription'; import { categoryTable, categoryTableHeader, intersectTarget, item } from './CategoryList.styles'; -interface CategoryListProps { - categoryList: CategoryType[]; - getMoreCategories: ( - options?: FetchNextPageOptions | undefined - ) => Promise, AxiosError>>; - hasNextPage: boolean | undefined; -} - -function CategoryList({ categoryList, getMoreCategories, hasNextPage }: CategoryListProps) { +function CategoryList() { const { accessToken } = useRecoilValue(userState); - const { data: subscriptionsGetResponse } = useQuery< + const { + isLoading: isCategoriesLoading, + data: categoriesGetResponse, + fetchNextPage, + hasNextPage, + } = useInfiniteQuery, AxiosError>( + CACHE_KEY.CATEGORIES, + ({ pageParam = 0 }) => categoryApi.get(pageParam, API.CATEGORY_GET_SIZE), + { + getNextPageParam: ({ data }) => { + if (data.categories.length > 0) { + return data.page + 1; + } + }, + } + ); + + const { isLoading: isSubscriptionsLoading, data: subscriptionsGetResponse } = useQuery< AxiosResponse, AxiosError >(CACHE_KEY.SUBSCRIPTIONS, () => subscriptionApi.get(accessToken)); const ref = useIntersect(() => { - hasNextPage && getMoreCategories(); + hasNextPage && fetchNextPage(); }); - if (subscriptionsGetResponse === undefined) { - return
; + if (isCategoriesLoading || categoriesGetResponse === undefined) { + return
Loading
; } + if (isSubscriptionsLoading || subscriptionsGetResponse === undefined) { + return
구독 Loading
; + } + + const categoryList = categoriesGetResponse.pages.flatMap(({ data }) => data.categories); const subscriptionList = subscriptionsGetResponse.data.map((el) => { return { subscriptionId: el.id, @@ -57,17 +73,23 @@ function CategoryList({ categoryList, getMoreCategories, hasNextPage }: Category
{categoryList.map((category) => { - const { subscriptionId } = subscriptionList.find( + const subscribedCategoryInfo = subscriptionList.find( (el) => el.categoryId === category.id - ) ?? { - subscriptionId: -1, - }; + ); + + if (subscribedCategoryInfo === undefined) { + return ; + } return ( - + ); })} -
+
); diff --git a/frontend/src/pages/CategoryPage/CategoryPage.tsx b/frontend/src/pages/CategoryPage/CategoryPage.tsx index b225dc21..bce98088 100644 --- a/frontend/src/pages/CategoryPage/CategoryPage.tsx +++ b/frontend/src/pages/CategoryPage/CategoryPage.tsx @@ -1,58 +1,17 @@ -import { AxiosError, AxiosResponse } from 'axios'; -import { useInfiniteQuery } from 'react-query'; - -import { CategoriesGetResponseType } from '@/@types/category'; - import FieldSet from '@/components/@common/FieldSet/FieldSet'; import PageLayout from '@/components/@common/PageLayout/PageLayout'; import CategoryList from '@/components/CategoryList/CategoryList'; -import { API, CACHE_KEY } from '@/constants'; - -import categoryApi from '@/api/category'; - import { categoryNav, categoryPage, categorySearch } from './CategoryPage.styles'; function CategoryPage() { - const { - isLoading, - error, - data: categoriesGetResponse, - fetchNextPage, - hasNextPage, - } = useInfiniteQuery, AxiosError>( - CACHE_KEY.CATEGORIES, - ({ pageParam = 0 }) => categoryApi.get(pageParam, API.CATEGORY_GET_SIZE), - { - getNextPageParam: ({ data }) => { - if (data.categories.length > 0) { - return data.page + 1; - } - }, - } - ); - - if (isLoading || categoriesGetResponse === undefined) { - return
Loading
; - } - - if (error) { - return
Error
; - } - - const categoryList = categoriesGetResponse.pages.flatMap(({ data }) => data.categories); - return (
- +
); From ef194c50d3dd9e8c1f8640e5066691c379b71117 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 27 Jul 2022 13:38:45 +0900 Subject: [PATCH 0338/1011] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EA=B2=A9=EB=A6=AC=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20DirtiesContext=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/allog/dallog/acceptance/AcceptanceTest.java | 4 ++-- backend/src/test/resources/truncate.sql | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 backend/src/test/resources/truncate.sql diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java index 995d318e..e8f7e7ba 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java @@ -6,10 +6,10 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.context.annotation.Import; -import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.jdbc.Sql; -@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@Sql("/truncate.sql") @Import(TestConfig.class) class AcceptanceTest { diff --git a/backend/src/test/resources/truncate.sql b/backend/src/test/resources/truncate.sql new file mode 100644 index 00000000..5edd93f7 --- /dev/null +++ b/backend/src/test/resources/truncate.sql @@ -0,0 +1,7 @@ +SET +foreign_key_checks = 0; +TRUNCATE TABLE subscriptions; +TRUNCATE TABLE categories; +TRUNCATE TABLE members; +SET +foreign_key_checks = 1; From b905b936f86978dff9171783f58864d449f4f81e Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 26 Jul 2022 19:40:28 +0900 Subject: [PATCH 0339/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=82=AD=EC=A0=9C=20=EC=8B=9C=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=EC=97=AC=EB=B6=80=20=ED=99=95=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 카테고리 수정 시 존재여부 확인 로직에 대한 테스트 코드 추가 --- .../category/application/CategoryService.java | 7 +++++ .../application/CategoryServiceTest.java | 26 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/backend/src/main/java/com/allog/dallog/domain/category/application/CategoryService.java b/backend/src/main/java/com/allog/dallog/domain/category/application/CategoryService.java index 49e560ac..2f7e5141 100644 --- a/backend/src/main/java/com/allog/dallog/domain/category/application/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/application/CategoryService.java @@ -69,11 +69,18 @@ public void update(final Long memberId, final Long categoryId, final CategoryUpd public void delete(final Long memberId, final Long categoryId) { memberService.getMember(memberId); + validateCategoryExisting(categoryId); validatePermission(memberId, categoryId); categoryRepository.deleteById(categoryId); } + private void validateCategoryExisting(final Long categoryId) { + if (!categoryRepository.existsById(categoryId)) { + throw new NoSuchCategoryException("존재하지 않는 카테고리를 삭제할 수 없습니다."); + } + } + private void validatePermission(final Long memberId, final Long categoryId) { if (!categoryRepository.existsByIdAndMemberId(categoryId, memberId)) { throw new NoPermissionException(); diff --git a/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java index 4616b27a..7be02f02 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java @@ -1,6 +1,7 @@ package com.allog.dallog.domain.category.application; import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_이름; import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_생성_요청; import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_이름; import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_생성_요청; @@ -147,6 +148,19 @@ class CategoryServiceTest { assertThat(category.getName()).isEqualTo(우테코_공통_일정_이름); } + @DisplayName("존재하지 않는 카테고리를 수정할 경우 예외를 던진다.") + @Test + void 존재하지_않는_카테고리를_수정할_경우_예외를_던진다() { + // given + Member 관리자 = memberRepository.save(관리자()); + CategoryResponse 공통_일정 = categoryService.save(관리자.getId(), 공통_일정_생성_요청); + CategoryUpdateRequest categoryUpdateRequest = new CategoryUpdateRequest(BE_일정_이름); + + // when & then + assertThatThrownBy(() -> categoryService.update(관리자.getId(), 공통_일정.getId() + 1, categoryUpdateRequest)) + .isInstanceOf(NoSuchCategoryException.class); + } + @DisplayName("자신이 만들지 않은 카테고리를 수정할 경우 예외를 던진다.") @Test void 자신이_만들지_않은_카테고리를_수정할_경우_예외를_던진다() { @@ -177,6 +191,18 @@ class CategoryServiceTest { .isInstanceOf(NoSuchCategoryException.class); } + @DisplayName("존재하지 않는 카테고리를 삭제할 경우 예외를 던진다.") + @Test + void 존재하지_않는_카테고리를_삭제할_경우_예외를_던진다() { + // given + Member 관리자 = memberRepository.save(관리자()); + CategoryResponse 공통_일정 = categoryService.save(관리자.getId(), 공통_일정_생성_요청); + + // when & then + assertThatThrownBy(() -> categoryService.delete(관리자.getId(), 공통_일정.getId() + 1)) + .isInstanceOf(NoSuchCategoryException.class); + } + @DisplayName("자신이 만들지 않은 카테고리를 삭제할 경우 예외를 던진다.") @Test void 자신이_만들지_않은_카테고리를_삭제할_경우_예외를_던진다() { From 72bab8572afaaee7e93c7b5cfce2a2b07fee217c Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 26 Jul 2022 19:47:06 +0900 Subject: [PATCH 0340/1011] =?UTF-8?q?test:=20id=EB=A1=9C=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EB=8B=A8=EA=B1=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=8B=9C=20=EC=A1=B4=EC=9E=AC=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8A=94=20=EC=BC=80=EC=9D=B4=EC=8A=A4=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/application/CategoryServiceTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java index 7be02f02..86cf7f17 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java @@ -130,6 +130,18 @@ class CategoryServiceTest { .isEqualTo(공통_일정); } + @DisplayName("id를 통해 카테고리를 단건 조회할 때 카테고리가 존재하지 않다면 예외가 발생한다.") + @Test + void id를_통해_카테고리를_단건_조회할_때_카테고리가_존재하지_않다면_예외가_발생한다() { + // given + Member creator = memberRepository.save(관리자()); + CategoryResponse 공통_일정 = categoryService.save(creator.getId(), 공통_일정_생성_요청); + + // when & then + assertThatThrownBy(() -> categoryService.findById(공통_일정.getId() + 1)) + .isInstanceOf(NoSuchCategoryException.class); + } + @DisplayName("회원과 카테고리 id를 통해 카테고리를 수정한다.") @Test void 회원과_카테고리_id를_통해_카테고리를_수정한다() { From 28f9ebbd4167efec9ed646e3bb29ae7c227ff1a8 Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 26 Jul 2022 19:52:53 +0900 Subject: [PATCH 0341/1011] =?UTF-8?q?refactor:=20final=20=ED=82=A4?= =?UTF-8?q?=EC=9B=8C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/domain/category/presentation/CategoryController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/allog/dallog/domain/category/presentation/CategoryController.java b/backend/src/main/java/com/allog/dallog/domain/category/presentation/CategoryController.java index e4cefb29..fe0f5115 100644 --- a/backend/src/main/java/com/allog/dallog/domain/category/presentation/CategoryController.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/presentation/CategoryController.java @@ -38,7 +38,7 @@ public ResponseEntity save(@AuthenticationPrincipal final Logi } @GetMapping - public ResponseEntity findAll(Pageable pageable) { + public ResponseEntity findAll(final Pageable pageable) { return ResponseEntity.ok(categoryService.findAll(pageable)); } From 85eeb51ff87784b5b9e27acda390f4869bad271b Mon Sep 17 00:00:00 2001 From: devHudi Date: Tue, 26 Jul 2022 20:24:34 +0900 Subject: [PATCH 0342/1011] =?UTF-8?q?feat:=20Spring=20JPA=20Data=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=B5=9C=EB=8C=80=20=ED=8E=98=EC=9D=B4=EC=A7=95=20?= =?UTF-8?q?=EC=82=AC=EC=9D=B4=EC=A6=88=EB=A5=BC=20100=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=9C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.yml | 7 ++++++- backend/src/test/resources/application.yml | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index c4f6fff4..920b1df4 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -12,7 +12,12 @@ spring: hibernate: ddl-auto: create defer-datasource-initialization: true - + + data: + web: + pageable: + max-page-size: 100 + h2: console: enabled: true diff --git a/backend/src/test/resources/application.yml b/backend/src/test/resources/application.yml index 9541b43b..3e38ccb0 100644 --- a/backend/src/test/resources/application.yml +++ b/backend/src/test/resources/application.yml @@ -19,6 +19,11 @@ spring: hibernate: ddl-auto: create + data: + web: + pageable: + max-page-size: 100 + logging: level: org.hibernate.type.descriptor.sql.BasicBinder: TRACE From bb8969306619962685abeac8eb28689e1be38b0c Mon Sep 17 00:00:00 2001 From: devHudi Date: Wed, 27 Jul 2022 11:50:43 +0900 Subject: [PATCH 0343/1011] =?UTF-8?q?refactor:=20=EB=A9=A4=EB=B2=84?= =?UTF-8?q?=EC=9D=98=20=EC=A1=B4=EC=9E=AC=EC=97=AC=EB=B6=80=EB=A5=BC=20?= =?UTF-8?q?=EA=B2=80=EC=82=AC=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20mem?= =?UTF-8?q?berService.getMember=20=ED=98=B8=EC=B6=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ArgumentResolver에서 멤버의 존재 여부를 검사해주기 때문에 제거가능 --- .../dallog/domain/category/application/CategoryService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/domain/category/application/CategoryService.java b/backend/src/main/java/com/allog/dallog/domain/category/application/CategoryService.java index 2f7e5141..96df1bc7 100644 --- a/backend/src/main/java/com/allog/dallog/domain/category/application/CategoryService.java +++ b/backend/src/main/java/com/allog/dallog/domain/category/application/CategoryService.java @@ -57,7 +57,6 @@ public Category getCategory(final Long id) { @Transactional public void update(final Long memberId, final Long categoryId, final CategoryUpdateRequest request) { - memberService.getMember(memberId); Category category = getCategory(categoryId); validatePermission(memberId, categoryId); @@ -67,8 +66,6 @@ public void update(final Long memberId, final Long categoryId, final CategoryUpd @Transactional public void delete(final Long memberId, final Long categoryId) { - memberService.getMember(memberId); - validateCategoryExisting(categoryId); validatePermission(memberId, categoryId); From 60addc7ce116ae6394570fa1f6f0e12969d7f738 Mon Sep 17 00:00:00 2001 From: devHudi Date: Wed, 27 Jul 2022 11:54:22 +0900 Subject: [PATCH 0344/1011] =?UTF-8?q?test:=20=ED=94=BD=EC=8A=A4=EC=B2=98?= =?UTF-8?q?=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=9C=20=EC=A7=80=EC=97=AD=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=EC=9D=98=20=EB=84=A4=EC=9D=B4=EB=B0=8D?= =?UTF-8?q?=EC=9D=84=20=ED=95=9C=EA=B8=80=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/CategoryServiceTest.java | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java b/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java index 86cf7f17..5aa3ec11 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/application/CategoryServiceTest.java @@ -47,10 +47,10 @@ class CategoryServiceTest { @Test void 새로운_카테고리를_생성한다() { // given - Member creator = memberRepository.save(관리자()); + Member 관리자 = memberRepository.save(관리자()); // when - CategoryResponse response = categoryService.save(creator.getId(), 공통_일정_생성_요청); + CategoryResponse response = categoryService.save(관리자.getId(), 공통_일정_생성_요청); // then assertThat(response.getName()).isEqualTo(공통_일정_이름); @@ -62,10 +62,10 @@ class CategoryServiceTest { void 새로운_카테고리를_생성_할_때_이름이_공백이거나_길이가_20을_초과하는_경우_예외를_던진다(final String name) { // given CategoryCreateRequest request = new CategoryCreateRequest(name); - Member creator = memberRepository.save(관리자()); + Member 관리자 = memberRepository.save(관리자()); // when & then - assertThatThrownBy(() -> categoryService.save(creator.getId(), request)) + assertThatThrownBy(() -> categoryService.save(관리자.getId(), request)) .isInstanceOf(InvalidCategoryException.class); } @@ -73,13 +73,13 @@ class CategoryServiceTest { @Test void 페이지를_받아_해당하는_구간의_카테고리를_가져온다() { // given - Member creator = memberRepository.save(관리자()); - Long creatorId = creator.getId(); - categoryService.save(creatorId, 공통_일정_생성_요청); - categoryService.save(creatorId, BE_일정_생성_요청); - categoryService.save(creatorId, FE_일정_생성_요청); - categoryService.save(creatorId, 매트_아고라_생성_요청); - categoryService.save(creatorId, 후디_JPA_스터디_생성_요청); + Member 관리자 = memberRepository.save(관리자()); + Long 관리자_ID = 관리자.getId(); + categoryService.save(관리자_ID, 공통_일정_생성_요청); + categoryService.save(관리자_ID, BE_일정_생성_요청); + categoryService.save(관리자_ID, FE_일정_생성_요청); + categoryService.save(관리자_ID, 매트_아고라_생성_요청); + categoryService.save(관리자_ID, 후디_JPA_스터디_생성_요청); PageRequest request = PageRequest.of(1, 2); @@ -97,18 +97,18 @@ class CategoryServiceTest { @Test void 회원_id와_페이지를_기반으로_카테고리를_가져온다() { // given - Member creator = memberRepository.save(관리자()); - Long creatorId = creator.getId(); - categoryService.save(creatorId, 공통_일정_생성_요청); - categoryService.save(creatorId, BE_일정_생성_요청); - categoryService.save(creatorId, FE_일정_생성_요청); - categoryService.save(creatorId, 매트_아고라_생성_요청); - categoryService.save(creatorId, 후디_JPA_스터디_생성_요청); + Member 관리자 = memberRepository.save(관리자()); + Long 관리자_ID = 관리자.getId(); + categoryService.save(관리자_ID, 공통_일정_생성_요청); + categoryService.save(관리자_ID, BE_일정_생성_요청); + categoryService.save(관리자_ID, FE_일정_생성_요청); + categoryService.save(관리자_ID, 매트_아고라_생성_요청); + categoryService.save(관리자_ID, 후디_JPA_스터디_생성_요청); PageRequest request = PageRequest.of(1, 2); // when - CategoriesResponse response = categoryService.findMine(creatorId, request); + CategoriesResponse response = categoryService.findMine(관리자_ID, request); // then assertThat(response.getCategories()) @@ -121,8 +121,8 @@ class CategoryServiceTest { @Test void id를_통해_카테고리를_단건_조회한다() { // given - Member creator = memberRepository.save(관리자()); - CategoryResponse 공통_일정 = categoryService.save(creator.getId(), 공통_일정_생성_요청); + Member 관리자 = memberRepository.save(관리자()); + CategoryResponse 공통_일정 = categoryService.save(관리자.getId(), 공통_일정_생성_요청); // when & then assertThat(categoryService.findById(공통_일정.getId())) @@ -134,8 +134,8 @@ class CategoryServiceTest { @Test void id를_통해_카테고리를_단건_조회할_때_카테고리가_존재하지_않다면_예외가_발생한다() { // given - Member creator = memberRepository.save(관리자()); - CategoryResponse 공통_일정 = categoryService.save(creator.getId(), 공통_일정_생성_요청); + Member 관리자 = memberRepository.save(관리자()); + CategoryResponse 공통_일정 = categoryService.save(관리자.getId(), 공통_일정_생성_요청); // when & then assertThatThrownBy(() -> categoryService.findById(공통_일정.getId() + 1)) @@ -146,14 +146,14 @@ class CategoryServiceTest { @Test void 회원과_카테고리_id를_통해_카테고리를_수정한다() { // given - Member creator = memberRepository.save(관리자()); - CategoryResponse 공통_일정 = categoryService.save(creator.getId(), 공통_일정_생성_요청); + Member 관리자 = memberRepository.save(관리자()); + CategoryResponse 공통_일정 = categoryService.save(관리자.getId(), 공통_일정_생성_요청); String 우테코_공통_일정_이름 = "우테코 공통 일정"; CategoryUpdateRequest categoryUpdateRequest = new CategoryUpdateRequest(우테코_공통_일정_이름); // when - categoryService.update(creator.getId(), 공통_일정.getId(), categoryUpdateRequest); + categoryService.update(관리자.getId(), 공통_일정.getId(), categoryUpdateRequest); Category category = categoryService.getCategory(공통_일정.getId()); //then @@ -193,13 +193,13 @@ class CategoryServiceTest { void 회원과_카테고리_id를_통해_카테고리를_삭제한다() { // given Member 관리자 = memberRepository.save(관리자()); - CategoryResponse savedCategory = categoryService.save(관리자.getId(), 공통_일정_생성_요청); + CategoryResponse 공통_일정 = categoryService.save(관리자.getId(), 공통_일정_생성_요청); // when - categoryService.delete(관리자.getId(), savedCategory.getId()); + categoryService.delete(관리자.getId(), 공통_일정.getId()); //then - assertThatThrownBy(() -> categoryService.getCategory(savedCategory.getId())) + assertThatThrownBy(() -> categoryService.getCategory(공통_일정.getId())) .isInstanceOf(NoSuchCategoryException.class); } @@ -221,11 +221,11 @@ class CategoryServiceTest { // given Member 관리자 = memberRepository.save(관리자()); Member 매트 = memberRepository.save(매트()); - CategoryResponse savedCategory = categoryService.save(관리자.getId(), 공통_일정_생성_요청); + CategoryResponse 공통_일정 = categoryService.save(관리자.getId(), 공통_일정_생성_요청); // when & then assertThatThrownBy( - () -> categoryService.delete(매트.getId(), savedCategory.getId())) + () -> categoryService.delete(매트.getId(), 공통_일정.getId())) .isInstanceOf(NoPermissionException.class); } } From 5aeb2165a3bcdbb0b8fb6cce0b09dedd5724f98f Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 27 Jul 2022 11:49:39 +0900 Subject: [PATCH 0345/1011] =?UTF-8?q?chore:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EA=B5=AC=EC=A1=B0=20=ED=86=B5=EC=9D=BC=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subscription/application/SubscriptionService.java | 2 +- .../{repository => domain}/SubscriptionRepository.java | 3 +-- .../{repository => domain}/SubscriptionRepositoryTest.java | 6 ++---- 3 files changed, 4 insertions(+), 7 deletions(-) rename backend/src/main/java/com/allog/dallog/domain/subscription/{repository => domain}/SubscriptionRepository.java (75%) rename backend/src/test/java/com/allog/dallog/domain/subscription/{repository => domain}/SubscriptionRepositoryTest.java (95%) diff --git a/backend/src/main/java/com/allog/dallog/domain/subscription/application/SubscriptionService.java b/backend/src/main/java/com/allog/dallog/domain/subscription/application/SubscriptionService.java index 873173c1..47420ada 100644 --- a/backend/src/main/java/com/allog/dallog/domain/subscription/application/SubscriptionService.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/application/SubscriptionService.java @@ -6,11 +6,11 @@ import com.allog.dallog.domain.member.application.MemberService; import com.allog.dallog.domain.member.domain.Member; import com.allog.dallog.domain.subscription.domain.Subscription; +import com.allog.dallog.domain.subscription.domain.SubscriptionRepository; import com.allog.dallog.domain.subscription.dto.request.SubscriptionCreateRequest; import com.allog.dallog.domain.subscription.dto.response.SubscriptionResponse; import com.allog.dallog.domain.subscription.dto.response.SubscriptionsResponse; import com.allog.dallog.domain.subscription.exception.NoSuchSubscriptionException; -import com.allog.dallog.domain.subscription.repository.SubscriptionRepository; import java.util.List; import java.util.stream.Collectors; import org.springframework.stereotype.Service; diff --git a/backend/src/main/java/com/allog/dallog/domain/subscription/repository/SubscriptionRepository.java b/backend/src/main/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepository.java similarity index 75% rename from backend/src/main/java/com/allog/dallog/domain/subscription/repository/SubscriptionRepository.java rename to backend/src/main/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepository.java index ceba97dd..f15e77e4 100644 --- a/backend/src/main/java/com/allog/dallog/domain/subscription/repository/SubscriptionRepository.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepository.java @@ -1,6 +1,5 @@ -package com.allog.dallog.domain.subscription.repository; +package com.allog.dallog.domain.subscription.domain; -import com.allog.dallog.domain.subscription.domain.Subscription; import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/backend/src/test/java/com/allog/dallog/domain/subscription/repository/SubscriptionRepositoryTest.java b/backend/src/test/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepositoryTest.java similarity index 95% rename from backend/src/test/java/com/allog/dallog/domain/subscription/repository/SubscriptionRepositoryTest.java rename to backend/src/test/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepositoryTest.java index 9ccdee9e..5bd62ee0 100644 --- a/backend/src/test/java/com/allog/dallog/domain/subscription/repository/SubscriptionRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepositoryTest.java @@ -1,4 +1,4 @@ -package com.allog.dallog.domain.subscription.repository; +package com.allog.dallog.domain.subscription.domain; import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정; import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정; @@ -12,11 +12,9 @@ import com.allog.dallog.domain.category.domain.Category; import com.allog.dallog.domain.category.domain.CategoryRepository; -import com.allog.dallog.domain.subscription.repository.SubscriptionRepository; -import com.allog.dallog.global.config.JpaConfig; import com.allog.dallog.domain.member.domain.Member; import com.allog.dallog.domain.member.domain.MemberRepository; -import com.allog.dallog.domain.subscription.domain.Subscription; +import com.allog.dallog.global.config.JpaConfig; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; From 60c85b207a416da44a31ec0559b95cd3400dd964 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 27 Jul 2022 12:03:16 +0900 Subject: [PATCH 0346/1011] =?UTF-8?q?test:=20=EB=88=84=EB=9D=BD=EB=90=9C?= =?UTF-8?q?=20SubscriptionRepository=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/SubscriptionRepository.java | 2 + .../domain/SubscriptionRepositoryTest.java | 60 ++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepository.java b/backend/src/main/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepository.java index f15e77e4..62cb1ad8 100644 --- a/backend/src/main/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepository.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepository.java @@ -5,6 +5,8 @@ public interface SubscriptionRepository extends JpaRepository { + boolean existsByMemberIdAndCategoryId(final Long memberId, final Long categoryId); + List findByMemberId(final Long memberId); boolean existsByIdAndMemberId(final Long id, final Long memberId); diff --git a/backend/src/test/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepositoryTest.java b/backend/src/test/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepositoryTest.java index 5bd62ee0..56d3d03e 100644 --- a/backend/src/test/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepositoryTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/subscription/domain/SubscriptionRepositoryTest.java @@ -4,6 +4,7 @@ import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정; import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정; import static com.allog.dallog.common.fixtures.MemberFixtures.관리자; +import static com.allog.dallog.common.fixtures.MemberFixtures.매트; import static com.allog.dallog.common.fixtures.MemberFixtures.후디; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.노란색_구독; import static com.allog.dallog.common.fixtures.SubscriptionFixtures.빨간색_구독; @@ -35,6 +36,39 @@ class SubscriptionRepositoryTest { @Autowired private SubscriptionRepository subscriptionRepository; + @DisplayName("존재하지 않는 카테고리를 확인할 경우 true를 반환한다.") + @Test + void 존재하지_않는_카테고리를_확인할_경우_true를_반환한다() { + // given + Member 관리자 = memberRepository.save(관리자()); + Category 공통_일정 = categoryRepository.save(공통_일정(관리자)); + + Member 매트 = memberRepository.save(매트()); + + // when + boolean actual = subscriptionRepository.existsByMemberIdAndCategoryId(매트.getId(), 공통_일정.getId()); + + // then + assertThat(actual).isFalse(); + } + + @DisplayName("이미 존재하는 카테고리를 확인할 경우 true를 반환한다.") + @Test + void 이미_존재하는_카테고리를_확인할_경우_true를_반환한다() { + // given + Member 관리자 = memberRepository.save(관리자()); + Category 공통_일정 = categoryRepository.save(공통_일정(관리자)); + + Member 매트 = memberRepository.save(매트()); + subscriptionRepository.save(빨간색_구독(매트, 공통_일정)); + + // when + boolean actual = subscriptionRepository.existsByMemberIdAndCategoryId(매트.getId(), 공통_일정.getId()); + + // then + assertThat(actual).isTrue(); + } + @DisplayName("회원 정보를 기반으로 구독 정보를 조회한다.") @Test void 회원_정보를_기반으로_구독_정보를_조회한다() { @@ -95,12 +129,34 @@ class SubscriptionRepositoryTest { @Test void 회원의_존재하지_않는_구독_정보_여부를_확인한다() { // given - Member member = memberRepository.save(관리자()); + Member 관리자 = memberRepository.save(관리자()); // when - boolean actual = subscriptionRepository.existsByIdAndMemberId(0L, member.getId()); + boolean actual = subscriptionRepository.existsByIdAndMemberId(0L, 관리자.getId()); // then assertThat(actual).isFalse(); } + + @DisplayName("구독 id와 member id를 활용하여 구독 정보를 삭제한다.") + @Test + void 구독_id와_member_id를_활용하여_구독_정보를_삭제한다() { + // given + Member 관리자 = memberRepository.save(관리자()); + Category 공통_일정 = categoryRepository.save(공통_일정(관리자)); + Category BE_일정 = categoryRepository.save(BE_일정(관리자)); + Category FE_일정 = categoryRepository.save(FE_일정(관리자)); + + Member 매트 = memberRepository.save(매트()); + Subscription 빨간색_구독 = subscriptionRepository.save(빨간색_구독(매트, 공통_일정)); + subscriptionRepository.save(파란색_구독(매트, BE_일정)); + subscriptionRepository.save(노란색_구독(매트, FE_일정)); + + // when + subscriptionRepository.deleteByIdAndMemberId(빨간색_구독.getId(), 매트.getId()); + + // then + List subscriptions = subscriptionRepository.findByMemberId(매트.getId()); + assertThat(subscriptions).hasSize(2); + } } From d92d848bb16cc1f29594d5acfab3bdea5eca0ce3 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 27 Jul 2022 13:15:27 +0900 Subject: [PATCH 0347/1011] =?UTF-8?q?feat:=20=EC=B4=88=EA=B8=B0=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=84=B8=ED=8C=85=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/main/resources/application.yml | 4 ++++ backend/src/main/resources/data.sql | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 920b1df4..bbe46df3 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -1,4 +1,8 @@ spring: + sql: + init: + mode: always + datasource: url: jdbc:h2:~/dallog;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE username: sa diff --git a/backend/src/main/resources/data.sql b/backend/src/main/resources/data.sql index 6da3b17d..eaf41c1c 100644 --- a/backend/src/main/resources/data.sql +++ b/backend/src/main/resources/data.sql @@ -7,7 +7,10 @@ VALUES ('admin@email.com', '귀요미 나인', 'GOOGLE', NOW(), NOW()), ('508yeah@gmail.com', 'https://file.namu.moe/file/8bc9e381797334eb33da66e3ba501be13bacd109d2d9b5f117ad0bb781574b9cb612e8226803fc6831128bc2945e5f7d2231ed68ff43ae17d3aeb6bb6947b668', - '티거', 'GOOGLE', NOW(), NOW()); + '티거', 'GOOGLE', NOW(), NOW()), + ('dev.hyeonic@gmail.com', + 'https://file.namu.moe/file/8bc9e381797334eb33da66e3ba501be13bacd109d2d9b5f117ad0bb781574b9cb612e8226803fc6831128bc2945e5f7d2231ed68ff43ae17d3aeb6bb6947b668', + '매트', 'GOOGLE', NOW(), NOW()); INSERT INTO categories (name, members_id, created_at, updated_at) VALUES ('공통 일정', 1, NOW(), NOW()), @@ -23,4 +26,6 @@ INSERT INTO subscriptions (members_id, categories_id, color, created_at, updated VALUES (2, 1, '#868e96', NOW(), NOW()), (2, 3, '#ffdeeb', NOW(), NOW()), (3, 1, '#d0bfff', NOW(), NOW()), - (3, 3, '#4263eb', NOW(), NOW()); + (3, 3, '#4263eb', NOW(), NOW()), + (4, 1, '#ffffff', NOW(), NOW()), + (4, 2, '#000000', NOW(), NOW()); From 41ec66fcf7ec37e4331745b8411d92c70a2788f5 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 27 Jul 2022 13:16:14 +0900 Subject: [PATCH 0348/1011] =?UTF-8?q?feat:=20=EC=A1=B4=EC=9E=AC=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EA=B5=AC=EB=8F=85=20=EC=A0=95=EB=B3=B4=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/ExistSubscriptionException.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/domain/subscription/exception/ExistSubscriptionException.java diff --git a/backend/src/main/java/com/allog/dallog/domain/subscription/exception/ExistSubscriptionException.java b/backend/src/main/java/com/allog/dallog/domain/subscription/exception/ExistSubscriptionException.java new file mode 100644 index 00000000..260a893b --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/exception/ExistSubscriptionException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.domain.subscription.exception; + +public class ExistSubscriptionException extends RuntimeException { + + public ExistSubscriptionException(final String message) { + super(message); + } + + public ExistSubscriptionException() { + this("이미 존재하는 구독 정보 입니다."); + } +} From 544d8821372c8cf842f59e630b7ba0c4ed675f49 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 27 Jul 2022 13:16:37 +0900 Subject: [PATCH 0349/1011] =?UTF-8?q?feat:=20subscription=20service=20?= =?UTF-8?q?=EB=88=84=EB=9D=BD=EB=90=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/SubscriptionService.java | 6 ++++++ .../application/SubscriptionServiceTest.java | 19 ++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/domain/subscription/application/SubscriptionService.java b/backend/src/main/java/com/allog/dallog/domain/subscription/application/SubscriptionService.java index 47420ada..e5def661 100644 --- a/backend/src/main/java/com/allog/dallog/domain/subscription/application/SubscriptionService.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/application/SubscriptionService.java @@ -10,6 +10,7 @@ import com.allog.dallog.domain.subscription.dto.request.SubscriptionCreateRequest; import com.allog.dallog.domain.subscription.dto.response.SubscriptionResponse; import com.allog.dallog.domain.subscription.dto.response.SubscriptionsResponse; +import com.allog.dallog.domain.subscription.exception.ExistSubscriptionException; import com.allog.dallog.domain.subscription.exception.NoSuchSubscriptionException; import java.util.List; import java.util.stream.Collectors; @@ -34,6 +35,10 @@ public SubscriptionService(final SubscriptionRepository subscriptionRepository, @Transactional public SubscriptionResponse save(final Long memberId, final Long categoryId, final SubscriptionCreateRequest request) { + if (subscriptionRepository.existsByMemberIdAndCategoryId(memberId, categoryId)) { + throw new ExistSubscriptionException(); + } + Member member = memberService.getMember(memberId); Category category = categoryService.getCategory(categoryId); @@ -59,6 +64,7 @@ public SubscriptionResponse findById(final Long id) { return new SubscriptionResponse(subscription); } + @Transactional public void deleteByIdAndMemberId(final Long id, final Long memberId) { if (!subscriptionRepository.existsByIdAndMemberId(id, memberId)) { throw new NoPermissionException(); diff --git a/backend/src/test/java/com/allog/dallog/domain/subscription/application/SubscriptionServiceTest.java b/backend/src/test/java/com/allog/dallog/domain/subscription/application/SubscriptionServiceTest.java index f87df71d..ae00cfb3 100644 --- a/backend/src/test/java/com/allog/dallog/domain/subscription/application/SubscriptionServiceTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/subscription/application/SubscriptionServiceTest.java @@ -23,6 +23,7 @@ import com.allog.dallog.domain.subscription.dto.request.SubscriptionCreateRequest; import com.allog.dallog.domain.subscription.dto.response.SubscriptionResponse; import com.allog.dallog.domain.subscription.dto.response.SubscriptionsResponse; +import com.allog.dallog.domain.subscription.exception.ExistSubscriptionException; import com.allog.dallog.domain.subscription.exception.InvalidSubscriptionException; import com.allog.dallog.domain.subscription.exception.NoSuchSubscriptionException; import javax.transaction.Transactional; @@ -63,6 +64,19 @@ class SubscriptionServiceTest { }); } + @DisplayName("이미 존재하는 구독 정보를 저장할 경우 예외를 던진다.") + @Test + void 이미_존재하는_구독_정보를_저장할_경우_예외를_던진다() { + // given + MemberResponse 후디 = memberService.save(후디()); + CategoryResponse BE_일정 = categoryService.save(후디.getId(), BE_일정_생성_요청); + subscriptionService.save(후디.getId(), BE_일정.getId(), 빨간색_구독_생성_요청); + + // when & then + assertThatThrownBy(() -> subscriptionService.save(후디.getId(), BE_일정.getId(), 빨간색_구독_생성_요청)) + .isInstanceOf(ExistSubscriptionException.class); + } + @DisplayName("색 정보 형식이 잘못된 경우 예외를 던진다.") @ParameterizedTest @ValueSource(strings = {"#111", "#1111", "#11111", "123456", "#**1234", "##12345", "334172#"}) @@ -134,13 +148,12 @@ class SubscriptionServiceTest { CategoryResponse FE_일정 = categoryService.save(관리자.getId(), FE_일정_생성_요청); MemberResponse 후디 = memberService.save(후디()); - SubscriptionResponse subscriptionResponse = subscriptionService.save(후디.getId(), 공통_일정.getId(), - 빨간색_구독_생성_요청); + SubscriptionResponse response = subscriptionService.save(후디.getId(), 공통_일정.getId(), 빨간색_구독_생성_요청); subscriptionService.save(후디.getId(), BE_일정.getId(), 파란색_구독_생성_요청); subscriptionService.save(후디.getId(), FE_일정.getId(), 노란색_구독_생성_요청); // when - subscriptionService.deleteByIdAndMemberId(subscriptionResponse.getId(), 후디.getId()); + subscriptionService.deleteByIdAndMemberId(response.getId(), 후디.getId()); // then assertThat(subscriptionService.findByMemberId(후디.getId()).getSubscriptions()).hasSize(2); From e3ebce7fdbba8b377501b0ff9bcd85aa480df265 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Wed, 27 Jul 2022 13:16:58 +0900 Subject: [PATCH 0350/1011] =?UTF-8?q?chore:=20subscription=20Controller=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20path=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subscription/presentation/SubscriptionController.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/domain/subscription/presentation/SubscriptionController.java b/backend/src/main/java/com/allog/dallog/domain/subscription/presentation/SubscriptionController.java index 9630fedf..5cce2216 100644 --- a/backend/src/main/java/com/allog/dallog/domain/subscription/presentation/SubscriptionController.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/presentation/SubscriptionController.java @@ -13,8 +13,10 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +@RequestMapping("/api/members/me") @RestController public class SubscriptionController { @@ -24,7 +26,7 @@ public SubscriptionController(final SubscriptionService subscriptionService) { this.subscriptionService = subscriptionService; } - @PostMapping("/api/members/me/categories/{categoryId}/subscriptions") + @PostMapping("/categories/{categoryId}/subscriptions") public ResponseEntity save(@AuthenticationPrincipal final LoginMember loginMember, @PathVariable final Long categoryId, @RequestBody final SubscriptionCreateRequest request) { @@ -33,13 +35,13 @@ public ResponseEntity save(@AuthenticationPrincipal final URI.create("/api/members/me/" + categoryId + "/subscriptions/" + response.getId())).body(response); } - @GetMapping("/api/members/me/subscriptions") + @GetMapping("/subscriptions") public ResponseEntity findMine(@AuthenticationPrincipal final LoginMember loginMember) { SubscriptionsResponse response = subscriptionService.findByMemberId(loginMember.getId()); return ResponseEntity.ok(response); } - @DeleteMapping("/api/members/me/subscriptions/{subscriptionId}") + @DeleteMapping("/subscriptions/{subscriptionId}") public ResponseEntity deleteById(@AuthenticationPrincipal final LoginMember loginMember, @PathVariable final Long subscriptionId) { subscriptionService.deleteByIdAndMemberId(subscriptionId, loginMember.getId()); From b2c1459f843b0c2228421fecd8009f9633bc1e7c Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Wed, 27 Jul 2022 12:45:04 +0900 Subject: [PATCH 0351/1011] =?UTF-8?q?test(auth):=20GoogleOAuthClient=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oauth/client/GoogleOAuthClient.java | 33 +++++++++++++------ .../oauth/exception/OAuthException.java | 12 +++++++ 2 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 backend/src/main/java/com/allog/dallog/infrastructure/oauth/exception/OAuthException.java diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java index faea5afa..c0d48e98 100644 --- a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/client/GoogleOAuthClient.java @@ -4,6 +4,7 @@ import com.allog.dallog.domain.auth.dto.OAuthMember; import com.allog.dallog.global.config.properties.GoogleProperties; import com.allog.dallog.infrastructure.oauth.dto.GoogleTokenResponse; +import com.allog.dallog.infrastructure.oauth.exception.OAuthException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import java.nio.charset.StandardCharsets; @@ -14,9 +15,11 @@ import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; @Component @@ -40,12 +43,7 @@ public OAuthMember getOAuthMember(final String code) { GoogleTokenResponse googleTokenResponse = requestGoogleToken(code); String payload = getPayloadFrom(googleTokenResponse.getIdToken()); String decodedPayload = decodeJwtPayload(payload); - - try { - return generateOAuthMemberBy(decodedPayload); - } catch (JsonProcessingException e) { - throw new IllegalArgumentException(); - } + return generateOAuthMemberBy(decodedPayload); } private GoogleTokenResponse requestGoogleToken(final String code) { @@ -54,7 +52,15 @@ private GoogleTokenResponse requestGoogleToken(final String code) { MultiValueMap params = generateRequestParams(code); HttpEntity> request = new HttpEntity<>(params, headers); - return restTemplate.postForEntity(googleProperties.getTokenUri(), request, GoogleTokenResponse.class).getBody(); + return post(request).getBody(); + } + + private ResponseEntity post(final HttpEntity> request) { + try { + return restTemplate.postForEntity(googleProperties.getTokenUri(), request, GoogleTokenResponse.class); + } catch (RestClientException e) { + throw new OAuthException(); + } } private MultiValueMap generateRequestParams(final String code) { @@ -75,12 +81,19 @@ private String decodeJwtPayload(final String payload) { return new String(Base64.getUrlDecoder().decode(payload), StandardCharsets.UTF_8); } - private OAuthMember generateOAuthMemberBy(final String decodedIdToken) throws JsonProcessingException { - Map userInfo = objectMapper.readValue(decodedIdToken, HashMap.class); + private OAuthMember generateOAuthMemberBy(final String decodedPayload) { + Map userInfo = readIdToken(decodedPayload); String email = userInfo.get("email"); String displayName = userInfo.get("name"); String profileImageUrl = userInfo.get("picture"); - return new OAuthMember(email, displayName, profileImageUrl); } + + private Map readIdToken(final String decodedPayload) { + try { + return objectMapper.readValue(decodedPayload, HashMap.class); + } catch (JsonProcessingException e) { + throw new OAuthException("id 토큰을 읽을 수 없습니다."); + } + } } diff --git a/backend/src/main/java/com/allog/dallog/infrastructure/oauth/exception/OAuthException.java b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/exception/OAuthException.java new file mode 100644 index 00000000..91ff7fea --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/infrastructure/oauth/exception/OAuthException.java @@ -0,0 +1,12 @@ +package com.allog.dallog.infrastructure.oauth.exception; + +public class OAuthException extends RuntimeException { + + public OAuthException(final String message) { + super(message); + } + + public OAuthException() { + this("Oauth 서버와의 통신 과정에서 문제가 발생했습니다."); + } +} From e6164993e9b461313913c347d11a66f24a7b3004 Mon Sep 17 00:00:00 2001 From: koo Date: Wed, 27 Jul 2022 13:09:48 +0900 Subject: [PATCH 0352/1011] =?UTF-8?q?refactor:=20Member=EC=9D=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=20=ED=8C=8C=EB=9D=BC=EB=AF=B8?= =?UTF-8?q?=ED=84=B0=20=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/application/AuthService.java | 2 +- .../dallog/domain/member/domain/Member.java | 18 ++++++++--------- .../common/fixtures/MemberFixtures.java | 20 +++++++++---------- .../domain/member/domain/MemberTest.java | 8 +++----- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/domain/auth/application/AuthService.java b/backend/src/main/java/com/allog/dallog/domain/auth/application/AuthService.java index d16932db..29cc06e7 100644 --- a/backend/src/main/java/com/allog/dallog/domain/auth/application/AuthService.java +++ b/backend/src/main/java/com/allog/dallog/domain/auth/application/AuthService.java @@ -49,7 +49,7 @@ private void saveMemberIfNotExists(final OAuthMember oAuthMember, final String e } private Member generateMemberBy(final OAuthMember oAuthMember) { - return new Member(oAuthMember.getEmail(), oAuthMember.getProfileImageUrl(), oAuthMember.getDisplayName(), + return new Member(oAuthMember.getEmail(), oAuthMember.getDisplayName(), oAuthMember.getProfileImageUrl(), SocialType.GOOGLE); } diff --git a/backend/src/main/java/com/allog/dallog/domain/member/domain/Member.java b/backend/src/main/java/com/allog/dallog/domain/member/domain/Member.java index 6d78833e..3803251a 100644 --- a/backend/src/main/java/com/allog/dallog/domain/member/domain/Member.java +++ b/backend/src/main/java/com/allog/dallog/domain/member/domain/Member.java @@ -28,12 +28,12 @@ public class Member extends BaseEntity { @Column(name = "email", nullable = false) private String email; - @Column(name = "profile_image_url", nullable = false) - private String profileImageUrl; - @Column(name = "display_name", nullable = false) private String displayName; + @Column(name = "profile_image_url", nullable = false) + private String profileImageUrl; + @Enumerated(value = EnumType.STRING) @Column(name = "social_type", nullable = false) private SocialType socialType; @@ -41,14 +41,14 @@ public class Member extends BaseEntity { protected Member() { } - public Member(final String email, final String profileImageUrl, final String displayName, + public Member(final String email, final String displayName, final String profileImageUrl, final SocialType socialType) { validateEmail(email); validateDisplayName(displayName); this.email = email; - this.profileImageUrl = profileImageUrl; this.displayName = displayName; + this.profileImageUrl = profileImageUrl; this.socialType = socialType; } @@ -73,14 +73,14 @@ public String getEmail() { return email; } - public String getProfileImageUrl() { - return profileImageUrl; - } - public String getDisplayName() { return displayName; } + public String getProfileImageUrl() { + return profileImageUrl; + } + public SocialType getSocialType() { return socialType; } diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java index 66173b45..660d22ef 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java @@ -7,46 +7,46 @@ public class MemberFixtures { /* 관리자 */ public static final String 관리자_이메일 = "dallog.admin@gmail.com"; - public static final String 관리자_프로필 = "/admin.png"; public static final String 관리자_이름 = "관리자"; + public static final String 관리자_프로필 = "/admin.png"; /* 파랑 */ public static final String 파랑_이메일 = "parang@email.com"; - public static final String 파랑_프로필 = "/parang.png"; public static final String 파랑_이름 = "파랑"; + public static final String 파랑_프로필 = "/parang.png"; /* 리버 */ public static final String 리버_이메일 = "leaver@email.com"; - public static final String 리버_프로필 = "/leaver.png"; public static final String 리버_이름 = "리버"; + public static final String 리버_프로필 = "/leaver.png"; /* 후디 */ public static final String 후디_이메일 = "devhudi@gmail.com"; - public static final String 후디_프로필 = "/hudi.png"; public static final String 후디_이름 = "후디"; + public static final String 후디_프로필 = "/hudi.png"; /* 매트 */ public static final String 매트_이메일 = "dev.hyeonic@gmail.com"; - public static final String 매트_프로필 = "/mat.png"; public static final String 매트_이름 = "매트"; + public static final String 매트_프로필 = "/mat.png"; public static Member 관리자() { - return new Member(관리자_이메일, 관리자_프로필, 관리자_이름, SocialType.GOOGLE); + return new Member(관리자_이메일, 관리자_이름, 관리자_프로필, SocialType.GOOGLE); } public static Member 파랑() { - return new Member(파랑_이메일, 파랑_프로필, 파랑_이름, SocialType.GOOGLE); + return new Member(파랑_이메일, 파랑_이름, 파랑_프로필, SocialType.GOOGLE); } public static Member 리버() { - return new Member(리버_이메일, 리버_프로필, 리버_이름, SocialType.GOOGLE); + return new Member(리버_이메일, 리버_이름, 리버_프로필, SocialType.GOOGLE); } public static Member 후디() { - return new Member(후디_이메일, 후디_프로필, 후디_이름, SocialType.GOOGLE); + return new Member(후디_이메일, 후디_이름, 후디_프로필, SocialType.GOOGLE); } public static Member 매트() { - return new Member(매트_이메일, 매트_프로필, 매트_이름, SocialType.GOOGLE); + return new Member(매트_이메일, 매트_이름, 매트_프로필, SocialType.GOOGLE); } } diff --git a/backend/src/test/java/com/allog/dallog/domain/member/domain/MemberTest.java b/backend/src/test/java/com/allog/dallog/domain/member/domain/MemberTest.java index 8f6cc9c7..c6876218 100644 --- a/backend/src/test/java/com/allog/dallog/domain/member/domain/MemberTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/member/domain/MemberTest.java @@ -6,8 +6,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import com.allog.dallog.domain.member.domain.Member; -import com.allog.dallog.domain.member.domain.SocialType; import com.allog.dallog.domain.member.exception.InvalidMemberException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -20,7 +18,7 @@ class MemberTest { @Test void 회원을_생성한다() { // given & when & then - assertDoesNotThrow(() -> new Member(파랑_이메일, 파랑_프로필, 파랑_이름, SocialType.GOOGLE)); + assertDoesNotThrow(() -> new Member(파랑_이메일, 파랑_이름, 파랑_프로필, SocialType.GOOGLE)); } @DisplayName("회원의 email이 형식이 맞지 않으면 예외를 던진다.") @@ -28,7 +26,7 @@ class MemberTest { @ValueSource(strings = {"dev.hyeonic@", "dev.hyeonicgmail.com", "dev.hyeonic@gmail", "@gmail.com", "dev.hyeonic"}) void 회원의_email이_형식이_맞지_않으면_예외를_던진다(final String email) { // given & when & then - assertThatThrownBy(() -> new Member(email, 파랑_프로필, 파랑_이름, SocialType.GOOGLE)) + assertThatThrownBy(() -> new Member(email, 파랑_이름, 파랑_프로필, SocialType.GOOGLE)) .isInstanceOf(InvalidMemberException.class); } @@ -37,7 +35,7 @@ class MemberTest { @ValueSource(strings = {"", "일이삼사오육칠팔구십일"}) void 회원의_이름이_1_에서_10_사이가_아닌_경우_예외를_던진다(final String displayName) { // given & when & then - assertThatThrownBy(() -> new Member(파랑_이메일, 파랑_프로필, displayName, SocialType.GOOGLE)) + assertThatThrownBy(() -> new Member(파랑_이메일, displayName, 파랑_프로필, SocialType.GOOGLE)) .isInstanceOf(InvalidMemberException.class); } } From 0d867b9d53dafbd36f75f7a4aa7ecf33675b8f13 Mon Sep 17 00:00:00 2001 From: devHudi Date: Wed, 27 Jul 2022 14:55:30 +0900 Subject: [PATCH 0353/1011] =?UTF-8?q?feat:=20ControllerAdvice=EB=A5=BC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ErrorResponse 추가 Co-authored-by: summerlunaa --- .../dallog/global/dto/ErrorResponse.java | 14 +++++ .../global/presentation/ControllerAdvice.java | 58 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 backend/src/main/java/com/allog/dallog/global/dto/ErrorResponse.java create mode 100644 backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java diff --git a/backend/src/main/java/com/allog/dallog/global/dto/ErrorResponse.java b/backend/src/main/java/com/allog/dallog/global/dto/ErrorResponse.java new file mode 100644 index 00000000..38913149 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/global/dto/ErrorResponse.java @@ -0,0 +1,14 @@ +package com.allog.dallog.global.dto; + +public class ErrorResponse { + + private final String message; + + public ErrorResponse(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } +} diff --git a/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java b/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java new file mode 100644 index 00000000..46d25e66 --- /dev/null +++ b/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java @@ -0,0 +1,58 @@ +package com.allog.dallog.global.presentation; + +import com.allog.dallog.domain.auth.exception.EmptyAuthorizationHeaderException; +import com.allog.dallog.domain.auth.exception.InvalidTokenException; +import com.allog.dallog.domain.auth.exception.NoPermissionException; +import com.allog.dallog.domain.category.exception.InvalidCategoryException; +import com.allog.dallog.domain.category.exception.NoSuchCategoryException; +import com.allog.dallog.domain.member.exception.InvalidMemberException; +import com.allog.dallog.domain.member.exception.NoSuchMemberException; +import com.allog.dallog.domain.schedule.exception.InvalidScheduleException; +import com.allog.dallog.domain.subscription.exception.InvalidSubscriptionException; +import com.allog.dallog.domain.subscription.exception.NoSuchSubscriptionException; +import com.allog.dallog.global.dto.ErrorResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class ControllerAdvice { + + @ExceptionHandler(Exception.class) + public ResponseEntity handleUnexpectedException() { + ErrorResponse errorResponse = new ErrorResponse("예상하지 못한 서버 에러가 발생했습니다."); + return ResponseEntity.internalServerError().body(errorResponse); + } + + @ExceptionHandler({ + EmptyAuthorizationHeaderException.class, + InvalidTokenException.class, + NoPermissionException.class + }) + public ResponseEntity handleInvalidAuthorization() { + ErrorResponse errorResponse = new ErrorResponse("사용자 인증에 실패하였습니다."); + return ResponseEntity.internalServerError().body(errorResponse); + } + + @ExceptionHandler({ + InvalidCategoryException.class, + InvalidMemberException.class, + InvalidScheduleException.class, + InvalidSubscriptionException.class + }) + public ResponseEntity handleInvalidData(final RuntimeException e) { + ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); + return ResponseEntity.badRequest().body(errorResponse); + } + + @ExceptionHandler({ + NoSuchCategoryException.class, + NoSuchMemberException.class, + NoSuchSubscriptionException.class + }) + public ResponseEntity handleNoSuchData(final RuntimeException e) { + ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorResponse); + } +} From 1847664b1dcfe56189f856120e263215512a87d1 Mon Sep 17 00:00:00 2001 From: devHudi Date: Wed, 27 Jul 2022 15:10:08 +0900 Subject: [PATCH 0354/1011] =?UTF-8?q?feat:=20OAuth=20=ED=86=B5=EC=8B=A0=20?= =?UTF-8?q?=EA=B3=BC=EC=A0=95=EC=9D=98=20=EC=97=90=EB=9F=AC=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20ControllerAdvice=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: summerlunaa --- .../allog/dallog/global/presentation/ControllerAdvice.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java b/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java index 46d25e66..e324ae98 100644 --- a/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java +++ b/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java @@ -11,6 +11,7 @@ import com.allog.dallog.domain.subscription.exception.InvalidSubscriptionException; import com.allog.dallog.domain.subscription.exception.NoSuchSubscriptionException; import com.allog.dallog.global.dto.ErrorResponse; +import com.allog.dallog.infrastructure.oauth.exception.OAuthException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -25,6 +26,12 @@ public ResponseEntity handleUnexpectedException() { return ResponseEntity.internalServerError().body(errorResponse); } + @ExceptionHandler(OAuthException.class) + public ResponseEntity handleOAuthException() { + ErrorResponse errorResponse = new ErrorResponse("OAuth 통신 과정에서 에러가 발생했습니다."); + return ResponseEntity.internalServerError().body(errorResponse); + } + @ExceptionHandler({ EmptyAuthorizationHeaderException.class, InvalidTokenException.class, From fc51b6b695b045e592a992108d999bb1c204a9a3 Mon Sep 17 00:00:00 2001 From: devHudi Date: Wed, 27 Jul 2022 15:14:25 +0900 Subject: [PATCH 0355/1011] =?UTF-8?q?refactor:=20=EB=88=84=EB=9D=BD?= =?UTF-8?q?=EB=90=9C=20final=20=ED=82=A4=EC=9B=8C=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: summerlunaa --- .../main/java/com/allog/dallog/global/dto/ErrorResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/com/allog/dallog/global/dto/ErrorResponse.java b/backend/src/main/java/com/allog/dallog/global/dto/ErrorResponse.java index 38913149..ce206d52 100644 --- a/backend/src/main/java/com/allog/dallog/global/dto/ErrorResponse.java +++ b/backend/src/main/java/com/allog/dallog/global/dto/ErrorResponse.java @@ -4,7 +4,7 @@ public class ErrorResponse { private final String message; - public ErrorResponse(String message) { + public ErrorResponse(final String message) { this.message = message; } From d63abe3cce8b141a3a830370420e48f31a82c3c7 Mon Sep 17 00:00:00 2001 From: devHudi Date: Wed, 27 Jul 2022 15:16:27 +0900 Subject: [PATCH 0356/1011] =?UTF-8?q?refactor:=20ControllerAdvice=20?= =?UTF-8?q?=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=88=9C=EC=84=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: summerlunaa --- .../global/presentation/ControllerAdvice.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java b/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java index e324ae98..cff75e61 100644 --- a/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java +++ b/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java @@ -20,16 +20,15 @@ @RestControllerAdvice public class ControllerAdvice { - @ExceptionHandler(Exception.class) - public ResponseEntity handleUnexpectedException() { - ErrorResponse errorResponse = new ErrorResponse("예상하지 못한 서버 에러가 발생했습니다."); - return ResponseEntity.internalServerError().body(errorResponse); - } - - @ExceptionHandler(OAuthException.class) - public ResponseEntity handleOAuthException() { - ErrorResponse errorResponse = new ErrorResponse("OAuth 통신 과정에서 에러가 발생했습니다."); - return ResponseEntity.internalServerError().body(errorResponse); + @ExceptionHandler({ + InvalidCategoryException.class, + InvalidMemberException.class, + InvalidScheduleException.class, + InvalidSubscriptionException.class + }) + public ResponseEntity handleInvalidData(final RuntimeException e) { + ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); + return ResponseEntity.badRequest().body(errorResponse); } @ExceptionHandler({ @@ -42,17 +41,6 @@ public ResponseEntity handleInvalidAuthorization() { return ResponseEntity.internalServerError().body(errorResponse); } - @ExceptionHandler({ - InvalidCategoryException.class, - InvalidMemberException.class, - InvalidScheduleException.class, - InvalidSubscriptionException.class - }) - public ResponseEntity handleInvalidData(final RuntimeException e) { - ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); - return ResponseEntity.badRequest().body(errorResponse); - } - @ExceptionHandler({ NoSuchCategoryException.class, NoSuchMemberException.class, @@ -62,4 +50,16 @@ public ResponseEntity handleNoSuchData(final RuntimeException e) ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorResponse); } + + @ExceptionHandler(OAuthException.class) + public ResponseEntity handleOAuthException() { + ErrorResponse errorResponse = new ErrorResponse("OAuth 통신 과정에서 에러가 발생했습니다."); + return ResponseEntity.internalServerError().body(errorResponse); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity handleUnexpectedException() { + ErrorResponse errorResponse = new ErrorResponse("예상하지 못한 서버 에러가 발생했습니다."); + return ResponseEntity.internalServerError().body(errorResponse); + } } From f55316561f623ace1d61e78ee7a76f2500c4cb21 Mon Sep 17 00:00:00 2001 From: devHudi Date: Wed, 27 Jul 2022 15:26:26 +0900 Subject: [PATCH 0357/1011] =?UTF-8?q?refactor:=20ExistSubscriptionExceptio?= =?UTF-8?q?n=20=ED=95=B8=EB=93=A4=EB=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: summerlunaa --- .../allog/dallog/global/presentation/ControllerAdvice.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java b/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java index cff75e61..682b2443 100644 --- a/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java +++ b/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java @@ -8,6 +8,7 @@ import com.allog.dallog.domain.member.exception.InvalidMemberException; import com.allog.dallog.domain.member.exception.NoSuchMemberException; import com.allog.dallog.domain.schedule.exception.InvalidScheduleException; +import com.allog.dallog.domain.subscription.exception.ExistSubscriptionException; import com.allog.dallog.domain.subscription.exception.InvalidSubscriptionException; import com.allog.dallog.domain.subscription.exception.NoSuchSubscriptionException; import com.allog.dallog.global.dto.ErrorResponse; @@ -24,7 +25,8 @@ public class ControllerAdvice { InvalidCategoryException.class, InvalidMemberException.class, InvalidScheduleException.class, - InvalidSubscriptionException.class + InvalidSubscriptionException.class, + ExistSubscriptionException.class }) public ResponseEntity handleInvalidData(final RuntimeException e) { ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); From 7b6e33bf042b73be311cc10e713eb1fe0cc00e85 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Wed, 27 Jul 2022 17:48:24 +0900 Subject: [PATCH 0358/1011] =?UTF-8?q?feat:=20=EC=8A=A4=EB=82=B5=EB=B0=94?= =?UTF-8?q?=20=EC=BB=A4=EC=8A=A4=ED=85=80=20=ED=9B=85=20=EB=B0=8F=20?= =?UTF-8?q?=EC=8A=A4=EB=82=B5=EB=B0=94=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/App.tsx | 2 ++ .../components/SnackBar/SnackBar.styles.ts | 22 +++++++++++++ frontend/src/components/SnackBar/SnackBar.tsx | 33 +++++++++++++++++++ frontend/src/constants/index.ts | 1 + frontend/src/hooks/useSnackBar.ts | 15 +++++++++ frontend/src/recoil/atoms/index.ts | 9 ++++- 6 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/SnackBar/SnackBar.styles.ts create mode 100644 frontend/src/components/SnackBar/SnackBar.tsx create mode 100644 frontend/src/hooks/useSnackBar.ts diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index e6154ca3..1044efc5 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -3,6 +3,7 @@ import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'; import NavBar from '@/components/NavBar/NavBar'; import ProtectRoute from '@/components/ProtectRoute'; import SideBar from '@/components/SideBar/SideBar'; +import SnackBar from '@/components/SnackBar/SnackBar'; import AuthPage from '@/pages/AuthPage/AuthPage'; import CategoryPage from '@/pages/CategoryPage/CategoryPage'; import LoginPage from '@/pages/LoginPage/LoginPage'; @@ -25,6 +26,7 @@ function App() { } /> + ); } diff --git a/frontend/src/components/SnackBar/SnackBar.styles.ts b/frontend/src/components/SnackBar/SnackBar.styles.ts new file mode 100644 index 00000000..9fdf1a4e --- /dev/null +++ b/frontend/src/components/SnackBar/SnackBar.styles.ts @@ -0,0 +1,22 @@ +import { css, Theme } from '@emotion/react'; + +const snackBarStyle = ({ colors }: Theme, isOpen: boolean) => css` + position: fixed; + bottom: ${isOpen ? '5rem' : '-20rem'}; + left: 50%; + transform: translateX(-50%); + + padding: 4rem; + border-radius: 3px; + + background: ${colors.YELLOW_500}; + + color: ${colors.WHITE}; + font-size: 3.5rem; + line-height: 3.5rem; + text-align: center; + + transition: bottom 1s; +`; + +export { snackBarStyle }; diff --git a/frontend/src/components/SnackBar/SnackBar.tsx b/frontend/src/components/SnackBar/SnackBar.tsx new file mode 100644 index 00000000..c872a265 --- /dev/null +++ b/frontend/src/components/SnackBar/SnackBar.tsx @@ -0,0 +1,33 @@ +import { useTheme } from '@emotion/react'; +import { useEffect, useState } from 'react'; +import { useRecoilValue } from 'recoil'; + +import { snackBarState } from '@/recoil/atoms'; + +import { snackBarStyle } from './SnackBar.styles'; + +function SnackBar() { + const theme = useTheme(); + + const snackBarInfo = useRecoilValue(snackBarState); + + const [timer, setTimer] = useState(null); + + useEffect(() => { + if (snackBarInfo.text === '' || timer) { + return; + } + + const newTimer = setTimeout(() => { + setTimer(null); + }, 1500); + + setTimer(newTimer); + }, [snackBarInfo]); + + const isOpen = timer !== null; + + return
{snackBarInfo.text}
; +} + +export default SnackBar; diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 291f0a54..fd95d3fc 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -5,6 +5,7 @@ const API = { const API_URL = process.env.API_URL; const ATOM_KEY = { + SNACK_BAR: 'snackBarState', SIDE_BAR: 'sideBarState', USER: 'userState', }; diff --git a/frontend/src/hooks/useSnackBar.ts b/frontend/src/hooks/useSnackBar.ts new file mode 100644 index 00000000..57de3351 --- /dev/null +++ b/frontend/src/hooks/useSnackBar.ts @@ -0,0 +1,15 @@ +import { useSetRecoilState } from 'recoil'; + +import { snackBarState } from '@/recoil/atoms'; + +function useSnackBar() { + const setText = useSetRecoilState(snackBarState); + + const openSnackBar = (text: string) => { + setText({ text }); + }; + + return { openSnackBar }; +} + +export default useSnackBar; diff --git a/frontend/src/recoil/atoms/index.ts b/frontend/src/recoil/atoms/index.ts index 5093dcb6..7bb28bc8 100644 --- a/frontend/src/recoil/atoms/index.ts +++ b/frontend/src/recoil/atoms/index.ts @@ -16,4 +16,11 @@ const userState = atom({ }, }); -export { sideBarState, userState }; +const snackBarState = atom({ + key: ATOM_KEY.SNACK_BAR, + default: { + text: '', + }, +}); + +export { snackBarState, sideBarState, userState }; From 812d4c46b382fd8c5550137d039da891f1003852 Mon Sep 17 00:00:00 2001 From: koo Date: Wed, 27 Jul 2022 18:05:49 +0900 Subject: [PATCH 0359/1011] =?UTF-8?q?test(MemberControllerTest):=20?= =?UTF-8?q?=EC=9E=90=EC=8B=A0=EC=9D=98=20=ED=9A=8C=EC=9B=90=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20API?= =?UTF-8?q?=20=EB=AC=B8=EC=84=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/index.adoc | 16 +++++ .../src/main/resources/static/docs/index.html | 71 ++++++++++++++---- .../dallog/common/fixtures/AuthFixtures.java | 3 + .../presentation/MemberControllerTest.java | 72 +++++++++++++++++++ 4 files changed, 150 insertions(+), 12 deletions(-) create mode 100644 backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java diff --git a/backend/src/docs/asciidoc/index.adoc b/backend/src/docs/asciidoc/index.adoc index a83d59e5..21aaba68 100644 --- a/backend/src/docs/asciidoc/index.adoc +++ b/backend/src/docs/asciidoc/index.adoc @@ -30,3 +30,19 @@ include::{snippets}/schedule/find/request-parameters.adoc[] ==== Response include::{snippets}/schedule/find/http-response.adoc[] + +== Member(회원) + +=== 내 정보 조회 + +==== Request + +include::{snippets}/member/me/http-request.adoc[] + +==== RequestHeaders + +include::{snippets}/member/me/request-headers.adoc[] + +==== Response + +include::{snippets}/member/me/http-response.adoc[] diff --git a/backend/src/main/resources/static/docs/index.html b/backend/src/main/resources/static/docs/index.html index 7bda2bf2..dd94a118 100644 --- a/backend/src/main/resources/static/docs/index.html +++ b/backend/src/main/resources/static/docs/index.html @@ -463,6 +463,16 @@

달록 API 문서

+
  • Member(회원) + +
  • @@ -479,14 +489,14 @@

    Request

    POST /api/schedules HTTP/1.1
     Content-Type: application/json;charset=UTF-8
     Accept: application/json
    -Content-Length: 150
    +Content-Length: 173
     Host: localhost:8080
     
     {
    -  "startDateTime" : "2022-07-15T14:20",
    -  "memo" : "세모 회의실 6시 회의",
    -  "title" : "알록",
    -  "endDateTime" : "2022-07-15T16:20"
    +  "title" : "알록달록 회의",
    +  "startDateTime" : "2022-07-15T16:00:00",
    +  "endDateTime" : "2022-07-16T16:00:00",
    +  "memo" : "알록달록 회의가 있어요"
     }
    @@ -496,6 +506,9 @@

    Response

    HTTP/1.1 201 Created
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
     Location: /api/schedules/0
    @@ -543,16 +556,19 @@

    Response

    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
     Content-Type: application/json
    -Content-Length: 180
    +Content-Length: 224
     
     {
    -  "data" : [ {
    +  "schedules" : [ {
         "id" : 1,
    -    "title" : "알록",
    -    "startDateTime" : "2022-07-15T14:20:00",
    -    "endDateTime" : "2022-07-15T16:20:00",
    -    "memo" : "달록"
    +    "title" : "알록달록 회의",
    +    "startDateTime" : "2022-07-15T16:00:00",
    +    "endDateTime" : "2022-07-16T16:00:00",
    +    "memo" : "알록달록 회의가 있어요"
       } ]
     }
    @@ -561,11 +577,42 @@

    Response

    +
    +

    Member(회원)

    +
    +
    +

    내 정보 조회

    +
    +

    Request

    +
    +
    +
    GET /api/members/me HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer aaaaa.bbbbb.ccccc
    +Accept: application/json
    +Host: localhost:8080
    +
    +
    +
    +
    +

    Response

    +
    +
    +
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
    +
    +
    +
    +
    +
    +
    diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java index 3bf4b82c..3706b586 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java @@ -9,4 +9,7 @@ public class AuthFixtures { public static final String STUB_이메일 = "stub@email.com"; public static final String STUB_이름 = "stub"; public static final String STUB_프로필 = "/image.png"; + + public static final String 더미_엑세스_토큰 = "aaaaa.bbbbb.ccccc"; + public static final String 토큰_정보 = "Bearer " + 더미_엑세스_토큰; } diff --git a/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java new file mode 100644 index 00000000..2949af9a --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java @@ -0,0 +1,72 @@ +package com.allog.dallog.domain.member.presentation; + +import static com.allog.dallog.common.fixtures.AuthFixtures.더미_엑세스_토큰; +import static com.allog.dallog.common.fixtures.AuthFixtures.토큰_정보; +import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_이름; +import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_이메일; +import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_프로필; +import static com.allog.dallog.domain.member.domain.SocialType.GOOGLE; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.allog.dallog.domain.auth.application.AuthService; +import com.allog.dallog.domain.member.application.MemberService; +import com.allog.dallog.domain.member.dto.MemberResponse; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +@AutoConfigureRestDocs +@WebMvcTest(MemberController.class) +class MemberControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private com.fasterxml.jackson.databind.ObjectMapper ObjectMapper; + + @MockBean + private AuthService authService; + + @MockBean + private MemberService memberService; + + @DisplayName("자신의 회원 정보를 조회한다.") + @Test + void 자신의_회원_정보를_조회한다() throws Exception { + //given + MemberResponse response = new MemberResponse(1L, 파랑_이메일, 파랑_이름, 파랑_프로필, GOOGLE); + + given(memberService.findById(response.getId())).willReturn(response); + given(authService.extractMemberId(더미_엑세스_토큰)).willReturn(response.getId()); + + // when & then + mockMvc.perform(get("/api/members/me") + .header("Authorization", 토큰_정보) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ) + .andDo(print()) + .andDo(document("member/me", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestHeaders( + headerWithName("Authorization").description("JWT 토큰")) + )) + .andExpect(status().isOk()); + } +} From 5bad3cf0b22b3f7c9a04c05d6752192ff69edb92 Mon Sep 17 00:00:00 2001 From: koo Date: Wed, 27 Jul 2022 20:23:22 +0900 Subject: [PATCH 0360/1011] =?UTF-8?q?test(MemberControllerTest):=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=EB=90=9C=20=ED=9A=8C=EC=9B=90=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/index.adoc | 10 +++ .../src/main/resources/static/docs/index.html | 74 ++++++++++++++++++- .../presentation/MemberControllerTest.java | 24 +++++- 3 files changed, 105 insertions(+), 3 deletions(-) diff --git a/backend/src/docs/asciidoc/index.adoc b/backend/src/docs/asciidoc/index.adoc index 21aaba68..1454b1bf 100644 --- a/backend/src/docs/asciidoc/index.adoc +++ b/backend/src/docs/asciidoc/index.adoc @@ -46,3 +46,13 @@ include::{snippets}/member/me/request-headers.adoc[] ==== Response include::{snippets}/member/me/http-response.adoc[] + +=== 삭제된 회원 정보 조회 + +==== Request + +include::{snippets}/member/exception/notfound/http-request.adoc[] + +==== Response + +include::{snippets}/member/exception/notfound/http-response.adoc[] diff --git a/backend/src/main/resources/static/docs/index.html b/backend/src/main/resources/static/docs/index.html index dd94a118..8e8302cd 100644 --- a/backend/src/main/resources/static/docs/index.html +++ b/backend/src/main/resources/static/docs/index.html @@ -468,9 +468,16 @@

    달록 API 문서

  • 내 정보 조회
  • +
  • 삭제된 회원 정보 조회 + +
  • @@ -595,13 +602,76 @@

    Request

    +

    RequestHeaders

    + ++++ + + + + + + + + + + + + +
    NameDescription

    Authorization

    JWT 토큰

    +
    +

    Response

    HTTP/1.1 200 OK
     Vary: Origin
     Vary: Access-Control-Request-Method
    -Vary: Access-Control-Request-Headers
    +Vary: Access-Control-Request-Headers +Content-Type: application/json +Content-Length: 144 + +{ + "id" : 1, + "email" : "parang@email.com", + "displayName" : "파랑", + "profileImageUrl" : "/parang.png", + "socialType" : "GOOGLE" +} +
    +
    +
    +
    +
    +

    삭제된 회원 정보 조회

    +
    +

    Request

    +
    +
    +
    GET /api/members/me HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Authorization: Bearer aaaaa.bbbbb.ccccc
    +Accept: application/json
    +Host: localhost:8080
    +
    +
    +
    +
    +

    Response

    +
    +
    +
    HTTP/1.1 404 Not Found
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
    +Content-Type: application/json
    +Content-Length: 58
    +
    +{
    +  "message" : "존재하지 않는 회원입니다."
    +}
    @@ -612,7 +682,7 @@

    Response

    diff --git a/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java index 2949af9a..ea74dc16 100644 --- a/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java @@ -20,6 +20,7 @@ import com.allog.dallog.domain.auth.application.AuthService; import com.allog.dallog.domain.member.application.MemberService; import com.allog.dallog.domain.member.dto.MemberResponse; +import com.allog.dallog.domain.member.exception.NoSuchMemberException; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -65,8 +66,29 @@ class MemberControllerTest { preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), requestHeaders( - headerWithName("Authorization").description("JWT 토큰")) + headerWithName("Authorization").description("JWT 토큰") + ) )) .andExpect(status().isOk()); } + + @DisplayName("존재하지 않는 회원의 정보를 조회하려고 하면 예외를 발생한다.") + @Test + void 존재하지_않는_회원의_정보를_조회하려고_하면_예외를_발생한다() throws Exception { + //given + given(memberService.findById(0L)).willThrow(new NoSuchMemberException()); + + // when & then + mockMvc.perform(get("/api/members/me") + .header("Authorization", 토큰_정보) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ) + .andDo(print()) + .andDo(document("member/exception/notfound", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()) + )) + .andExpect(status().isNotFound()); + } } From d35dedc90f5c4f33f3302c90bcaa544dae30c0d8 Mon Sep 17 00:00:00 2001 From: koo Date: Thu, 28 Jul 2022 12:45:58 +0900 Subject: [PATCH 0361/1011] =?UTF-8?q?test(AuthControllerTest):=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/static/docs/index.html | 325 ++++++++++++++++-- .../common/fixtures/MemberFixtures.java | 15 +- .../presentation/MemberControllerTest.java | 15 +- .../presentation/ScheduleControllerTest.java | 6 +- 4 files changed, 304 insertions(+), 57 deletions(-) diff --git a/backend/src/main/resources/static/docs/index.html b/backend/src/main/resources/static/docs/index.html index 8e8302cd..0fe789d0 100644 --- a/backend/src/main/resources/static/docs/index.html +++ b/backend/src/main/resources/static/docs/index.html @@ -446,18 +446,21 @@

    달록 API 문서

    -

    Schedule(일정)

    +

    Auth(인증)

    -

    일정 등록

    +

    OAuth 로그인 링크 생성

    Request

    -
    POST /api/schedules HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Accept: application/json
    -Content-Length: 173
    -Host: localhost:8080
    -
    -{
    -  "title" : "알록달록 회의",
    -  "startDateTime" : "2022-07-15T16:00:00",
    -  "endDateTime" : "2022-07-16T16:00:00",
    -  "memo" : "알록달록 회의가 있어요"
    -}
    +
    GET /api/auth/oauthProvider/oauth-uri HTTP/1.1
    +Host: localhost:8080
    +

    pathParameters

    + + ++++ + + + + + + + + + + + + +
    Table 1. /api/auth/{oauthProvider}/oauth-uri
    ParameterDescription

    oauthProvider

    OAuth 로그인 제공자

    +
    +

    Response

    -
    HTTP/1.1 201 Created
    +
    HTTP/1.1 200 OK
     Vary: Origin
     Vary: Access-Control-Request-Method
     Vary: Access-Control-Request-Headers
    -Location: /api/schedules/0
    +Content-Type: application/json +Content-Length: 67 + +{ + "oAuthUri" : "https://accounts.google.com/o/oauth2/v2/auth" +}
    +
    +

    ResponseFields

    + +++++ + + + + + + + + + + + + + + +
    PathTypeDescription

    oAuthUri

    String

    OAuth 소셜 로그인 링크

    +
    -

    월별 일정 조회

    +

    OAuth 로그인 : Resource Server 에러

    Request

    -
    GET /api/schedules?year=2022&month=7 HTTP/1.1
    +
    POST /api/auth/oauthProvider/token HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
     Accept: application/json
    -Host: localhost:8080
    +Content-Length: 37 +Host: localhost:8080 + +{ + "code" : "authorization code" +}
    -

    RequestParameters

    +

    RequestFields

    +@@ -548,12 +618,32 @@

    RequestParameters

    - - + + + +
    Table 2. /api/auth/{oauthProvider}/token

    year

    년도

    oauthProvider

    OAuth 로그인 제공자

    +
    +
    +

    RequestFields

    + +++++ + - - + + + + + + + + + +

    month

    PathTypeDescription

    code

    String

    OAuth 로그인 인증 코드

    @@ -562,21 +652,15 @@

    RequestParameters

    Response

    -
    HTTP/1.1 200 OK
    +
    HTTP/1.1 500 Internal Server Error
     Vary: Origin
     Vary: Access-Control-Request-Method
     Vary: Access-Control-Request-Headers
     Content-Type: application/json
    -Content-Length: 224
    +Content-Length: 77
     
     {
    -  "schedules" : [ {
    -    "id" : 1,
    -    "title" : "알록달록 회의",
    -    "startDateTime" : "2022-07-15T16:00:00",
    -    "endDateTime" : "2022-07-16T16:00:00",
    -    "memo" : "알록달록 회의가 있어요"
    -  } ]
    +  "message" : "OAuth 통신 과정에서 에러가 발생했습니다."
     }
    @@ -643,6 +727,50 @@

    Response

    +
    +

    ResponseFields

    + +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PathTypeDescription

    id

    Number

    기본키 값

    email

    String

    이메일

    displayName

    String

    닉네임

    profileImageUrl

    String

    프로필 사진

    socialType

    String

    소셜 로그인 서비스

    +

    삭제된 회원 정보 조회

    @@ -659,6 +787,27 @@

    Request

    +

    RequestHeaders

    + ++++ + + + + + + + + + + + + +
    NameDescription

    Authorization

    JWT 토큰

    +
    +

    Response

    @@ -678,11 +827,111 @@

    Response

    +
    +

    Schedule(일정)

    +
    +
    +

    일정 등록

    +
    +

    Request

    +
    +
    +
    POST /api/schedules HTTP/1.1
    +Content-Type: application/json;charset=UTF-8
    +Accept: application/json
    +Content-Length: 173
    +Host: localhost:8080
    +
    +{
    +  "title" : "알록달록 회의",
    +  "startDateTime" : "2022-07-15T16:00:00",
    +  "endDateTime" : "2022-07-16T16:00:00",
    +  "memo" : "알록달록 회의가 있어요"
    +}
    +
    +
    +
    +
    +

    Response

    +
    +
    +
    HTTP/1.1 201 Created
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
    +Location: /api/schedules/0
    +
    +
    +
    +
    +
    +

    월별 일정 조회

    +
    +

    Request

    +
    +
    +
    GET /api/schedules?year=2022&month=7 HTTP/1.1
    +Accept: application/json
    +Host: localhost:8080
    +
    +
    +
    +
    +

    RequestParameters

    + ++++ + + + + + + + + + + + + + + + + +
    ParameterDescription

    year

    년도

    month

    +
    +
    +

    Response

    +
    +
    +
    HTTP/1.1 200 OK
    +Vary: Origin
    +Vary: Access-Control-Request-Method
    +Vary: Access-Control-Request-Headers
    +Content-Type: application/json
    +Content-Length: 224
    +
    +{
    +  "schedules" : [ {
    +    "id" : 1,
    +    "title" : "알록달록 회의",
    +    "startDateTime" : "2022-07-15T16:00:00",
    +    "endDateTime" : "2022-07-16T16:00:00",
    +    "memo" : "알록달록 회의가 있어요"
    +  } ]
    +}
    +
    +
    +
    +
    +
    +
    diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java index 660d22ef..dcb775ff 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java @@ -1,7 +1,9 @@ package com.allog.dallog.common.fixtures; +import static com.allog.dallog.domain.member.domain.SocialType.GOOGLE; + import com.allog.dallog.domain.member.domain.Member; -import com.allog.dallog.domain.member.domain.SocialType; +import com.allog.dallog.domain.member.dto.MemberResponse; public class MemberFixtures { @@ -14,6 +16,7 @@ public class MemberFixtures { public static final String 파랑_이메일 = "parang@email.com"; public static final String 파랑_이름 = "파랑"; public static final String 파랑_프로필 = "/parang.png"; + public static final MemberResponse 파랑_응답 = new MemberResponse(1L, 파랑_이메일, 파랑_이름, 파랑_프로필, GOOGLE); /* 리버 */ public static final String 리버_이메일 = "leaver@email.com"; @@ -31,22 +34,22 @@ public class MemberFixtures { public static final String 매트_프로필 = "/mat.png"; public static Member 관리자() { - return new Member(관리자_이메일, 관리자_이름, 관리자_프로필, SocialType.GOOGLE); + return new Member(관리자_이메일, 관리자_이름, 관리자_프로필, GOOGLE); } public static Member 파랑() { - return new Member(파랑_이메일, 파랑_이름, 파랑_프로필, SocialType.GOOGLE); + return new Member(파랑_이메일, 파랑_이름, 파랑_프로필, GOOGLE); } public static Member 리버() { - return new Member(리버_이메일, 리버_이름, 리버_프로필, SocialType.GOOGLE); + return new Member(리버_이메일, 리버_이름, 리버_프로필, GOOGLE); } public static Member 후디() { - return new Member(후디_이메일, 후디_이름, 후디_프로필, SocialType.GOOGLE); + return new Member(후디_이메일, 후디_이름, 후디_프로필, GOOGLE); } public static Member 매트() { - return new Member(매트_이메일, 매트_이름, 매트_프로필, SocialType.GOOGLE); + return new Member(매트_이메일, 매트_이름, 매트_프로필, GOOGLE); } } diff --git a/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java index ea74dc16..86e10d1a 100644 --- a/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java @@ -2,10 +2,7 @@ import static com.allog.dallog.common.fixtures.AuthFixtures.더미_엑세스_토큰; import static com.allog.dallog.common.fixtures.AuthFixtures.토큰_정보; -import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_이름; -import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_이메일; -import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_프로필; -import static com.allog.dallog.domain.member.domain.SocialType.GOOGLE; +import static com.allog.dallog.common.fixtures.MemberFixtures.파랑_응답; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; @@ -19,8 +16,8 @@ import com.allog.dallog.domain.auth.application.AuthService; import com.allog.dallog.domain.member.application.MemberService; -import com.allog.dallog.domain.member.dto.MemberResponse; import com.allog.dallog.domain.member.exception.NoSuchMemberException; +import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -38,7 +35,7 @@ class MemberControllerTest { private MockMvc mockMvc; @Autowired - private com.fasterxml.jackson.databind.ObjectMapper ObjectMapper; + private ObjectMapper objectMapper; @MockBean private AuthService authService; @@ -50,10 +47,8 @@ class MemberControllerTest { @Test void 자신의_회원_정보를_조회한다() throws Exception { //given - MemberResponse response = new MemberResponse(1L, 파랑_이메일, 파랑_이름, 파랑_프로필, GOOGLE); - - given(memberService.findById(response.getId())).willReturn(response); - given(authService.extractMemberId(더미_엑세스_토큰)).willReturn(response.getId()); + given(memberService.findById(파랑_응답.getId())).willReturn(파랑_응답); + given(authService.extractMemberId(더미_엑세스_토큰)).willReturn(파랑_응답.getId()); // when & then mockMvc.perform(get("/api/members/me") diff --git a/backend/src/test/java/com/allog/dallog/domain/schedule/presentation/ScheduleControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/schedule/presentation/ScheduleControllerTest.java index 856a06c7..e1914703 100644 --- a/backend/src/test/java/com/allog/dallog/domain/schedule/presentation/ScheduleControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/schedule/presentation/ScheduleControllerTest.java @@ -19,9 +19,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.allog.dallog.domain.auth.application.AuthService; +import com.allog.dallog.domain.schedule.application.ScheduleService; import com.allog.dallog.domain.schedule.dto.request.ScheduleCreateRequest; import com.allog.dallog.domain.schedule.dto.response.ScheduleResponse; -import com.allog.dallog.domain.schedule.application.ScheduleService; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import org.junit.jupiter.api.DisplayName; @@ -41,7 +41,7 @@ class ScheduleControllerTest { private MockMvc mockMvc; @Autowired - private ObjectMapper ObjectMapper; + private ObjectMapper objectMapper; @MockBean private AuthService authService; @@ -61,7 +61,7 @@ class ScheduleControllerTest { mockMvc.perform(post("/api/schedules") .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) - .content(ObjectMapper.writeValueAsString(request))) + .content(objectMapper.writeValueAsString(request))) .andDo(print()) .andDo(document("schedule/save", preprocessRequest(prettyPrint()), From 177212bb5b33c11a567751167e9763885b32e9d4 Mon Sep 17 00:00:00 2001 From: koo Date: Thu, 28 Jul 2022 13:07:44 +0900 Subject: [PATCH 0362/1011] =?UTF-8?q?chore:=20.gitignore=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=EC=9D=B4=20index.html=EC=9D=84=20=EB=AC=B4=EC=8B=9C?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/.gitignore | 3 + .../src/main/resources/static/docs/index.html | 941 ------------------ 2 files changed, 3 insertions(+), 941 deletions(-) delete mode 100644 backend/src/main/resources/static/docs/index.html diff --git a/backend/.gitignore b/backend/.gitignore index c2065bc2..6284274d 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -35,3 +35,6 @@ out/ ### VS Code ### .vscode/ + +### resources ### +/src/main/resources/static/docs diff --git a/backend/src/main/resources/static/docs/index.html b/backend/src/main/resources/static/docs/index.html deleted file mode 100644 index 0fe789d0..00000000 --- a/backend/src/main/resources/static/docs/index.html +++ /dev/null @@ -1,941 +0,0 @@ - - - - - - - -달록 API 문서 - - - - - - -
    -
    -

    Auth(인증)

    -
    -
    -

    OAuth 로그인 링크 생성

    -
    -

    Request

    -
    -
    -
    GET /api/auth/oauthProvider/oauth-uri HTTP/1.1
    -Host: localhost:8080
    -
    -
    -
    -
    -

    pathParameters

    - - ---- - - - - - - - - - - - - -
    Table 1. /api/auth/{oauthProvider}/oauth-uri
    ParameterDescription

    oauthProvider

    OAuth 로그인 제공자

    -
    -
    -

    Response

    -
    -
    -
    HTTP/1.1 200 OK
    -Vary: Origin
    -Vary: Access-Control-Request-Method
    -Vary: Access-Control-Request-Headers
    -Content-Type: application/json
    -Content-Length: 67
    -
    -{
    -  "oAuthUri" : "https://accounts.google.com/o/oauth2/v2/auth"
    -}
    -
    -
    -
    -
    -

    ResponseFields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    oAuthUri

    String

    OAuth 소셜 로그인 링크

    -
    -
    -
    -

    OAuth 로그인 : Resource Server 에러

    -
    -

    Request

    -
    -
    -
    POST /api/auth/oauthProvider/token HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Accept: application/json
    -Content-Length: 37
    -Host: localhost:8080
    -
    -{
    -  "code" : "authorization code"
    -}
    -
    -
    -
    -
    -

    RequestFields

    - - ---- - - - - - - - - - - - - -
    Table 2. /api/auth/{oauthProvider}/token
    ParameterDescription

    oauthProvider

    OAuth 로그인 제공자

    -
    -
    -

    RequestFields

    - ----- - - - - - - - - - - - - - - -
    PathTypeDescription

    code

    String

    OAuth 로그인 인증 코드

    -
    -
    -

    Response

    -
    -
    -
    HTTP/1.1 500 Internal Server Error
    -Vary: Origin
    -Vary: Access-Control-Request-Method
    -Vary: Access-Control-Request-Headers
    -Content-Type: application/json
    -Content-Length: 77
    -
    -{
    -  "message" : "OAuth 통신 과정에서 에러가 발생했습니다."
    -}
    -
    -
    -
    -
    -
    -
    -
    -

    Member(회원)

    -
    -
    -

    내 정보 조회

    -
    -

    Request

    -
    -
    -
    GET /api/members/me HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer aaaaa.bbbbb.ccccc
    -Accept: application/json
    -Host: localhost:8080
    -
    -
    -
    -
    -

    RequestHeaders

    - ---- - - - - - - - - - - - - -
    NameDescription

    Authorization

    JWT 토큰

    -
    -
    -

    Response

    -
    -
    -
    HTTP/1.1 200 OK
    -Vary: Origin
    -Vary: Access-Control-Request-Method
    -Vary: Access-Control-Request-Headers
    -Content-Type: application/json
    -Content-Length: 144
    -
    -{
    -  "id" : 1,
    -  "email" : "parang@email.com",
    -  "displayName" : "파랑",
    -  "profileImageUrl" : "/parang.png",
    -  "socialType" : "GOOGLE"
    -}
    -
    -
    -
    -
    -

    ResponseFields

    - ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    PathTypeDescription

    id

    Number

    기본키 값

    email

    String

    이메일

    displayName

    String

    닉네임

    profileImageUrl

    String

    프로필 사진

    socialType

    String

    소셜 로그인 서비스

    -
    -
    -
    -

    삭제된 회원 정보 조회

    -
    -

    Request

    -
    -
    -
    GET /api/members/me HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Authorization: Bearer aaaaa.bbbbb.ccccc
    -Accept: application/json
    -Host: localhost:8080
    -
    -
    -
    -
    -

    RequestHeaders

    - ---- - - - - - - - - - - - - -
    NameDescription

    Authorization

    JWT 토큰

    -
    -
    -

    Response

    -
    -
    -
    HTTP/1.1 404 Not Found
    -Vary: Origin
    -Vary: Access-Control-Request-Method
    -Vary: Access-Control-Request-Headers
    -Content-Type: application/json
    -Content-Length: 58
    -
    -{
    -  "message" : "존재하지 않는 회원입니다."
    -}
    -
    -
    -
    -
    -
    -
    -
    -

    Schedule(일정)

    -
    -
    -

    일정 등록

    -
    -

    Request

    -
    -
    -
    POST /api/schedules HTTP/1.1
    -Content-Type: application/json;charset=UTF-8
    -Accept: application/json
    -Content-Length: 173
    -Host: localhost:8080
    -
    -{
    -  "title" : "알록달록 회의",
    -  "startDateTime" : "2022-07-15T16:00:00",
    -  "endDateTime" : "2022-07-16T16:00:00",
    -  "memo" : "알록달록 회의가 있어요"
    -}
    -
    -
    -
    -
    -

    Response

    -
    -
    -
    HTTP/1.1 201 Created
    -Vary: Origin
    -Vary: Access-Control-Request-Method
    -Vary: Access-Control-Request-Headers
    -Location: /api/schedules/0
    -
    -
    -
    -
    -
    -

    월별 일정 조회

    -
    -

    Request

    -
    -
    -
    GET /api/schedules?year=2022&month=7 HTTP/1.1
    -Accept: application/json
    -Host: localhost:8080
    -
    -
    -
    -
    -

    RequestParameters

    - ---- - - - - - - - - - - - - - - - - -
    ParameterDescription

    year

    년도

    month

    -
    -
    -

    Response

    -
    -
    -
    HTTP/1.1 200 OK
    -Vary: Origin
    -Vary: Access-Control-Request-Method
    -Vary: Access-Control-Request-Headers
    -Content-Type: application/json
    -Content-Length: 224
    -
    -{
    -  "schedules" : [ {
    -    "id" : 1,
    -    "title" : "알록달록 회의",
    -    "startDateTime" : "2022-07-15T16:00:00",
    -    "endDateTime" : "2022-07-16T16:00:00",
    -    "memo" : "알록달록 회의가 있어요"
    -  } ]
    -}
    -
    -
    -
    -
    -
    -
    -
    - - - - - - \ No newline at end of file From 388cfd522e84ac6a961f904f2167f2257a88df9c Mon Sep 17 00:00:00 2001 From: koo Date: Thu, 28 Jul 2022 13:24:19 +0900 Subject: [PATCH 0363/1011] =?UTF-8?q?chore:=20adoc=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=EC=9D=84=20=EB=B6=84=ED=95=A0=ED=95=98=EC=97=AC=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=ED=95=98=EB=8F=84=EB=A1=9D=20gradle=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/build.gradle | 5 +++ backend/src/docs/asciidoc/index.adoc | 53 +------------------------ backend/src/docs/asciidoc/member.adoc | 25 ++++++++++++ backend/src/docs/asciidoc/schedule.adoc | 26 ++++++++++++ 4 files changed, 58 insertions(+), 51 deletions(-) create mode 100644 backend/src/docs/asciidoc/member.adoc create mode 100644 backend/src/docs/asciidoc/schedule.adoc diff --git a/backend/build.gradle b/backend/build.gradle index 28169b7f..3f7ba077 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -48,10 +48,15 @@ test { asciidoctor { configurations 'asciidoctorExtensions' + baseDirFollowsSourceFile() inputs.dir snippetsDir dependsOn test } +asciidoctor.doFirst { + delete file('src/main/resources/static/docs') +} + task copyDocument(type: Copy) { dependsOn asciidoctor diff --git a/backend/src/docs/asciidoc/index.adoc b/backend/src/docs/asciidoc/index.adoc index 1454b1bf..bac7f791 100644 --- a/backend/src/docs/asciidoc/index.adoc +++ b/backend/src/docs/asciidoc/index.adoc @@ -5,54 +5,5 @@ :toc: left :toclevels: 3 -== Schedule(일정) - -=== 일정 등록 - -==== Request - -include::{snippets}/schedule/save/http-request.adoc[] - -==== Response - -include::{snippets}/schedule/save/http-response.adoc[] - -=== 월별 일정 조회 - -==== Request - -include::{snippets}/schedule/find/http-request.adoc[] - -==== RequestParameters - -include::{snippets}/schedule/find/request-parameters.adoc[] - -==== Response - -include::{snippets}/schedule/find/http-response.adoc[] - -== Member(회원) - -=== 내 정보 조회 - -==== Request - -include::{snippets}/member/me/http-request.adoc[] - -==== RequestHeaders - -include::{snippets}/member/me/request-headers.adoc[] - -==== Response - -include::{snippets}/member/me/http-response.adoc[] - -=== 삭제된 회원 정보 조회 - -==== Request - -include::{snippets}/member/exception/notfound/http-request.adoc[] - -==== Response - -include::{snippets}/member/exception/notfound/http-response.adoc[] +include::member.adoc[] +include::schedule.adoc[] diff --git a/backend/src/docs/asciidoc/member.adoc b/backend/src/docs/asciidoc/member.adoc new file mode 100644 index 00000000..9625adc9 --- /dev/null +++ b/backend/src/docs/asciidoc/member.adoc @@ -0,0 +1,25 @@ +== Member(회원) + +=== 내 정보 조회 + +==== Request + +include::{snippets}/member/me/http-request.adoc[] + +==== RequestHeaders + +include::{snippets}/member/me/request-headers.adoc[] + +==== Response + +include::{snippets}/member/me/http-response.adoc[] + +=== 삭제된 회원 정보 조회 + +==== Request + +include::{snippets}/member/exception/notfound/http-request.adoc[] + +==== Response + +include::{snippets}/member/exception/notfound/http-response.adoc[] diff --git a/backend/src/docs/asciidoc/schedule.adoc b/backend/src/docs/asciidoc/schedule.adoc new file mode 100644 index 00000000..d7c1720f --- /dev/null +++ b/backend/src/docs/asciidoc/schedule.adoc @@ -0,0 +1,26 @@ + +== Schedule(일정) + +=== 일정 등록 + +==== Request + +include::{snippets}/schedule/save/http-request.adoc[] + +==== Response + +include::{snippets}/schedule/save/http-response.adoc[] + +=== 월별 일정 조회 + +==== Request + +include::{snippets}/schedule/find/http-request.adoc[] + +==== RequestParameters + +include::{snippets}/schedule/find/request-parameters.adoc[] + +==== Response + +include::{snippets}/schedule/find/http-response.adoc[] From a9447a06b08b71a2851bdb33bd72ace4e82adbd7 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Wed, 27 Jul 2022 13:42:37 +0900 Subject: [PATCH 0364/1011] =?UTF-8?q?refactor:=20=EB=82=98=EC=9D=98=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EB=B0=8F=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MyCategoryList/MyCategoryList.styles.ts | 37 ++++++++++++++ .../MyCategoryList/MyCategoryList.tsx | 49 +++++++++++++++++++ frontend/src/components/SideBar/SideBar.tsx | 36 ++------------ 3 files changed, 89 insertions(+), 33 deletions(-) create mode 100644 frontend/src/components/MyCategoryList/MyCategoryList.styles.ts create mode 100644 frontend/src/components/MyCategoryList/MyCategoryList.tsx diff --git a/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts b/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts new file mode 100644 index 00000000..81d3e762 --- /dev/null +++ b/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts @@ -0,0 +1,37 @@ +import { css, Theme } from '@emotion/react'; + +const list = ({ flex }: Theme, isSideBarOpen: boolean) => css` + ${flex.column} + + display: ${isSideBarOpen ? 'flex' : 'none'}; + gap: 3rem; + + width: 56rem; +`; + +const title = ({ flex }: Theme) => css` + ${flex.row} + + justify-content: space-between; + + width: 100%; + + font-size: 4rem; + font-weight: bold; +`; + +const myCategory = ({ flex }: Theme) => css` + ${flex.row} + + justify-content: space-between; + + width: 56rem; + + font-size: 4rem; +`; + +const button = css` + background: transparent; +`; + +export { button, list, myCategory, title }; diff --git a/frontend/src/components/MyCategoryList/MyCategoryList.tsx b/frontend/src/components/MyCategoryList/MyCategoryList.tsx new file mode 100644 index 00000000..22d344c3 --- /dev/null +++ b/frontend/src/components/MyCategoryList/MyCategoryList.tsx @@ -0,0 +1,49 @@ +import { useTheme } from '@emotion/react'; +import { useRecoilValue } from 'recoil'; + +import useToggle from '@/hooks/useToggle'; + +import { sideBarState } from '@/recoil/atoms'; + +import Button from '@/components/@common/Button/Button'; +import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; +import CategoryAddModal from '@/components/CategoryAddModal/CategoryAddModal'; + +import { FiEdit3, FiPlus } from 'react-icons/fi'; +import { RiDeleteBin6Line } from 'react-icons/ri'; + +import { button, list, myCategory, title } from './MyCategoryList.styles'; + +function MyCategoryList() { + const isSideBarOpen = useRecoilValue(sideBarState); + const theme = useTheme(); + + const { state: isCategoryAddModalOpen, toggleState: toggleCategoryAddModalOpen } = useToggle(); + + return ( +
    +
    + + + + 나의 카테고리 + +
    +
    + 우아한테크코스 FE +
    + + +
    +
    +
    + ); +} + +export default MyCategoryList; diff --git a/frontend/src/components/SideBar/SideBar.tsx b/frontend/src/components/SideBar/SideBar.tsx index b7cec39e..9e0591dd 100644 --- a/frontend/src/components/SideBar/SideBar.tsx +++ b/frontend/src/components/SideBar/SideBar.tsx @@ -1,49 +1,19 @@ import { useTheme } from '@emotion/react'; import { useRecoilValue } from 'recoil'; -import useToggle from '@/hooks/useToggle'; - import { sideBarState } from '@/recoil/atoms'; -import Button from '@/components/@common/Button/Button'; -import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; -import CategoryAddModal from '@/components/CategoryAddModal/CategoryAddModal'; - -import { FiEdit3, FiPlus } from 'react-icons/fi'; -import { RiDeleteBin6Line } from 'react-icons/ri'; +import MyCategoryList from '@/components/MyCategoryList/MyCategoryList'; -import { button, list, myCategory, sideBar, title } from './SideBar.styles'; +import { sideBar } from './SideBar.styles'; function SideBar() { const isSideBarOpen = useRecoilValue(sideBarState); const theme = useTheme(); - const { state: isCategoryAddModalOpen, toggleState: toggleCategoryAddModalOpen } = useToggle(); - return (
    -
    -
    - - - - 나의 카테고리 - -
    -
    - 우아한테크코스 FE -
    - - -
    -
    -
    +
    ); } From 53b1c75dce540569d61de2e8a60639ce70af5bd2 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Thu, 28 Jul 2022 15:53:57 +0900 Subject: [PATCH 0365/1011] =?UTF-8?q?refactor:=20=EC=83=81=EB=8C=80=20?= =?UTF-8?q?=EA=B2=BD=EB=A1=9C=EB=A5=BC=20=EC=A0=88=EB=8C=80=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/ScheduleAddModal/ScheduleAddModal.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx index 579679f2..3ac808d4 100644 --- a/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx +++ b/frontend/src/components/ScheduleAddModal/ScheduleAddModal.tsx @@ -5,6 +5,9 @@ import { useMutation, useQueryClient } from 'react-query'; import { Schedule } from '@/@types'; +import Button from '@/components/@common/Button/Button'; +import FieldSet from '@/components/@common/FieldSet/FieldSet'; + import { CACHE_KEY } from '@/constants'; import { createPostBody } from '@/utils'; @@ -12,8 +15,6 @@ import { getDate, getDateTime } from '@/utils/date'; import scheduleApi from '@/api/schedule'; -import Button from '../@common/Button/Button'; -import FieldSet from '../@common/FieldSet/FieldSet'; import { allDayButton, arrow, From 9bba28423cd7b2f25e6f832f760cd5f0d073020f Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Thu, 28 Jul 2022 22:16:40 +0900 Subject: [PATCH 0366/1011] =?UTF-8?q?feat:=20=EB=82=98=EC=9D=98=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/category.ts | 20 ++++-- .../components/CategoryList/CategoryList.tsx | 2 +- .../MyCategoryList/MyCategoryList.styles.ts | 69 ++++++++++++++++--- .../MyCategoryList/MyCategoryList.tsx | 64 ++++++++++++----- .../src/components/SideBar/SideBar.styles.ts | 3 +- frontend/src/constants/index.ts | 3 +- frontend/src/mocks/handlers.ts | 8 +-- 7 files changed, 131 insertions(+), 38 deletions(-) diff --git a/frontend/src/api/category.ts b/frontend/src/api/category.ts index 512fa6cd..cbde099e 100644 --- a/frontend/src/api/category.ts +++ b/frontend/src/api/category.ts @@ -3,14 +3,17 @@ import { CategoriesGetResponseType, CategoryType } from '@/@types/category'; import dallogApi from './'; const categoryApi = { - endpoint: '/api/categories', + endpoint: { + entire: '/api/categories', + my: '/api/categories/me', + }, headers: { 'Content-Type': 'application/json', Accept: 'application/json', }, - get: async (page: number, size: number) => { - const response = await dallogApi.get(categoryApi.endpoint, { + getEntire: async (page: number, size: number) => { + const response = await dallogApi.get(categoryApi.endpoint.entire, { params: { page, size }, headers: categoryApi.headers, }); @@ -18,8 +21,17 @@ const categoryApi = { return response; }, + getMy: async (accessToken: string | null) => { + const response = await dallogApi.get(categoryApi.endpoint.my, { + headers: { ...categoryApi.headers, Authorization: `Bearer ${accessToken}` }, + transformResponse: (res) => JSON.parse(res).categories, + }); + + return response; + }, + post: async (accessToken: string | null, body: Pick) => { - const response = await dallogApi.post(categoryApi.endpoint, body, { + const response = await dallogApi.post(categoryApi.endpoint.entire, body, { headers: { ...categoryApi.headers, Authorization: `Bearer ${accessToken}` }, }); diff --git a/frontend/src/components/CategoryList/CategoryList.tsx b/frontend/src/components/CategoryList/CategoryList.tsx index 30f36481..ac042465 100644 --- a/frontend/src/components/CategoryList/CategoryList.tsx +++ b/frontend/src/components/CategoryList/CategoryList.tsx @@ -29,7 +29,7 @@ function CategoryList() { hasNextPage, } = useInfiniteQuery, AxiosError>( CACHE_KEY.CATEGORIES, - ({ pageParam = 0 }) => categoryApi.get(pageParam, API.CATEGORY_GET_SIZE), + ({ pageParam = 0 }) => categoryApi.getEntire(pageParam, API.CATEGORY_GET_SIZE), { getNextPageParam: ({ data }) => { if (data.categories.length > 0) { diff --git a/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts b/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts index 81d3e762..d1388bf8 100644 --- a/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts +++ b/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts @@ -1,37 +1,84 @@ import { css, Theme } from '@emotion/react'; -const list = ({ flex }: Theme, isSideBarOpen: boolean) => css` +const listStyle = ({ flex }: Theme, isSideBarOpen: boolean) => css` ${flex.column} display: ${isSideBarOpen ? 'flex' : 'none'}; - gap: 3rem; + justify-content: flex-start; - width: 56rem; + width: 54rem; + + font-size: 4rem; `; -const title = ({ flex }: Theme) => css` +const headerStyle = ({ flex }: Theme) => css` ${flex.row} justify-content: space-between; width: 100%; + margin-bottom: 2rem; - font-size: 4rem; font-weight: bold; `; -const myCategory = ({ flex }: Theme) => css` +const buttonStyle = ({ colors }: Theme) => css` + width: 8rem; + height: 8rem; + + background: transparent; + + color: ${colors.GRAY_700}; + + &:hover { + border-radius: 50%; + + background: ${colors.GRAY_100}; + + filter: none; + } +`; + +const contentStyle = css` + display: flex; + flex-direction: column; + gap: 2rem; + + width: 100%; +`; + +const itemStyle = ({ flex }: Theme) => css` ${flex.row} justify-content: space-between; - width: 56rem; + width: 100%; +`; - font-size: 4rem; +const nameStyle = css` + overflow: hidden; + position: relative; + + width: 32rem; + + white-space: nowrap; + text-overflow: ellipsis; + + &:hover { + cursor: pointer; + } `; -const button = css` - background: transparent; +const controlButtonsStyle = ({ flex }: Theme) => css` + ${flex.row} `; -export { button, list, myCategory, title }; +export { + buttonStyle, + contentStyle, + controlButtonsStyle, + headerStyle, + itemStyle, + listStyle, + nameStyle, +}; diff --git a/frontend/src/components/MyCategoryList/MyCategoryList.tsx b/frontend/src/components/MyCategoryList/MyCategoryList.tsx index 22d344c3..e34f090e 100644 --- a/frontend/src/components/MyCategoryList/MyCategoryList.tsx +++ b/frontend/src/components/MyCategoryList/MyCategoryList.tsx @@ -1,47 +1,79 @@ import { useTheme } from '@emotion/react'; +import { AxiosError, AxiosResponse } from 'axios'; +import { useQuery } from 'react-query'; import { useRecoilValue } from 'recoil'; import useToggle from '@/hooks/useToggle'; -import { sideBarState } from '@/recoil/atoms'; +import { CategoryType } from '@/@types/category'; + +import { sideBarState, userState } from '@/recoil/atoms'; import Button from '@/components/@common/Button/Button'; import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; import CategoryAddModal from '@/components/CategoryAddModal/CategoryAddModal'; +import { CACHE_KEY } from '@/constants'; + +import categoryApi from '@/api/category'; + import { FiEdit3, FiPlus } from 'react-icons/fi'; import { RiDeleteBin6Line } from 'react-icons/ri'; -import { button, list, myCategory, title } from './MyCategoryList.styles'; +import { + buttonStyle, + contentStyle, + controlButtonsStyle, + headerStyle, + itemStyle, + listStyle, + nameStyle, +} from './MyCategoryList.styles'; function MyCategoryList() { - const isSideBarOpen = useRecoilValue(sideBarState); const theme = useTheme(); + const { accessToken } = useRecoilValue(userState); + const isSideBarOpen = useRecoilValue(sideBarState); const { state: isCategoryAddModalOpen, toggleState: toggleCategoryAddModalOpen } = useToggle(); + const { data } = useQuery, AxiosError>( + CACHE_KEY.MY_CATEGORIES, + () => categoryApi.getMy(accessToken) + ); + + if (data === undefined) { + return
    Loading
    ; + } + return ( -
    -
    +
    +
    나의 카테고리 - -
    -
    - 우아한테크코스 FE
    - -
    +
    + {data.data.map((category) => ( +
    + {category.name} +
    + + +
    +
    + ))} +
    ); } diff --git a/frontend/src/components/SideBar/SideBar.styles.ts b/frontend/src/components/SideBar/SideBar.styles.ts index a6218b78..ad80b13f 100644 --- a/frontend/src/components/SideBar/SideBar.styles.ts +++ b/frontend/src/components/SideBar/SideBar.styles.ts @@ -3,7 +3,8 @@ import { css, Theme } from '@emotion/react'; const sideBar = ({ colors, flex }: Theme, isSideBarOpen: boolean) => css` ${flex.row} - overflow: hidden; + align-items: flex-start; + overflow: overlay; position: fixed; z-index: 10; diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index fd95d3fc..aafb7791 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -14,8 +14,9 @@ const CACHE_KEY = { AUTH: 'auth', CATEGORIES: 'categories', ENTER: 'enter', - SCHEDULES: 'schedules', + MY_CATEGORIES: 'myCategories', PROFILE: 'profile', + SCHEDULES: 'schedules', SUBSCRIPTIONS: 'subscriptions', }; diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index ff4cf5f8..52b089b5 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -4,7 +4,7 @@ import { Schedule } from '@/@types'; import { CategoryType } from '@/@types/category'; import { SubscriptionType } from '@/@types/subscription'; -import { API_URL } from '@/constants'; +import { API, API_URL } from '@/constants'; import categoryApi from '@/api/category'; import profileApi from '@/api/profile'; @@ -14,9 +14,9 @@ import subscriptionApi from '@/api/subscription'; import { categoryDB, profileDB, scheduleDB, subscriptionDB } from './data'; const handlers = [ - rest.get(API_URL + categoryApi.endpoint, (req, res, ctx) => { + rest.get(API_URL + categoryApi.endpoint.entire, (req, res, ctx) => { const page = parseInt(req.url.searchParams.get('page') as string); - const size = parseInt(req.url.searchParams.get('size') as string); + const size = API.CATEGORY_GET_SIZE; const slicedCategories = categoryDB.categories.slice(page * size, page * size + size); return res( @@ -28,7 +28,7 @@ const handlers = [ ); }), - rest.post>(API_URL + categoryApi.endpoint, (req, res, ctx) => { + rest.post>(API_URL + categoryApi.endpoint.entire, (req, res, ctx) => { categoryDB.categories.push({ ...req.body, id: categoryDB.categories.length + 1, From ef22acf2e5f2cb6ea9de647fdb9fd15cad95d690 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Thu, 28 Jul 2022 22:18:49 +0900 Subject: [PATCH 0367/1011] =?UTF-8?q?style:=20=EB=82=B4=EB=B9=84=EA=B2=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EB=B0=94=20=EB=A9=94=EB=89=B4=20=EB=B0=8F?= =?UTF-8?q?=20=EB=8B=AC=EB=A0=A5=20=EC=9D=B4=EB=8F=99=20=EB=B2=84=ED=8A=BC?= =?UTF-8?q?=EC=9D=98=20hover=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Calendar/Calendar.styles.ts | 5 ++++- frontend/src/components/NavBar/NavBar.styles.ts | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Calendar/Calendar.styles.ts b/frontend/src/components/Calendar/Calendar.styles.ts index 21623425..1a06919b 100644 --- a/frontend/src/components/Calendar/Calendar.styles.ts +++ b/frontend/src/components/Calendar/Calendar.styles.ts @@ -47,7 +47,10 @@ const navButton = ({ colors }: Theme) => css` &:hover { border-radius: 50%; - background: ${colors.GRAY_300}; + + background: ${colors.GRAY_100}; + + filter: none; } &:hover span { diff --git a/frontend/src/components/NavBar/NavBar.styles.ts b/frontend/src/components/NavBar/NavBar.styles.ts index ad20eab8..4eb0f77c 100644 --- a/frontend/src/components/NavBar/NavBar.styles.ts +++ b/frontend/src/components/NavBar/NavBar.styles.ts @@ -45,7 +45,9 @@ const menu = ({ colors, flex }: Theme) => css` &:hover { border-radius: 50%; - background: ${colors.GRAY_300}; + background: ${colors.GRAY_100}; + + filter: none; } &:hover span { From a1348eae9cdfcd9b0ae3fbefce1470074b745af1 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Thu, 28 Jul 2022 22:31:47 +0900 Subject: [PATCH 0368/1011] =?UTF-8?q?feat:=20msw=20=EB=82=98=EC=9D=98=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EB=AA=A8=ED=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/mocks/data.ts | 168 ++++++++++++++++++++++++++++----- frontend/src/mocks/handlers.ts | 12 ++- 2 files changed, 155 insertions(+), 25 deletions(-) diff --git a/frontend/src/mocks/data.ts b/frontend/src/mocks/data.ts index b73b0167..44eb122a 100644 --- a/frontend/src/mocks/data.ts +++ b/frontend/src/mocks/data.ts @@ -1,6 +1,3 @@ -import { Schedule } from '@/@types'; -import { CategoryType } from '@/@types/category'; - const profileDB = { id: 1, email: 'example@email.com', @@ -9,26 +6,7 @@ const profileDB = { socialType: 'GOOGLE', }; -const scheduleDB: Schedule[] = [ - { - id: 1, - title: '우테코 데모데이', - startDateTime: '2022-07-07T14:00', - endDateTime: '2022-07-07T18:00', - memo: '달록팀 스프린트 1차 발표', - }, - { - id: 2, - title: '테코톡', - startDateTime: '2022-07-09T14:00', - endDateTime: '2022-07-10T20:00', - memo: '레벨3 첫 테코톡', - }, -]; - -const categoryDB: { - categories: CategoryType[]; -} = { +const categoryDB = { categories: [ { id: 1, @@ -141,6 +119,148 @@ const categoryDB: { ], }; +const myCategoryDB = { + categories: [ + { + id: 1, + name: '나의 카테고리 1', + createdAt: '2022-07-04T13:00:00', + creator: profileDB, + }, + { + id: 2, + name: '나의 카테고리 2', + createdAt: '2022-07-08T15:00:00', + creator: profileDB, + }, + { + id: 3, + name: '나의 카테고리 3', + createdAt: '2022-07-05T13:00:00', + creator: profileDB, + }, + { + id: 4, + name: '나의 카테고리 4', + createdAt: '2022-07-03T15:00:00', + creator: profileDB, + }, + { + id: 5, + name: '나의 카테고리 5', + createdAt: '2022-07-02T13:00:00', + creator: profileDB, + }, + { + id: 6, + name: '나의 카테고리 6', + createdAt: '2022-07-01T15:00:00', + creator: profileDB, + }, + { + id: 7, + name: '나의 카테고리 7', + createdAt: '2022-07-11T13:00:00', + creator: profileDB, + }, + { + id: 8, + name: '나의 카테고리 8', + createdAt: '2022-07-12T15:00:00', + creator: profileDB, + }, + { + id: 9, + name: '나의 카테고리 9', + createdAt: '2022-07-13T13:00:00', + creator: profileDB, + }, + { + id: 10, + name: '나의 카테고리 10', + createdAt: '2022-07-14T15:00:00', + creator: profileDB, + }, + { + id: 11, + name: '나의 카테고리 11', + createdAt: '2022-07-15T13:00:00', + creator: profileDB, + }, + { + id: 12, + name: '나의 카테고리 12', + createdAt: '2022-07-16T15:00:00', + creator: profileDB, + }, + { + id: 13, + name: '나의 카테고리 13', + createdAt: '2022-07-18T13:00:00', + creator: profileDB, + }, + { + id: 14, + name: '나의 카테고리 14', + createdAt: '2022-07-20T15:00:00', + creator: profileDB, + }, + { + id: 15, + name: '나의 카테고리 15', + createdAt: '2022-07-12T13:00:00', + creator: profileDB, + }, + { + id: 16, + name: '나의 카테고리 16', + createdAt: '2022-07-13T15:00:00', + creator: profileDB, + }, + { + id: 17, + name: '나의 카테고리 17', + createdAt: '2022-07-25T13:00:00', + creator: profileDB, + }, + { + id: 18, + name: '나의 카테고리 18', + createdAt: '2022-07-30T15:00:00', + creator: profileDB, + }, + { + id: 19, + name: '나의 카테고리 19', + createdAt: '2022-07-30T15:00:00', + creator: profileDB, + }, + { + id: 20, + name: '나의 카테고리 20', + createdAt: '2022-07-30T15:00:00', + creator: profileDB, + }, + ], +}; + +const scheduleDB = [ + { + id: 1, + title: '우테코 데모데이', + startDateTime: '2022-07-07T14:00', + endDateTime: '2022-07-07T18:00', + memo: '달록팀 스프린트 1차 발표', + }, + { + id: 2, + title: '테코톡', + startDateTime: '2022-07-09T14:00', + endDateTime: '2022-07-10T20:00', + memo: '레벨3 첫 테코톡', + }, +]; + const subscriptionDB = { subscriptions: [ { @@ -191,4 +311,4 @@ const subscriptionDB = { ], }; -export { scheduleDB, categoryDB, profileDB, subscriptionDB }; +export { categoryDB, myCategoryDB, profileDB, scheduleDB, subscriptionDB }; diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 52b089b5..ac92f84b 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -11,7 +11,7 @@ import profileApi from '@/api/profile'; import scheduleApi from '@/api/schedule'; import subscriptionApi from '@/api/subscription'; -import { categoryDB, profileDB, scheduleDB, subscriptionDB } from './data'; +import { categoryDB, myCategoryDB, profileDB, scheduleDB, subscriptionDB } from './data'; const handlers = [ rest.get(API_URL + categoryApi.endpoint.entire, (req, res, ctx) => { @@ -35,10 +35,20 @@ const handlers = [ createdAt: new Date().toISOString().slice(0, -5), creator: profileDB, }); + myCategoryDB.categories.push({ + ...req.body, + id: myCategoryDB.categories.length + 1, + createdAt: new Date().toISOString().slice(0, -5), + creator: profileDB, + }); return res(ctx.status(201)); }), + rest.get(API_URL + categoryApi.endpoint.my, (req, res, ctx) => { + return res(ctx.status(200), ctx.json(myCategoryDB)); + }), + rest.get(API_URL + profileApi.endpoint, (req, res, ctx) => { return res(ctx.status(200), ctx.json(profileDB)); }), From d275a3a4e81d482a15d115437356a8b51cacd104 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Thu, 28 Jul 2022 22:33:11 +0900 Subject: [PATCH 0369/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=EC=97=90=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/CategoryAddModal/CategoryAddModal.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx b/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx index a0c7c521..b9d57e22 100644 --- a/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx +++ b/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx @@ -1,7 +1,7 @@ import { useTheme } from '@emotion/react'; import { AxiosError, AxiosResponse } from 'axios'; import { useRef } from 'react'; -import { useMutation } from 'react-query'; +import { useMutation, useQueryClient } from 'react-query'; import { useRecoilValue } from 'recoil'; import { CategoryType } from '@/@types/category'; @@ -11,6 +11,8 @@ import { userState } from '@/recoil/atoms'; import Button from '@/components/@common/Button/Button'; import FieldSet from '@/components/@common/FieldSet/FieldSet'; +import { CACHE_KEY } from '@/constants'; + import { createPostBody } from '@/utils'; import categoryApi from '@/api/category'; @@ -34,6 +36,7 @@ function CategoryAddModal({ closeModal }: CategoryAddModalProps) { const { accessToken } = useRecoilValue(userState); + const queryClient = useQueryClient(); const { mutate: postCategory } = useMutation< AxiosResponse>, AxiosError, @@ -62,6 +65,8 @@ function CategoryAddModal({ closeModal }: CategoryAddModalProps) { }; const onSuccessPostCategory = () => { + queryClient.invalidateQueries(CACHE_KEY.CATEGORIES); + queryClient.invalidateQueries(CACHE_KEY.MY_CATEGORIES); closeModal(); }; From 865c0624f2e4860cc4f17a5f210099a7137408e3 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Thu, 28 Jul 2022 20:24:54 +0900 Subject: [PATCH 0370/1011] =?UTF-8?q?feat:=20truncate=EB=A5=BC=20=EC=A7=84?= =?UTF-8?q?=ED=96=89=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20DatabaseClea?= =?UTF-8?q?nup=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/acceptance/AcceptanceTest.java | 10 +++-- .../allog/dallog/common/DatabaseCleanup.java | 39 +++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 backend/src/test/java/com/allog/dallog/common/DatabaseCleanup.java diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java index e8f7e7ba..5d642a9f 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java @@ -1,23 +1,27 @@ package com.allog.dallog.acceptance; +import com.allog.dallog.common.DatabaseCleanup; import com.allog.dallog.common.config.TestConfig; import io.restassured.RestAssured; import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.context.annotation.Import; -import org.springframework.test.context.jdbc.Sql; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@Sql("/truncate.sql") @Import(TestConfig.class) class AcceptanceTest { @LocalServerPort - int port; + private int port; + + @Autowired + private DatabaseCleanup databaseCleanup; @BeforeEach void setUp() { RestAssured.port = port; + databaseCleanup.execute(); } } diff --git a/backend/src/test/java/com/allog/dallog/common/DatabaseCleanup.java b/backend/src/test/java/com/allog/dallog/common/DatabaseCleanup.java new file mode 100644 index 00000000..132db014 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/common/DatabaseCleanup.java @@ -0,0 +1,39 @@ +package com.allog.dallog.common; + +import java.util.List; +import java.util.stream.Collectors; +import javax.persistence.EntityManager; +import javax.persistence.Table; +import javax.persistence.metamodel.Type; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +public class DatabaseCleanup { + + private final EntityManager entityManager; + private final List tableNames; + + public DatabaseCleanup(final EntityManager entityManager) { + this.entityManager = entityManager; + this.tableNames = entityManager.getMetamodel() + .getEntities() + .stream() + .map(Type::getJavaType) + .map(javaType -> javaType.getAnnotation(Table.class)) + .map(Table::name) + .collect(Collectors.toList()); + } + + @Transactional + public void execute() { + entityManager.flush(); + entityManager.createNativeQuery("SET foreign_key_checks = 0").executeUpdate(); + + for (String tableName : tableNames) { + entityManager.createNativeQuery("TRUNCATE TABLE " + tableName).executeUpdate(); + } + + entityManager.createNativeQuery("SET foreign_key_checks = 1").executeUpdate(); + } +} From 8ddcfbaa3c58998290d351b4da62b496c3363dcb Mon Sep 17 00:00:00 2001 From: hyeonic Date: Fri, 29 Jul 2022 09:58:30 +0900 Subject: [PATCH 0371/1011] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/test/resources/truncate.sql | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 backend/src/test/resources/truncate.sql diff --git a/backend/src/test/resources/truncate.sql b/backend/src/test/resources/truncate.sql deleted file mode 100644 index 5edd93f7..00000000 --- a/backend/src/test/resources/truncate.sql +++ /dev/null @@ -1,7 +0,0 @@ -SET -foreign_key_checks = 0; -TRUNCATE TABLE subscriptions; -TRUNCATE TABLE categories; -TRUNCATE TABLE members; -SET -foreign_key_checks = 1; From 4a236b2ef2f4a46e1a7b2951c8ec7ae4105c5f99 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Fri, 29 Jul 2022 12:06:57 +0900 Subject: [PATCH 0372/1011] =?UTF-8?q?chore:=20Database=20=EC=B4=88?= =?UTF-8?q?=EA=B8=B0=ED=99=94=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/allog/dallog/acceptance/AcceptanceTest.java | 6 +++--- .../common/{DatabaseCleanup.java => DatabaseCleaner.java} | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) rename backend/src/test/java/com/allog/dallog/common/{DatabaseCleanup.java => DatabaseCleaner.java} (92%) diff --git a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java index 5d642a9f..77826cdc 100644 --- a/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java +++ b/backend/src/test/java/com/allog/dallog/acceptance/AcceptanceTest.java @@ -1,6 +1,6 @@ package com.allog.dallog.acceptance; -import com.allog.dallog.common.DatabaseCleanup; +import com.allog.dallog.common.DatabaseCleaner; import com.allog.dallog.common.config.TestConfig; import io.restassured.RestAssured; import org.junit.jupiter.api.BeforeEach; @@ -17,11 +17,11 @@ class AcceptanceTest { private int port; @Autowired - private DatabaseCleanup databaseCleanup; + private DatabaseCleaner databaseCleaner; @BeforeEach void setUp() { RestAssured.port = port; - databaseCleanup.execute(); + databaseCleaner.execute(); } } diff --git a/backend/src/test/java/com/allog/dallog/common/DatabaseCleanup.java b/backend/src/test/java/com/allog/dallog/common/DatabaseCleaner.java similarity index 92% rename from backend/src/test/java/com/allog/dallog/common/DatabaseCleanup.java rename to backend/src/test/java/com/allog/dallog/common/DatabaseCleaner.java index 132db014..7151314a 100644 --- a/backend/src/test/java/com/allog/dallog/common/DatabaseCleanup.java +++ b/backend/src/test/java/com/allog/dallog/common/DatabaseCleaner.java @@ -9,12 +9,12 @@ import org.springframework.transaction.annotation.Transactional; @Component -public class DatabaseCleanup { +public class DatabaseCleaner { private final EntityManager entityManager; private final List tableNames; - public DatabaseCleanup(final EntityManager entityManager) { + public DatabaseCleaner(final EntityManager entityManager) { this.entityManager = entityManager; this.tableNames = entityManager.getMetamodel() .getEntities() From 1fbbc7678589ef462f8d0666235e93dc3510cc89 Mon Sep 17 00:00:00 2001 From: devHudi Date: Fri, 29 Jul 2022 00:52:26 +0900 Subject: [PATCH 0373/1011] =?UTF-8?q?feat:=20ControllerAdvice=EC=97=90=20H?= =?UTF-8?q?ttpMessageNotReadableException=20=ED=95=B8=EB=93=A4=EB=9F=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../allog/dallog/global/presentation/ControllerAdvice.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java b/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java index 682b2443..7dfd179f 100644 --- a/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java +++ b/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java @@ -15,6 +15,7 @@ import com.allog.dallog.infrastructure.oauth.exception.OAuthException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -59,6 +60,12 @@ public ResponseEntity handleOAuthException() { return ResponseEntity.internalServerError().body(errorResponse); } + @ExceptionHandler(HttpMessageNotReadableException.class) + public ResponseEntity handleInvalidRequestBody() { + ErrorResponse errorResponse = new ErrorResponse("잘못된 형식의 Request Body 입니다."); + return ResponseEntity.badRequest().body(errorResponse); + } + @ExceptionHandler(Exception.class) public ResponseEntity handleUnexpectedException() { ErrorResponse errorResponse = new ErrorResponse("예상하지 못한 서버 에러가 발생했습니다."); From f48af0b6b13ec4cadb5edb95c00cdfb212b23d0e Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 28 Jul 2022 17:10:43 +0900 Subject: [PATCH 0374/1011] =?UTF-8?q?feat:=20=ED=8C=94=EB=A0=88=ED=8A=B8?= =?UTF-8?q?=20=EC=83=89=EC=83=81=20=EC=83=81=EC=88=98=ED=99=94=20=EB=B0=8F?= =?UTF-8?q?=20=EC=82=AC=EC=9D=B4=EB=93=9C=20=EB=B0=94=20=EB=82=B4=EB=B6=80?= =?UTF-8?q?=20=EA=B5=AC=EB=8F=85=ED=95=9C=20=EA=B0=9C=EB=B3=84=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FilterCategoryItem.styles.ts | 89 +++++++++++++++++++ .../FilterCategoryItem/FilterCategoryItem.tsx | 55 ++++++++++++ frontend/src/constants/index.ts | 28 ++++++ 3 files changed, 172 insertions(+) create mode 100644 frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts create mode 100644 frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx diff --git a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts new file mode 100644 index 00000000..459092d6 --- /dev/null +++ b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts @@ -0,0 +1,89 @@ +import { css, Theme } from '@emotion/react'; + +const categoryItemStyle = ({ colors, flex }: Theme) => css` + ${flex.row} + + justify-content: space-between; + + width: 64rem; + padding: 2rem 3rem; + + &:hover { + background-color: ${colors.GRAY_100}; + + button { + visibility: visible; + } + } +`; + +const checkBoxNameStyle = ({ flex }: Theme) => css` + ${flex.row} + + gap: 1rem; +`; + +const categoryNameStyle = css` + font-size: 3.5rem; +`; + +const colorStyle = (color: string) => css` + width: 5rem; + height: 5rem; + border-radius: 50%; + + background: ${color}; +`; + +const headerStyle = css` + padding: 2rem; + + font-size: 5rem; +`; + +const iconStyle = css` + visibility: hidden; +`; + +const paletteStyle = ({ colors }: Theme) => css` + position: absolute; + z-index: 30; + display: grid; + grid-template-columns: repeat(4, 1fr); + place-items: center; + gap: 2rem; + + width: 35rem; + padding: 2rem; + border: 1px solid ${colors.GRAY_300}; + border-radius: 4px; + + background: ${colors.WHITE}; +`; + +const paletteLayoutStyle = css` + position: relative; +`; + +const outerStyle = css` + position: fixed; + left: 0; + top: 16rem; + + width: 100%; + height: 100%; + + background-color: transparent; +`; + +export { + categoryItemStyle, + colorStyle, + checkBoxNameStyle, + categoryNameStyle, + headerStyle, + outerStyle, + iconStyle, + paletteStyle, + paletteLayoutStyle, +}; diff --git a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx new file mode 100644 index 00000000..dcf1d816 --- /dev/null +++ b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx @@ -0,0 +1,55 @@ +import useToggle from '@/hooks/useToggle'; + +import { CategoryType } from '@/@types/category'; + +import Button from '@/components/@common/Button/Button'; + +import { PALETTE } from '@/constants'; + +import { BiPalette } from 'react-icons/bi'; +import { RiCheckboxFill } from 'react-icons/ri'; + +import { + categoryItemStyle, + categoryNameStyle, + checkBoxNameStyle, + colorStyle, + iconStyle, + outerStyle, + paletteLayoutStyle, + paletteStyle, +} from './FilterCategoryItem.styles'; + +interface FilterItemProps { + category: CategoryType; +} + +function FilterCategoryItem({ category }: FilterItemProps) { + const { state, toggleState } = useToggle(); + + return ( +
    +
    + + {category.name} +
    +
    + + {state && ( + <> +
    +
    + {PALETTE.map((color) => { + return
    ; + })} +
    + + )} +
    +
    + ); +} + +export default FilterCategoryItem; diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index aafb7791..12d2aab4 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -34,6 +34,33 @@ const STORAGE_KEY = { ACCESS_TOKEN: 'accessToken', }; +const PALETTE = [ + '#FABEC0', + '#F85C70', + '#F37970', + '#E43D40', + '#F9D876', + '#FBE39D', + '#FEDA15', + '#CBAE11', + '#3D550C', + '#81B622', + '#ECF87F', + '#59981A', + '#145DA0', + '#0C2D48', + '#2E8BC0', + '#B1D4E0', + '#BEAFC2', + '#695E93', + '#8155BA', + '#E43480', + '#EAD4C0', + '#BBC4C2', + '#464033', + '#7E7C73', +]; + const PATH = { MAIN: '/', AUTH: '/oauth', @@ -51,5 +78,6 @@ export { DAYS, SELECTOR_KEY, STORAGE_KEY, + PALETTE, PATH, }; From 5b5ba5b86b201d45c001beff1254cfe4470db4e6 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 28 Jul 2022 17:11:06 +0900 Subject: [PATCH 0375/1011] =?UTF-8?q?feat:=20=EC=82=AC=EC=9D=B4=EB=93=9C?= =?UTF-8?q?=20=EB=B0=94=20=EA=B5=AC=EB=8F=85=ED=95=9C=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/@types/subscription.ts | 9 ++-- .../MyFilterCategoryList.styles.ts | 9 ++++ .../MyFilterCategoryList.tsx | 42 +++++++++++++++++++ 3 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.styles.ts create mode 100644 frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.tsx diff --git a/frontend/src/@types/subscription.ts b/frontend/src/@types/subscription.ts index 502bf78d..5c0f777d 100644 --- a/frontend/src/@types/subscription.ts +++ b/frontend/src/@types/subscription.ts @@ -1,14 +1,11 @@ +import { ProfileType } from './profile'; + interface SubscriptionType { id: number; category: { id: number; name: string; - creator: { - displayName: string; - email: string; - id: number; - profileImageUri: string; - }; + creator: ProfileType; createdAt: string; }; color: string; diff --git a/frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.styles.ts b/frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.styles.ts new file mode 100644 index 00000000..eeb12f11 --- /dev/null +++ b/frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.styles.ts @@ -0,0 +1,9 @@ +import { css } from '@emotion/react'; + +const headerStyle = css` + padding: 2rem; + + font-size: 5rem; +`; + +export { headerStyle }; diff --git a/frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.tsx b/frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.tsx new file mode 100644 index 00000000..2aefde32 --- /dev/null +++ b/frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.tsx @@ -0,0 +1,42 @@ +import { AxiosError, AxiosResponse } from 'axios'; +import { useQuery } from 'react-query'; +import { useRecoilValue } from 'recoil'; + +import { SubscriptionType } from '@/@types/subscription'; + +import { userState } from '@/recoil/atoms'; + +import { CACHE_KEY } from '@/constants'; + +import subscriptionApi from '@/api/subscription'; + +import FilterCategoryItem from '../FilterCategoryItem/FilterCategoryItem'; +import { headerStyle } from './MyFilterCategoryList.styles'; + +function MyFilterCategoryList() { + const { accessToken } = useRecoilValue(userState); + + const { data: subscriptionsGetResponse } = useQuery< + AxiosResponse, + AxiosError + >(CACHE_KEY.SUBSCRIPTIONS, () => subscriptionApi.get(accessToken)); + + if (subscriptionsGetResponse === undefined) { + return
    Loading
    ; + } + + const categoryList = subscriptionsGetResponse.data.map((el) => { + return el.category; + }); + + return ( +
    + 구독 카테고리 + {categoryList.map((category) => { + return ; + })} +
    + ); +} + +export default MyFilterCategoryList; From e3eaa5d4a8a20de0ee59bf1f61c52a16630722c2 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Fri, 29 Jul 2022 11:51:26 +0900 Subject: [PATCH 0376/1011] =?UTF-8?q?refactor:=20=EC=82=AC=EC=9D=B4?= =?UTF-8?q?=EB=93=9C=20=EB=B0=94=20=EA=B5=AC=EB=8F=85=ED=95=9C=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FilterCategoryList.styles.ts | 33 +++++++++++++++++++ .../FilterCategoryList.tsx} | 18 ++++++---- .../MyFilterCategoryList.styles.ts | 9 ----- 3 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 frontend/src/components/FilterCategoryList/FilterCategoryList.styles.ts rename frontend/src/components/{MyFilterCategoryList/MyFilterCategoryList.tsx => FilterCategoryList/FilterCategoryList.tsx} (65%) delete mode 100644 frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.styles.ts diff --git a/frontend/src/components/FilterCategoryList/FilterCategoryList.styles.ts b/frontend/src/components/FilterCategoryList/FilterCategoryList.styles.ts new file mode 100644 index 00000000..37098c93 --- /dev/null +++ b/frontend/src/components/FilterCategoryList/FilterCategoryList.styles.ts @@ -0,0 +1,33 @@ +import { css, Theme } from '@emotion/react'; + +const contentStyle = css` + display: flex; + flex-direction: column; + gap: 2rem; + + width: 100%; +`; + +const headerStyle = ({ flex }: Theme) => css` + ${flex.row} + + justify-content: space-between; + + width: 100%; + margin-bottom: 2rem; + + font-weight: bold; +`; + +const listStyle = ({ flex }: Theme, isSideBarOpen: boolean) => css` + ${flex.column} + + display: ${isSideBarOpen ? 'flex' : 'none'}; + justify-content: flex-start; + + width: 54rem; + + font-size: 4rem; +`; + +export { contentStyle, headerStyle, listStyle }; diff --git a/frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.tsx b/frontend/src/components/FilterCategoryList/FilterCategoryList.tsx similarity index 65% rename from frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.tsx rename to frontend/src/components/FilterCategoryList/FilterCategoryList.tsx index 2aefde32..78e08b4b 100644 --- a/frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.tsx +++ b/frontend/src/components/FilterCategoryList/FilterCategoryList.tsx @@ -1,21 +1,25 @@ +import { useTheme } from '@emotion/react'; import { AxiosError, AxiosResponse } from 'axios'; import { useQuery } from 'react-query'; import { useRecoilValue } from 'recoil'; import { SubscriptionType } from '@/@types/subscription'; -import { userState } from '@/recoil/atoms'; +import { sideBarState, userState } from '@/recoil/atoms'; import { CACHE_KEY } from '@/constants'; import subscriptionApi from '@/api/subscription'; import FilterCategoryItem from '../FilterCategoryItem/FilterCategoryItem'; -import { headerStyle } from './MyFilterCategoryList.styles'; +import { contentStyle, headerStyle, listStyle } from './FilterCategoryList.styles'; function MyFilterCategoryList() { + const isSideBarOpen = useRecoilValue(sideBarState); const { accessToken } = useRecoilValue(userState); + const theme = useTheme(); + const { data: subscriptionsGetResponse } = useQuery< AxiosResponse, AxiosError @@ -30,11 +34,13 @@ function MyFilterCategoryList() { }); return ( -
    +
    구독 카테고리 - {categoryList.map((category) => { - return ; - })} +
    + {categoryList.map((category) => { + return ; + })} +
    ); } diff --git a/frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.styles.ts b/frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.styles.ts deleted file mode 100644 index eeb12f11..00000000 --- a/frontend/src/components/MyFilterCategoryList/MyFilterCategoryList.styles.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { css } from '@emotion/react'; - -const headerStyle = css` - padding: 2rem; - - font-size: 5rem; -`; - -export { headerStyle }; From a76d48edbb46f15b7deb9d58d9bb9fc8d66edc7d Mon Sep 17 00:00:00 2001 From: jhy979 Date: Fri, 29 Jul 2022 11:52:20 +0900 Subject: [PATCH 0377/1011] =?UTF-8?q?style:=20=EC=82=AC=EC=9D=B4=EB=93=9C?= =?UTF-8?q?=20=EB=B0=94=20=EA=B5=AC=EB=8F=85=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CategoryList/CategoryList.styles.ts | 3 --- .../FilterCategoryItem.styles.ts | 26 ++++++++++++++----- .../FilterCategoryItem/FilterCategoryItem.tsx | 12 ++++----- .../src/components/SideBar/SideBar.styles.ts | 2 +- frontend/src/components/SideBar/SideBar.tsx | 2 ++ 5 files changed, 28 insertions(+), 17 deletions(-) diff --git a/frontend/src/components/CategoryList/CategoryList.styles.ts b/frontend/src/components/CategoryList/CategoryList.styles.ts index fb441e5d..1bd5e2ad 100644 --- a/frontend/src/components/CategoryList/CategoryList.styles.ts +++ b/frontend/src/components/CategoryList/CategoryList.styles.ts @@ -1,10 +1,7 @@ import { css, Theme } from '@emotion/react'; const categoryTable = css` - overflow-y: scroll; - width: 100%; - height: 72vh; `; const categoryTableHeader = ({ flex, colors }: Theme) => css` diff --git a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts index 459092d6..5360c482 100644 --- a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts +++ b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts @@ -1,12 +1,11 @@ import { css, Theme } from '@emotion/react'; -const categoryItemStyle = ({ colors, flex }: Theme) => css` +const itemStyle = ({ colors, flex }: Theme) => css` ${flex.row} justify-content: space-between; - width: 64rem; - padding: 2rem 3rem; + width: 100%; &:hover { background-color: ${colors.GRAY_100}; @@ -23,8 +22,18 @@ const checkBoxNameStyle = ({ flex }: Theme) => css` gap: 1rem; `; -const categoryNameStyle = css` - font-size: 3.5rem; +const nameStyle = css` + overflow: hidden; + position: relative; + + width: 32rem; + + white-space: nowrap; + text-overflow: ellipsis; + + &:hover { + cursor: pointer; + } `; const colorStyle = (color: string) => css` @@ -47,7 +56,9 @@ const iconStyle = css` const paletteStyle = ({ colors }: Theme) => css` position: absolute; + right: 0; z-index: 30; + display: grid; grid-template-columns: repeat(4, 1fr); place-items: center; @@ -69,6 +80,7 @@ const outerStyle = css` position: fixed; left: 0; top: 16rem; + z-index: 20; width: 100%; height: 100%; @@ -77,10 +89,10 @@ const outerStyle = css` `; export { - categoryItemStyle, + itemStyle, colorStyle, checkBoxNameStyle, - categoryNameStyle, + nameStyle, headerStyle, outerStyle, iconStyle, diff --git a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx index dcf1d816..87ca3125 100644 --- a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx +++ b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx @@ -10,11 +10,11 @@ import { BiPalette } from 'react-icons/bi'; import { RiCheckboxFill } from 'react-icons/ri'; import { - categoryItemStyle, - categoryNameStyle, checkBoxNameStyle, colorStyle, iconStyle, + itemStyle, + nameStyle, outerStyle, paletteLayoutStyle, paletteStyle, @@ -28,14 +28,14 @@ function FilterCategoryItem({ category }: FilterItemProps) { const { state, toggleState } = useToggle(); return ( -
    +
    - - {category.name} + + {category.name}
    {state && ( <> diff --git a/frontend/src/components/SideBar/SideBar.styles.ts b/frontend/src/components/SideBar/SideBar.styles.ts index ad80b13f..7f211882 100644 --- a/frontend/src/components/SideBar/SideBar.styles.ts +++ b/frontend/src/components/SideBar/SideBar.styles.ts @@ -1,7 +1,7 @@ import { css, Theme } from '@emotion/react'; const sideBar = ({ colors, flex }: Theme, isSideBarOpen: boolean) => css` - ${flex.row} + ${flex.col} align-items: flex-start; overflow: overlay; diff --git a/frontend/src/components/SideBar/SideBar.tsx b/frontend/src/components/SideBar/SideBar.tsx index 9e0591dd..93c85268 100644 --- a/frontend/src/components/SideBar/SideBar.tsx +++ b/frontend/src/components/SideBar/SideBar.tsx @@ -3,6 +3,7 @@ import { useRecoilValue } from 'recoil'; import { sideBarState } from '@/recoil/atoms'; +import MyFilterCategoryList from '@/components/FilterCategoryList/FilterCategoryList'; import MyCategoryList from '@/components/MyCategoryList/MyCategoryList'; import { sideBar } from './SideBar.styles'; @@ -13,6 +14,7 @@ function SideBar() { return (
    +
    ); From 494c2f198a0feede998f214eb54df2ec46a90aa0 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Fri, 29 Jul 2022 12:14:04 +0900 Subject: [PATCH 0378/1011] =?UTF-8?q?style:=20=EC=82=AC=EC=9D=B4=EB=93=9C?= =?UTF-8?q?=20=EB=B0=94=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/CategoryList/CategoryList.styles.ts | 3 +++ .../FilterCategoryItem/FilterCategoryItem.styles.ts | 1 + .../FilterCategoryList/FilterCategoryList.styles.ts | 1 + .../src/components/MyCategoryList/MyCategoryList.styles.ts | 3 +++ frontend/src/components/SideBar/SideBar.tsx | 4 ++-- 5 files changed, 10 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/CategoryList/CategoryList.styles.ts b/frontend/src/components/CategoryList/CategoryList.styles.ts index 1bd5e2ad..cb8a323b 100644 --- a/frontend/src/components/CategoryList/CategoryList.styles.ts +++ b/frontend/src/components/CategoryList/CategoryList.styles.ts @@ -1,7 +1,10 @@ import { css, Theme } from '@emotion/react'; const categoryTable = css` + overflow-y: overlay; + width: 100%; + height: 72vh; `; const categoryTableHeader = ({ flex, colors }: Theme) => css` diff --git a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts index 5360c482..e274d227 100644 --- a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts +++ b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts @@ -6,6 +6,7 @@ const itemStyle = ({ colors, flex }: Theme) => css` justify-content: space-between; width: 100%; + height: 8rem; &:hover { background-color: ${colors.GRAY_100}; diff --git a/frontend/src/components/FilterCategoryList/FilterCategoryList.styles.ts b/frontend/src/components/FilterCategoryList/FilterCategoryList.styles.ts index 37098c93..bac03956 100644 --- a/frontend/src/components/FilterCategoryList/FilterCategoryList.styles.ts +++ b/frontend/src/components/FilterCategoryList/FilterCategoryList.styles.ts @@ -14,6 +14,7 @@ const headerStyle = ({ flex }: Theme) => css` justify-content: space-between; width: 100%; + height: 8rem; margin-bottom: 2rem; font-weight: bold; diff --git a/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts b/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts index d1388bf8..3e1c0c2c 100644 --- a/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts +++ b/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts @@ -7,6 +7,7 @@ const listStyle = ({ flex }: Theme, isSideBarOpen: boolean) => css` justify-content: flex-start; width: 54rem; + margin-top: 5rem; font-size: 4rem; `; @@ -17,6 +18,7 @@ const headerStyle = ({ flex }: Theme) => css` justify-content: space-between; width: 100%; + height: 8rem; margin-bottom: 2rem; font-weight: bold; @@ -53,6 +55,7 @@ const itemStyle = ({ flex }: Theme) => css` justify-content: space-between; width: 100%; + height: 8rem; `; const nameStyle = css` diff --git a/frontend/src/components/SideBar/SideBar.tsx b/frontend/src/components/SideBar/SideBar.tsx index 93c85268..b5cd3874 100644 --- a/frontend/src/components/SideBar/SideBar.tsx +++ b/frontend/src/components/SideBar/SideBar.tsx @@ -3,7 +3,7 @@ import { useRecoilValue } from 'recoil'; import { sideBarState } from '@/recoil/atoms'; -import MyFilterCategoryList from '@/components/FilterCategoryList/FilterCategoryList'; +import FilterCategoryList from '@/components/FilterCategoryList/FilterCategoryList'; import MyCategoryList from '@/components/MyCategoryList/MyCategoryList'; import { sideBar } from './SideBar.styles'; @@ -14,7 +14,7 @@ function SideBar() { return (
    - +
    ); From 205999a5b77070b401447617bd77db4f6679fa04 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Fri, 29 Jul 2022 12:35:45 +0900 Subject: [PATCH 0379/1011] =?UTF-8?q?refactor:=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/FilterCategoryList/FilterCategoryList.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/FilterCategoryList/FilterCategoryList.tsx b/frontend/src/components/FilterCategoryList/FilterCategoryList.tsx index 78e08b4b..f483b69d 100644 --- a/frontend/src/components/FilterCategoryList/FilterCategoryList.tsx +++ b/frontend/src/components/FilterCategoryList/FilterCategoryList.tsx @@ -14,7 +14,7 @@ import subscriptionApi from '@/api/subscription'; import FilterCategoryItem from '../FilterCategoryItem/FilterCategoryItem'; import { contentStyle, headerStyle, listStyle } from './FilterCategoryList.styles'; -function MyFilterCategoryList() { +function FilterCategoryList() { const isSideBarOpen = useRecoilValue(sideBarState); const { accessToken } = useRecoilValue(userState); @@ -45,4 +45,4 @@ function MyFilterCategoryList() { ); } -export default MyFilterCategoryList; +export default FilterCategoryList; From 53e5f7f41054298e592d72736fb7a156a39b9d6b Mon Sep 17 00:00:00 2001 From: jhy979 Date: Fri, 29 Jul 2022 12:36:00 +0900 Subject: [PATCH 0380/1011] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/SideBar/SideBar.styles.ts | 36 +------------------ 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/frontend/src/components/SideBar/SideBar.styles.ts b/frontend/src/components/SideBar/SideBar.styles.ts index 7f211882..9f4b366c 100644 --- a/frontend/src/components/SideBar/SideBar.styles.ts +++ b/frontend/src/components/SideBar/SideBar.styles.ts @@ -18,38 +18,4 @@ const sideBar = ({ colors, flex }: Theme, isSideBarOpen: boolean) => css` transition: width 0.3s; `; -const list = ({ flex }: Theme, isSideBarOpen: boolean) => css` - ${flex.column} - - display: ${isSideBarOpen ? 'flex' : 'none'}; - gap: 3rem; - - width: 56rem; -`; - -const title = ({ flex }: Theme) => css` - ${flex.row} - - justify-content: space-between; - - width: 100%; - - font-size: 4rem; - font-weight: bold; -`; - -const myCategory = ({ flex }: Theme) => css` - ${flex.row} - - justify-content: space-between; - - width: 56rem; - - font-size: 4rem; -`; - -const button = css` - background: transparent; -`; - -export { button, list, myCategory, sideBar, title }; +export { sideBar }; From 64cb1c6379a35c32bb4a9838d06ef7198cff0517 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Fri, 29 Jul 2022 12:38:45 +0900 Subject: [PATCH 0381/1011] =?UTF-8?q?style:=20=EC=82=AC=EC=9D=B4=EB=93=9C?= =?UTF-8?q?=20=EB=B0=94=20=EB=82=B4=EB=B6=80=20=EC=97=AC=EB=B0=B1=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/SideBar/SideBar.styles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/SideBar/SideBar.styles.ts b/frontend/src/components/SideBar/SideBar.styles.ts index 9f4b366c..282e5d66 100644 --- a/frontend/src/components/SideBar/SideBar.styles.ts +++ b/frontend/src/components/SideBar/SideBar.styles.ts @@ -10,7 +10,7 @@ const sideBar = ({ colors, flex }: Theme, isSideBarOpen: boolean) => css` width: ${isSideBarOpen ? '64rem' : '0'}; height: calc(100vh - 16rem); - padding: ${isSideBarOpen ? '5rem' : '0'}; + padding: ${isSideBarOpen ? '4rem' : '0'}; border: 1px solid ${colors.GRAY_400}; background: ${colors.WHITE}; From 2a4b20852d7f2e16da7ad7c80ac704459d3cb94e Mon Sep 17 00:00:00 2001 From: jhy979 Date: Fri, 29 Jul 2022 12:49:33 +0900 Subject: [PATCH 0382/1011] =?UTF-8?q?refactor:=20=ED=8C=94=EB=A0=88?= =?UTF-8?q?=ED=8A=B8=20hover=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EB=B0=8F=20=ED=8C=94=EB=A0=88=ED=8A=B8=20toggle=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FilterCategoryItem/FilterCategoryItem.styles.ts | 5 +++++ .../FilterCategoryItem/FilterCategoryItem.tsx | 10 +++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts index e274d227..be61c3da 100644 --- a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts +++ b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.styles.ts @@ -43,6 +43,11 @@ const colorStyle = (color: string) => css` border-radius: 50%; background: ${color}; + + &:hover { + filter: none; + transform: scale(1.2); + } `; const headerStyle = css` diff --git a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx index 87ca3125..f95f1184 100644 --- a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx +++ b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx @@ -25,7 +25,7 @@ interface FilterItemProps { } function FilterCategoryItem({ category }: FilterItemProps) { - const { state, toggleState } = useToggle(); + const { state: isPaletteOpen, toggleState: togglePaletteOpen } = useToggle(); return (
    @@ -34,15 +34,15 @@ function FilterCategoryItem({ category }: FilterItemProps) { {category.name}
    - - {state && ( + {isPaletteOpen && ( <> -
    +
    {PALETTE.map((color) => { - return
    ; + return ; })}
    From 9eb4513be45e6cf65446a161678e255631893df1 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Fri, 29 Jul 2022 14:58:45 +0900 Subject: [PATCH 0383/1011] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0=20?= =?UTF-8?q?=EB=B0=8F=20=EC=83=81=EB=8C=80=20=EA=B2=BD=EB=A1=9C=EC=99=80=20?= =?UTF-8?q?=EB=B3=84=EC=B9=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FilterCategoryItem/FilterCategoryItem.tsx | 2 +- .../FilterCategoryList/FilterCategoryList.tsx | 15 ++++++++------- frontend/src/components/SideBar/SideBar.styles.ts | 5 +---- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx index f95f1184..2080774c 100644 --- a/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx +++ b/frontend/src/components/FilterCategoryItem/FilterCategoryItem.tsx @@ -28,7 +28,7 @@ function FilterCategoryItem({ category }: FilterItemProps) { const { state: isPaletteOpen, toggleState: togglePaletteOpen } = useToggle(); return ( -
    +
    {category.name} diff --git a/frontend/src/components/FilterCategoryList/FilterCategoryList.tsx b/frontend/src/components/FilterCategoryList/FilterCategoryList.tsx index f483b69d..68c1845d 100644 --- a/frontend/src/components/FilterCategoryList/FilterCategoryList.tsx +++ b/frontend/src/components/FilterCategoryList/FilterCategoryList.tsx @@ -7,11 +7,12 @@ import { SubscriptionType } from '@/@types/subscription'; import { sideBarState, userState } from '@/recoil/atoms'; +import FilterCategoryItem from '@/components/FilterCategoryItem/FilterCategoryItem'; + import { CACHE_KEY } from '@/constants'; import subscriptionApi from '@/api/subscription'; -import FilterCategoryItem from '../FilterCategoryItem/FilterCategoryItem'; import { contentStyle, headerStyle, listStyle } from './FilterCategoryList.styles'; function FilterCategoryList() { @@ -20,16 +21,16 @@ function FilterCategoryList() { const theme = useTheme(); - const { data: subscriptionsGetResponse } = useQuery< - AxiosResponse, - AxiosError - >(CACHE_KEY.SUBSCRIPTIONS, () => subscriptionApi.get(accessToken)); + const { data } = useQuery, AxiosError>( + CACHE_KEY.SUBSCRIPTIONS, + () => subscriptionApi.get(accessToken) + ); - if (subscriptionsGetResponse === undefined) { + if (data === undefined) { return
    Loading
    ; } - const categoryList = subscriptionsGetResponse.data.map((el) => { + const categoryList = data.data.map((el) => { return el.category; }); diff --git a/frontend/src/components/SideBar/SideBar.styles.ts b/frontend/src/components/SideBar/SideBar.styles.ts index 282e5d66..bb6ef569 100644 --- a/frontend/src/components/SideBar/SideBar.styles.ts +++ b/frontend/src/components/SideBar/SideBar.styles.ts @@ -1,9 +1,6 @@ import { css, Theme } from '@emotion/react'; -const sideBar = ({ colors, flex }: Theme, isSideBarOpen: boolean) => css` - ${flex.col} - - align-items: flex-start; +const sideBar = ({ colors }: Theme, isSideBarOpen: boolean) => css` overflow: overlay; position: fixed; z-index: 10; From b87072250420bce78ddef01b09c39e8271a14304 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Fri, 29 Jul 2022 14:49:11 +0900 Subject: [PATCH 0384/1011] =?UTF-8?q?fix:=20=EB=82=98=EC=9D=98=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=EC=9D=98=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20id=EB=A5=BC=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=EC=9D=98=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20id?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/mocks/data.ts | 227 ++++++++++++++------------------- frontend/src/mocks/handlers.ts | 12 +- 2 files changed, 100 insertions(+), 139 deletions(-) diff --git a/frontend/src/mocks/data.ts b/frontend/src/mocks/data.ts index 44eb122a..84ae50c2 100644 --- a/frontend/src/mocks/data.ts +++ b/frontend/src/mocks/data.ts @@ -1,4 +1,4 @@ -const profileDB = { +const matProfileDB = { id: 1, email: 'example@email.com', displayName: '매트', @@ -6,240 +6,201 @@ const profileDB = { socialType: 'GOOGLE', }; +const tigerProfileDB = { + id: 2, + email: 'tiger@dallog.com', + displayName: '티거', + profileImageUrl: + 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRBo4PPBaz3xqgKPEs8W2djKBXYb2D8PFDkZg&usqp=CAU', + socialType: 'GOOGLE', +}; + const categoryDB = { categories: [ { id: 1, - name: 'BE 공식일정', + name: 'BE 공식 일정', createdAt: '2022-07-04T13:00:00', - creator: profileDB, + creator: matProfileDB, }, { id: 2, - name: '알록달록 팀 회의', + name: '알록달록', createdAt: '2022-07-08T15:00:00', - creator: profileDB, + creator: matProfileDB, }, { id: 3, - name: '카테고리 3', + name: '공원조', createdAt: '2022-07-05T13:00:00', - creator: profileDB, + creator: tigerProfileDB, }, { id: 4, - name: '카테고리 4', + name: '자바 스터디', createdAt: '2022-07-03T15:00:00', - creator: profileDB, + creator: matProfileDB, }, { id: 5, - name: '카테고리 5', + name: '코틀린 스터디', createdAt: '2022-07-02T13:00:00', - creator: profileDB, + creator: matProfileDB, }, { id: 6, - name: '카테고리 6', + name: '지원 플랫폼 근로', createdAt: '2022-07-01T15:00:00', - creator: profileDB, + creator: matProfileDB, }, { id: 7, - name: '카테고리 7', - createdAt: '2022-07-11T13:00:00', - creator: profileDB, + name: '레벨 2 준조', + createdAt: '2022-07-08T15:00:00', + creator: tigerProfileDB, }, { id: 8, - name: '카테고리 8', + name: '레벨 1 네오조', createdAt: '2022-07-12T15:00:00', - creator: profileDB, + creator: matProfileDB, }, { id: 9, - name: '카테고리 9', + name: '매트의 아고라', createdAt: '2022-07-13T13:00:00', - creator: profileDB, + creator: matProfileDB, }, { id: 10, - name: '카테고리 10', - createdAt: '2022-07-14T15:00:00', - creator: profileDB, + name: '자바스크립트 스터디', + createdAt: '2022-07-05T13:00:00', + creator: tigerProfileDB, }, { id: 11, - name: '카테고리 11', - createdAt: '2022-07-15T13:00:00', - creator: profileDB, + name: '리액트 스터디', + createdAt: '2022-07-03T15:00:00', + creator: tigerProfileDB, }, { id: 12, - name: '카테고리 12', + name: 'FE 공식 일정', createdAt: '2022-07-16T15:00:00', - creator: profileDB, + creator: tigerProfileDB, }, { id: 13, - name: '카테고리 13', + name: '레벨 2 브리조', createdAt: '2022-07-18T13:00:00', - creator: profileDB, + creator: matProfileDB, }, { id: 14, - name: '카테고리 14', + name: '세미나', createdAt: '2022-07-20T15:00:00', - creator: profileDB, + creator: matProfileDB, }, { id: 15, - name: '카테고리 15', - createdAt: '2022-07-12T13:00:00', - creator: profileDB, + name: '네오 면담', + createdAt: '2022-07-01T15:00:00', + creator: tigerProfileDB, }, { id: 16, - name: '카테고리 16', - createdAt: '2022-07-13T15:00:00', - creator: profileDB, + name: '공원 면담', + createdAt: '2022-07-11T13:00:00', + creator: tigerProfileDB, }, { id: 17, - name: '카테고리 17', - createdAt: '2022-07-25T13:00:00', - creator: profileDB, + name: '포코 면담', + createdAt: '2022-07-12T15:00:00', + creator: tigerProfileDB, }, { id: 18, - name: '카테고리 18', - createdAt: '2022-07-30T15:00:00', - creator: profileDB, + name: '포비의 수다 타임', + createdAt: '2022-07-13T13:00:00', + creator: matProfileDB, + }, + { + id: 19, + name: '튼튼이 클럽', + createdAt: '2022-07-13T13:00:00', + creator: tigerProfileDB, + }, + { + id: 20, + name: '한강팟', + createdAt: '2022-07-14T15:00:00', + creator: tigerProfileDB, }, ], }; const myCategoryDB = { categories: [ - { - id: 1, - name: '나의 카테고리 1', - createdAt: '2022-07-04T13:00:00', - creator: profileDB, - }, - { - id: 2, - name: '나의 카테고리 2', - createdAt: '2022-07-08T15:00:00', - creator: profileDB, - }, { id: 3, - name: '나의 카테고리 3', + name: '레벨 1 공원조', createdAt: '2022-07-05T13:00:00', - creator: profileDB, - }, - { - id: 4, - name: '나의 카테고리 4', - createdAt: '2022-07-03T15:00:00', - creator: profileDB, - }, - { - id: 5, - name: '나의 카테고리 5', - createdAt: '2022-07-02T13:00:00', - creator: profileDB, - }, - { - id: 6, - name: '나의 카테고리 6', - createdAt: '2022-07-01T15:00:00', - creator: profileDB, + creator: tigerProfileDB, }, { id: 7, - name: '나의 카테고리 7', - createdAt: '2022-07-11T13:00:00', - creator: profileDB, - }, - { - id: 8, - name: '나의 카테고리 8', - createdAt: '2022-07-12T15:00:00', - creator: profileDB, - }, - { - id: 9, - name: '나의 카테고리 9', - createdAt: '2022-07-13T13:00:00', - creator: profileDB, + name: '레벨 2 준조', + createdAt: '2022-07-08T15:00:00', + creator: tigerProfileDB, }, { id: 10, - name: '나의 카테고리 10', - createdAt: '2022-07-14T15:00:00', - creator: profileDB, + name: '자바스크립트 스터디', + createdAt: '2022-07-05T13:00:00', + creator: tigerProfileDB, }, { id: 11, - name: '나의 카테고리 11', - createdAt: '2022-07-15T13:00:00', - creator: profileDB, + name: '리액트 스터디', + createdAt: '2022-07-03T15:00:00', + creator: tigerProfileDB, }, { id: 12, - name: '나의 카테고리 12', + name: 'FE 공식 일정', createdAt: '2022-07-16T15:00:00', - creator: profileDB, - }, - { - id: 13, - name: '나의 카테고리 13', - createdAt: '2022-07-18T13:00:00', - creator: profileDB, - }, - { - id: 14, - name: '나의 카테고리 14', - createdAt: '2022-07-20T15:00:00', - creator: profileDB, + creator: tigerProfileDB, }, { id: 15, - name: '나의 카테고리 15', - createdAt: '2022-07-12T13:00:00', - creator: profileDB, + name: '네오 면담', + createdAt: '2022-07-01T15:00:00', + creator: tigerProfileDB, }, { id: 16, - name: '나의 카테고리 16', - createdAt: '2022-07-13T15:00:00', - creator: profileDB, + name: '공원 면담', + createdAt: '2022-07-11T13:00:00', + creator: tigerProfileDB, }, { id: 17, - name: '나의 카테고리 17', - createdAt: '2022-07-25T13:00:00', - creator: profileDB, - }, - { - id: 18, - name: '나의 카테고리 18', - createdAt: '2022-07-30T15:00:00', - creator: profileDB, + name: '포코 면담', + createdAt: '2022-07-12T15:00:00', + creator: tigerProfileDB, }, { id: 19, - name: '나의 카테고리 19', - createdAt: '2022-07-30T15:00:00', - creator: profileDB, + name: '튼튼이 클럽', + createdAt: '2022-07-13T13:00:00', + creator: tigerProfileDB, }, { id: 20, - name: '나의 카테고리 20', - createdAt: '2022-07-30T15:00:00', - creator: profileDB, + name: '한강팟', + createdAt: '2022-07-14T15:00:00', + creator: tigerProfileDB, }, ], }; @@ -311,4 +272,4 @@ const subscriptionDB = { ], }; -export { categoryDB, myCategoryDB, profileDB, scheduleDB, subscriptionDB }; +export { categoryDB, matProfileDB, myCategoryDB, scheduleDB, subscriptionDB, tigerProfileDB }; diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index ac92f84b..d3af8946 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -11,7 +11,7 @@ import profileApi from '@/api/profile'; import scheduleApi from '@/api/schedule'; import subscriptionApi from '@/api/subscription'; -import { categoryDB, myCategoryDB, profileDB, scheduleDB, subscriptionDB } from './data'; +import { categoryDB, myCategoryDB, scheduleDB, subscriptionDB, tigerProfileDB } from './data'; const handlers = [ rest.get(API_URL + categoryApi.endpoint.entire, (req, res, ctx) => { @@ -33,13 +33,13 @@ const handlers = [ ...req.body, id: categoryDB.categories.length + 1, createdAt: new Date().toISOString().slice(0, -5), - creator: profileDB, + creator: tigerProfileDB, }); myCategoryDB.categories.push({ ...req.body, - id: myCategoryDB.categories.length + 1, + id: categoryDB.categories.length + 1, createdAt: new Date().toISOString().slice(0, -5), - creator: profileDB, + creator: tigerProfileDB, }); return res(ctx.status(201)); @@ -50,7 +50,7 @@ const handlers = [ }), rest.get(API_URL + profileApi.endpoint, (req, res, ctx) => { - return res(ctx.status(200), ctx.json(profileDB)); + return res(ctx.status(200), ctx.json(tigerProfileDB)); }), rest.get(API_URL + scheduleApi.endpoint, (req, res, ctx) => { @@ -77,7 +77,7 @@ const handlers = [ category: { id: categoryDB.categories[categoryId - 1].id, name: categoryDB.categories[categoryId - 1].name, - creator: profileDB, + creator: tigerProfileDB, createdAt: categoryDB.categories[categoryId - 1].createdAt, }, color: req.body.color, From f674ecff6055163fae54ddc8c4430461d41b9fc7 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Fri, 29 Jul 2022 15:15:26 +0900 Subject: [PATCH 0385/1011] =?UTF-8?q?refactor:=20=EB=82=98=EC=9D=98=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EB=AA=A9=EB=A1=9D?= =?UTF-8?q?=EC=9D=98=20=EC=9A=94=EC=86=8C=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MyCategoryItem/MyCategoryItem.style.ts | 46 +++++++++++++++++++ .../MyCategoryItem/MyCategoryItem.tsx | 30 ++++++++++++ .../MyCategoryList/MyCategoryList.styles.ts | 37 +-------------- .../MyCategoryList/MyCategoryList.tsx | 26 ++--------- 4 files changed, 81 insertions(+), 58 deletions(-) create mode 100644 frontend/src/components/MyCategoryItem/MyCategoryItem.style.ts create mode 100644 frontend/src/components/MyCategoryItem/MyCategoryItem.tsx diff --git a/frontend/src/components/MyCategoryItem/MyCategoryItem.style.ts b/frontend/src/components/MyCategoryItem/MyCategoryItem.style.ts new file mode 100644 index 00000000..e50813a0 --- /dev/null +++ b/frontend/src/components/MyCategoryItem/MyCategoryItem.style.ts @@ -0,0 +1,46 @@ +import { css, Theme } from '@emotion/react'; + +const itemStyle = ({ flex }: Theme) => css` + ${flex.row} + + justify-content: space-between; + + width: 100%; +`; + +const nameStyle = css` + overflow: hidden; + position: relative; + + width: 32rem; + + white-space: nowrap; + text-overflow: ellipsis; + + &:hover { + cursor: pointer; + } +`; + +const controlButtonsStyle = ({ flex }: Theme) => css` + ${flex.row} +`; + +const buttonStyle = ({ colors }: Theme) => css` + width: 8rem; + height: 8rem; + + background: transparent; + + color: ${colors.GRAY_700}; + + &:hover { + border-radius: 50%; + + background: ${colors.GRAY_100}; + + filter: none; + } +`; + +export { buttonStyle, controlButtonsStyle, itemStyle, nameStyle }; diff --git a/frontend/src/components/MyCategoryItem/MyCategoryItem.tsx b/frontend/src/components/MyCategoryItem/MyCategoryItem.tsx new file mode 100644 index 00000000..03931d10 --- /dev/null +++ b/frontend/src/components/MyCategoryItem/MyCategoryItem.tsx @@ -0,0 +1,30 @@ +import { CategoryType } from '@/@types/category'; + +import Button from '@/components/@common/Button/Button'; + +import { FiEdit3 } from 'react-icons/fi'; +import { RiDeleteBin6Line } from 'react-icons/ri'; + +import { buttonStyle, controlButtonsStyle, itemStyle, nameStyle } from './MyCategoryItem.style'; + +interface MyCategoryItemProps { + category: CategoryType; +} + +function MyCategoryItem({ category }: MyCategoryItemProps) { + return ( +
    + {category.name} +
    + + +
    +
    + ); +} + +export default MyCategoryItem; diff --git a/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts b/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts index 3e1c0c2c..4bb7bff4 100644 --- a/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts +++ b/frontend/src/components/MyCategoryList/MyCategoryList.styles.ts @@ -49,39 +49,4 @@ const contentStyle = css` width: 100%; `; -const itemStyle = ({ flex }: Theme) => css` - ${flex.row} - - justify-content: space-between; - - width: 100%; - height: 8rem; -`; - -const nameStyle = css` - overflow: hidden; - position: relative; - - width: 32rem; - - white-space: nowrap; - text-overflow: ellipsis; - - &:hover { - cursor: pointer; - } -`; - -const controlButtonsStyle = ({ flex }: Theme) => css` - ${flex.row} -`; - -export { - buttonStyle, - contentStyle, - controlButtonsStyle, - headerStyle, - itemStyle, - listStyle, - nameStyle, -}; +export { buttonStyle, contentStyle, headerStyle, listStyle }; diff --git a/frontend/src/components/MyCategoryList/MyCategoryList.tsx b/frontend/src/components/MyCategoryList/MyCategoryList.tsx index e34f090e..2051e36c 100644 --- a/frontend/src/components/MyCategoryList/MyCategoryList.tsx +++ b/frontend/src/components/MyCategoryList/MyCategoryList.tsx @@ -12,23 +12,15 @@ import { sideBarState, userState } from '@/recoil/atoms'; import Button from '@/components/@common/Button/Button'; import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; import CategoryAddModal from '@/components/CategoryAddModal/CategoryAddModal'; +import MyCategoryItem from '@/components/MyCategoryItem/MyCategoryItem'; import { CACHE_KEY } from '@/constants'; import categoryApi from '@/api/category'; -import { FiEdit3, FiPlus } from 'react-icons/fi'; -import { RiDeleteBin6Line } from 'react-icons/ri'; +import { FiPlus } from 'react-icons/fi'; -import { - buttonStyle, - contentStyle, - controlButtonsStyle, - headerStyle, - itemStyle, - listStyle, - nameStyle, -} from './MyCategoryList.styles'; +import { buttonStyle, contentStyle, headerStyle, listStyle } from './MyCategoryList.styles'; function MyCategoryList() { const theme = useTheme(); @@ -61,17 +53,7 @@ function MyCategoryList() {
    {data.data.map((category) => ( -
    - {category.name} -
    - - -
    -
    + ))}
    From 988f11e793c4ddf34f6ba15c71be0d8bff1794b2 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Fri, 29 Jul 2022 15:19:01 +0900 Subject: [PATCH 0386/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/category.ts | 8 +++++ .../MyCategoryItem/MyCategoryItem.tsx | 29 ++++++++++++++++++- frontend/src/constants/index.ts | 1 + 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/frontend/src/api/category.ts b/frontend/src/api/category.ts index cbde099e..66ecae6b 100644 --- a/frontend/src/api/category.ts +++ b/frontend/src/api/category.ts @@ -37,6 +37,14 @@ const categoryApi = { return response; }, + + delete: async (accessToken: string | null, categoryId: number) => { + const response = await dallogApi.delete(`${categoryApi.endpoint.entire}/${categoryId}`, { + headers: { ...categoryApi.headers, Authorization: `Bearer ${accessToken}` }, + }); + + return response; + }, }; export default categoryApi; diff --git a/frontend/src/components/MyCategoryItem/MyCategoryItem.tsx b/frontend/src/components/MyCategoryItem/MyCategoryItem.tsx index 03931d10..bd4ffc4a 100644 --- a/frontend/src/components/MyCategoryItem/MyCategoryItem.tsx +++ b/frontend/src/components/MyCategoryItem/MyCategoryItem.tsx @@ -1,7 +1,16 @@ +import { useMutation, useQueryClient } from 'react-query'; +import { useRecoilValue } from 'recoil'; + import { CategoryType } from '@/@types/category'; +import { userState } from '@/recoil/atoms'; + import Button from '@/components/@common/Button/Button'; +import { CACHE_KEY, CONFIRM_MESSAGE } from '@/constants'; + +import categoryApi from '@/api/category'; + import { FiEdit3 } from 'react-icons/fi'; import { RiDeleteBin6Line } from 'react-icons/ri'; @@ -12,6 +21,24 @@ interface MyCategoryItemProps { } function MyCategoryItem({ category }: MyCategoryItemProps) { + const { accessToken } = useRecoilValue(userState); + + const queryClient = useQueryClient(); + const { mutate } = useMutation(() => categoryApi.delete(accessToken, category.id), { + onSuccess: () => onSuccessDeleteCategory(), + }); + + const handleClickDeleteButton = () => { + if (confirm(CONFIRM_MESSAGE.DELETE_CATEGORY)) { + mutate(); + } + }; + + const onSuccessDeleteCategory = () => { + queryClient.invalidateQueries(CACHE_KEY.CATEGORIES); + queryClient.invalidateQueries(CACHE_KEY.MY_CATEGORIES); + }; + return (
    {category.name} @@ -19,7 +46,7 @@ function MyCategoryItem({ category }: MyCategoryItemProps) { -
    diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 12d2aab4..7bbbc881 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -21,6 +21,7 @@ const CACHE_KEY = { }; const CONFIRM_MESSAGE = { + DELETE_CATEGORY: '정말 삭제하시겠습니까?', UNSUBSCRIBE: '구독을 해제하시겠습니까?', }; From ae284c972281637e8e7962de071699e2ff0a2856 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Fri, 29 Jul 2022 15:21:30 +0900 Subject: [PATCH 0387/1011] =?UTF-8?q?feat:=20msw=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=82=AD=EC=A0=9C=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=EB=AA=A8=ED=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/mocks/handlers.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index d3af8946..70c3a18c 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -45,6 +45,25 @@ const handlers = [ return res(ctx.status(201)); }), + rest.delete>( + `${API_URL}${categoryApi.endpoint.entire}/:id`, + (req, res, ctx) => { + const { id } = req.params; + const categoryId = parseInt(id as string); + const categoryIndex = categoryDB.categories.findIndex((el) => el.id === categoryId); + const myCategoryIndex = myCategoryDB.categories.findIndex((el) => el.id === categoryId); + + if (categoryIndex < 0 || myCategoryIndex < 0) { + return res(ctx.status(400)); + } + + categoryDB.categories.splice(categoryIndex, 1); + myCategoryDB.categories.splice(myCategoryIndex, 1); + + return res(ctx.status(204)); + } + ), + rest.get(API_URL + categoryApi.endpoint.my, (req, res, ctx) => { return res(ctx.status(200), ctx.json(myCategoryDB)); }), From a54ec8b81eab7cca63d0dff0d82f8a4351854223 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Fri, 29 Jul 2022 15:50:29 +0900 Subject: [PATCH 0388/1011] =?UTF-8?q?fix:=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/mocks/data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/mocks/data.ts b/frontend/src/mocks/data.ts index 84ae50c2..dd4affc2 100644 --- a/frontend/src/mocks/data.ts +++ b/frontend/src/mocks/data.ts @@ -31,7 +31,7 @@ const categoryDB = { }, { id: 3, - name: '공원조', + name: '레벨 1 공원조', createdAt: '2022-07-05T13:00:00', creator: tigerProfileDB, }, From 679d7822cd7cd16ea9d119c30c5e3e3937c07711 Mon Sep 17 00:00:00 2001 From: koo Date: Wed, 27 Jul 2022 20:52:48 +0900 Subject: [PATCH 0389/1011] =?UTF-8?q?test(AuthControllerTest):=20OAuth=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=A7=81=ED=81=AC=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EB=AC=B8=EC=84=9C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dallog/common/fixtures/AuthFixtures.java | 2 + .../auth/presentation/AuthControllerTest.java | 48 +++++++++++++++++++ .../presentation/MemberControllerTest.java | 2 +- 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 backend/src/test/java/com/allog/dallog/domain/auth/presentation/AuthControllerTest.java diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java index 3706b586..265356de 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java @@ -12,4 +12,6 @@ public class AuthFixtures { public static final String 더미_엑세스_토큰 = "aaaaa.bbbbb.ccccc"; public static final String 토큰_정보 = "Bearer " + 더미_엑세스_토큰; + + public static final String OAuth_로그인_링크 = "https://accounts.google.com/o/oauth2/v2/auth"; } diff --git a/backend/src/test/java/com/allog/dallog/domain/auth/presentation/AuthControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/auth/presentation/AuthControllerTest.java new file mode 100644 index 00000000..d03e557a --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/domain/auth/presentation/AuthControllerTest.java @@ -0,0 +1,48 @@ +package com.allog.dallog.domain.auth.presentation; + +import static com.allog.dallog.common.fixtures.AuthFixtures.GOOGLE_PROVIDER; +import static com.allog.dallog.common.fixtures.AuthFixtures.OAuth_로그인_링크; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.allog.dallog.domain.auth.application.AuthService; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; + +@AutoConfigureRestDocs +@WebMvcTest(AuthController.class) +class AuthControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private AuthService authService; + + @DisplayName("OAuth 소셜 로그인을 위한 링크를 반환한다.") + @Test + void OAuth_소셜_로그인을_위한_링크를_반환한다() throws Exception { + // given + given(authService.generateGoogleLink()).willReturn(OAuth_로그인_링크); + + // when & than + mockMvc.perform(get("/api/auth/{oauthProvider}/oauth-uri", GOOGLE_PROVIDER)) + .andDo(print()) + .andDo(document("auth/link", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()) + )) + .andExpect(status().isOk()); + } +} diff --git a/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java index 86e10d1a..9416e0fc 100644 --- a/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/member/presentation/MemberControllerTest.java @@ -70,7 +70,7 @@ class MemberControllerTest { @DisplayName("존재하지 않는 회원의 정보를 조회하려고 하면 예외를 발생한다.") @Test void 존재하지_않는_회원의_정보를_조회하려고_하면_예외를_발생한다() throws Exception { - //given + // given given(memberService.findById(0L)).willThrow(new NoSuchMemberException()); // when & then From 5b596fa1dea9ae671aeb68602aca114c6cdf4ccd Mon Sep 17 00:00:00 2001 From: koo Date: Wed, 27 Jul 2022 22:15:23 +0900 Subject: [PATCH 0390/1011] =?UTF-8?q?test(AuthControllerTest):=20Member?= =?UTF-8?q?=EC=99=80=20Auth=EC=9D=98=20=EB=AC=B8=EC=84=9C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/auth.adoc | 37 +++++++++++ backend/src/docs/asciidoc/index.adoc | 1 + .../dallog/common/fixtures/AuthFixtures.java | 1 + .../auth/presentation/AuthControllerTest.java | 63 +++++++++++++++++-- 4 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 backend/src/docs/asciidoc/auth.adoc diff --git a/backend/src/docs/asciidoc/auth.adoc b/backend/src/docs/asciidoc/auth.adoc new file mode 100644 index 00000000..b67261e2 --- /dev/null +++ b/backend/src/docs/asciidoc/auth.adoc @@ -0,0 +1,37 @@ +== Auth(인증) + +=== OAuth 로그인 링크 생성 + +==== Request + +include::{snippets}/auth/link/http-request.adoc[] + +==== pathParameters + +include::{snippets}/auth/link/path-parameters.adoc[] + +==== Response + +include::{snippets}/auth/link/http-response.adoc[] + +==== ResponseFields + +include::{snippets}/auth/link/response-fields.adoc[] + +=== OAuth 로그인 : Resource Server 에러 + +==== Request + +include::{snippets}/auth/exception/token/http-request.adoc[] + +==== RequestFields + +include::{snippets}/auth/exception/token/path-parameters.adoc[] + +==== RequestFields + +include::{snippets}/auth/exception/token/request-fields.adoc[] + +==== Response + +include::{snippets}/auth/exception/token/http-response.adoc[] diff --git a/backend/src/docs/asciidoc/index.adoc b/backend/src/docs/asciidoc/index.adoc index bac7f791..ae796a60 100644 --- a/backend/src/docs/asciidoc/index.adoc +++ b/backend/src/docs/asciidoc/index.adoc @@ -5,5 +5,6 @@ :toc: left :toclevels: 3 +include::auth.adoc[] include::member.adoc[] include::schedule.adoc[] diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java index 265356de..b2761405 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java @@ -3,6 +3,7 @@ public class AuthFixtures { public static final String GOOGLE_PROVIDER = "google"; + public static final String OAUTH_PROVIDER = "oauthProvider"; public static final String 인증_코드 = "authorization code"; diff --git a/backend/src/test/java/com/allog/dallog/domain/auth/presentation/AuthControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/auth/presentation/AuthControllerTest.java index d03e557a..1a570750 100644 --- a/backend/src/test/java/com/allog/dallog/domain/auth/presentation/AuthControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/auth/presentation/AuthControllerTest.java @@ -1,23 +1,36 @@ package com.allog.dallog.domain.auth.presentation; -import static com.allog.dallog.common.fixtures.AuthFixtures.GOOGLE_PROVIDER; +import static com.allog.dallog.common.fixtures.AuthFixtures.OAUTH_PROVIDER; import static com.allog.dallog.common.fixtures.AuthFixtures.OAuth_로그인_링크; +import static com.allog.dallog.common.fixtures.AuthFixtures.인증_코드; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.allog.dallog.domain.auth.application.AuthService; +import com.allog.dallog.domain.auth.dto.TokenRequest; +import com.allog.dallog.infrastructure.oauth.exception.OAuthException; +import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; import org.springframework.test.web.servlet.MockMvc; @AutoConfigureRestDocs @@ -27,22 +40,60 @@ class AuthControllerTest { @Autowired private MockMvc mockMvc; + @Autowired + private ObjectMapper objectMapper; + @MockBean private AuthService authService; - @DisplayName("OAuth 소셜 로그인을 위한 링크를 반환한다.") + @DisplayName("OAuth 소셜 로그인을 위한 링크와 상태코드 200을 반환한다.") @Test - void OAuth_소셜_로그인을_위한_링크를_반환한다() throws Exception { + void OAuth_소셜_로그인을_위한_링크와_상태코드_200을_반환한다() throws Exception { // given given(authService.generateGoogleLink()).willReturn(OAuth_로그인_링크); // when & than - mockMvc.perform(get("/api/auth/{oauthProvider}/oauth-uri", GOOGLE_PROVIDER)) + mockMvc.perform(get("/api/auth/{oauthProvider}/oauth-uri", OAUTH_PROVIDER)) .andDo(print()) .andDo(document("auth/link", preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint()) + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("oauthProvider").description("OAuth 로그인 제공자") + ), + responseFields( + fieldWithPath("oAuthUri").type(JsonFieldType.STRING).description("OAuth 소셜 로그인 링크") + ) )) .andExpect(status().isOk()); } + + //TODO : OAuth로그인 시 토큰 발급 테스트 만들어야함. + + @DisplayName("OAuth 로그인을 할 떄 Resource Server 에러시 상태코드 500을 반환한다.") + @Test + void OAuth_로그인을_할_때_Resource_Server_에러시_상태코드_500을_반환한다() throws Exception { + // given + given(authService.generateTokenWithCode(인증_코드)).willThrow(new OAuthException()); + + TokenRequest request = new TokenRequest(인증_코드); + + // when & than + mockMvc.perform(post("/api/auth/{oauthProvider}/token", OAUTH_PROVIDER) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andDo(print()) + .andDo(document("auth/exception/token", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("oauthProvider").description("OAuth 로그인 제공자") + ), + requestFields( + fieldWithPath("code").type(JsonFieldType.STRING).description("OAuth 로그인 인증 코드") + ) + )) + .andExpect(status().isInternalServerError()); + } } From 375794f816dd12d7c3acdd6c20e857084fe564f7 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 28 Jul 2022 12:38:47 +0900 Subject: [PATCH 0391/1011] =?UTF-8?q?test(Auth):=20OAuth=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EB=AC=B8=EC=84=9C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/auth.adoc | 20 ++++++++- .../dallog/common/fixtures/AuthFixtures.java | 11 +++++ .../auth/presentation/AuthControllerTest.java | 41 ++++++++++++++----- 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/backend/src/docs/asciidoc/auth.adoc b/backend/src/docs/asciidoc/auth.adoc index b67261e2..2a57efdd 100644 --- a/backend/src/docs/asciidoc/auth.adoc +++ b/backend/src/docs/asciidoc/auth.adoc @@ -18,13 +18,31 @@ include::{snippets}/auth/link/http-response.adoc[] include::{snippets}/auth/link/response-fields.adoc[] +=== OAuth 로그인 + +==== Request + +include::{snippets}/auth/token/http-request.adoc[] + +==== PathParameters + +include::{snippets}/auth/token/path-parameters.adoc[] + +==== RequestFields + +include::{snippets}/auth/token/request-fields.adoc[] + +==== Response + +include::{snippets}/auth/token/http-response.adoc[] + === OAuth 로그인 : Resource Server 에러 ==== Request include::{snippets}/auth/exception/token/http-request.adoc[] -==== RequestFields +==== PathParameters include::{snippets}/auth/exception/token/path-parameters.adoc[] diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java index b2761405..866d9a2b 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/AuthFixtures.java @@ -1,5 +1,8 @@ package com.allog.dallog.common.fixtures; +import com.allog.dallog.domain.auth.dto.TokenRequest; +import com.allog.dallog.domain.auth.dto.TokenResponse; + public class AuthFixtures { public static final String GOOGLE_PROVIDER = "google"; @@ -7,6 +10,14 @@ public class AuthFixtures { public static final String 인증_코드 = "authorization code"; + public static TokenRequest 인증_코드_토큰_요청() { + return new TokenRequest(인증_코드); + } + + public static TokenResponse 인증_코드_토큰_응답() { + return new TokenResponse(인증_코드); + } + public static final String STUB_이메일 = "stub@email.com"; public static final String STUB_이름 = "stub"; public static final String STUB_프로필 = "/image.png"; diff --git a/backend/src/test/java/com/allog/dallog/domain/auth/presentation/AuthControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/auth/presentation/AuthControllerTest.java index 1a570750..05179715 100644 --- a/backend/src/test/java/com/allog/dallog/domain/auth/presentation/AuthControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/auth/presentation/AuthControllerTest.java @@ -3,6 +3,8 @@ import static com.allog.dallog.common.fixtures.AuthFixtures.OAUTH_PROVIDER; import static com.allog.dallog.common.fixtures.AuthFixtures.OAuth_로그인_링크; import static com.allog.dallog.common.fixtures.AuthFixtures.인증_코드; +import static com.allog.dallog.common.fixtures.AuthFixtures.인증_코드_토큰_요청; +import static com.allog.dallog.common.fixtures.AuthFixtures.인증_코드_토큰_응답; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; @@ -15,12 +17,10 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; -import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.allog.dallog.domain.auth.application.AuthService; -import com.allog.dallog.domain.auth.dto.TokenRequest; import com.allog.dallog.infrastructure.oauth.exception.OAuthException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.DisplayName; @@ -52,7 +52,7 @@ class AuthControllerTest { // given given(authService.generateGoogleLink()).willReturn(OAuth_로그인_링크); - // when & than + // when & then mockMvc.perform(get("/api/auth/{oauthProvider}/oauth-uri", OAUTH_PROVIDER)) .andDo(print()) .andDo(document("auth/link", @@ -68,21 +68,42 @@ class AuthControllerTest { .andExpect(status().isOk()); } - //TODO : OAuth로그인 시 토큰 발급 테스트 만들어야함. + @DisplayName("OAuth 로그인을 하면 token과 상태코드 200을 반환한다.") + @Test + void OAuth_로그인을_하면_token과_상태코드_200을_반환한다() throws Exception { + // given + given(authService.generateTokenWithCode(인증_코드)).willReturn(인증_코드_토큰_응답()); - @DisplayName("OAuth 로그인을 할 떄 Resource Server 에러시 상태코드 500을 반환한다.") + // when & then + mockMvc.perform(post("/api/auth/{oauthProvider}/token", OAUTH_PROVIDER) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(인증_코드_토큰_요청()))) + .andDo(print()) + .andDo(document("auth/token", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("oauthProvider").description("OAuth 로그인 제공자") + ), + requestFields( + fieldWithPath("code").type(JsonFieldType.STRING).description("OAuth 로그인 인증 코드") + ) + )) + .andExpect(status().isOk()); + } + + @DisplayName("OAuth 로그인 과정에서 Resource Server 에러가 발생하면 상태코드 500을 반환한다.") @Test - void OAuth_로그인을_할_때_Resource_Server_에러시_상태코드_500을_반환한다() throws Exception { + void OAuth_로그인_과정에서_Resource_Server_에러가_발생하면_상태코드_500을_반환한다() throws Exception { // given given(authService.generateTokenWithCode(인증_코드)).willThrow(new OAuthException()); - TokenRequest request = new TokenRequest(인증_코드); - - // when & than + // when & then mockMvc.perform(post("/api/auth/{oauthProvider}/token", OAUTH_PROVIDER) .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(request))) + .content(objectMapper.writeValueAsString(인증_코드_토큰_요청()))) .andDo(print()) .andDo(document("auth/exception/token", preprocessRequest(prettyPrint()), From 59bc016834699cbcaa2f49feb69346303a2b1bf5 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Thu, 28 Jul 2022 15:25:19 +0900 Subject: [PATCH 0392/1011] =?UTF-8?q?test:=20Rest=20Docs=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=9D=91=EB=8B=B5=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?fixtures=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/fixtures/CategoryFixtures.java | 23 +++++++++++++++++++ .../common/fixtures/MemberFixtures.java | 6 ++++- .../common/fixtures/SubscriptionFixtures.java | 14 +++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java index 5322132c..3e27f5aa 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/CategoryFixtures.java @@ -2,7 +2,10 @@ import com.allog.dallog.domain.category.domain.Category; import com.allog.dallog.domain.category.dto.request.CategoryCreateRequest; +import com.allog.dallog.domain.category.dto.response.CategoryResponse; import com.allog.dallog.domain.member.domain.Member; +import com.allog.dallog.domain.member.dto.MemberResponse; +import java.time.LocalDateTime; public class CategoryFixtures { @@ -45,4 +48,24 @@ public class CategoryFixtures { public static Category 후디_JPA_스터디(final Member creator) { return new Category(후디_JPA_스터디_이름, creator); } + + public static CategoryResponse 공통_일정_응답(final MemberResponse creatorResponse) { + return new CategoryResponse(1L, 공통_일정_이름, creatorResponse, LocalDateTime.now()); + } + + public static CategoryResponse BE_일정_응답(final MemberResponse creatorResponse) { + return new CategoryResponse(2L, BE_일정_이름, creatorResponse, LocalDateTime.now()); + } + + public static CategoryResponse FE_일정_응답(final MemberResponse creatorResponse) { + return new CategoryResponse(3L, FE_일정_이름, creatorResponse, LocalDateTime.now()); + } + + public static CategoryResponse 매트_아고라_응답(final MemberResponse creatorResponse) { + return new CategoryResponse(4L, 매트_아고라_이름, creatorResponse, LocalDateTime.now()); + } + + public static CategoryResponse 후디_JPA_스터디_응답(final MemberResponse creatorResponse) { + return new CategoryResponse(5L, 후디_JPA_스터디_이름, creatorResponse, LocalDateTime.now()); + } } diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java index dcb775ff..359b8f99 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/MemberFixtures.java @@ -11,27 +11,31 @@ public class MemberFixtures { public static final String 관리자_이메일 = "dallog.admin@gmail.com"; public static final String 관리자_이름 = "관리자"; public static final String 관리자_프로필 = "/admin.png"; + public static final MemberResponse 관리자_응답 = new MemberResponse(1L, 관리자_이메일, 관리자_이름, 관리자_프로필, GOOGLE); /* 파랑 */ public static final String 파랑_이메일 = "parang@email.com"; public static final String 파랑_이름 = "파랑"; public static final String 파랑_프로필 = "/parang.png"; - public static final MemberResponse 파랑_응답 = new MemberResponse(1L, 파랑_이메일, 파랑_이름, 파랑_프로필, GOOGLE); + public static final MemberResponse 파랑_응답 = new MemberResponse(2L, 파랑_이메일, 파랑_이름, 파랑_프로필, GOOGLE); /* 리버 */ public static final String 리버_이메일 = "leaver@email.com"; public static final String 리버_이름 = "리버"; public static final String 리버_프로필 = "/leaver.png"; + public static final MemberResponse 리버_응답 = new MemberResponse(3L, 리버_이메일, 리버_이름, 리버_프로필, GOOGLE); /* 후디 */ public static final String 후디_이메일 = "devhudi@gmail.com"; public static final String 후디_이름 = "후디"; public static final String 후디_프로필 = "/hudi.png"; + public static final MemberResponse 후디_응답 = new MemberResponse(4L, 후디_이메일, 후디_이름, 후디_프로필, GOOGLE); /* 매트 */ public static final String 매트_이메일 = "dev.hyeonic@gmail.com"; public static final String 매트_이름 = "매트"; public static final String 매트_프로필 = "/mat.png"; + public static final MemberResponse 매트_응답 = new MemberResponse(5L, 매트_이메일, 매트_이름, 매트_프로필, GOOGLE); public static Member 관리자() { return new Member(관리자_이메일, 관리자_이름, 관리자_프로필, GOOGLE); diff --git a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java index 48430180..284ceb76 100644 --- a/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java +++ b/backend/src/test/java/com/allog/dallog/common/fixtures/SubscriptionFixtures.java @@ -1,9 +1,11 @@ package com.allog.dallog.common.fixtures; import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.category.dto.response.CategoryResponse; import com.allog.dallog.domain.member.domain.Member; import com.allog.dallog.domain.subscription.domain.Subscription; import com.allog.dallog.domain.subscription.dto.request.SubscriptionCreateRequest; +import com.allog.dallog.domain.subscription.dto.response.SubscriptionResponse; public class SubscriptionFixtures { @@ -23,11 +25,23 @@ public class SubscriptionFixtures { return new Subscription(member, category, 빨간색); } + public static SubscriptionResponse 빨간색_구독_응답(final CategoryResponse categoryResponse) { + return new SubscriptionResponse(1L, categoryResponse, 빨간색); + } + public static Subscription 파란색_구독(final Member member, final Category category) { return new Subscription(member, category, 파란색); } + public static SubscriptionResponse 파란색_구독_응답(final CategoryResponse categoryResponse) { + return new SubscriptionResponse(2L, categoryResponse, 파란색); + } + public static Subscription 노란색_구독(final Member member, final Category category) { return new Subscription(member, category, 노란색); } + + public static SubscriptionResponse 노란색_구독_응답(final CategoryResponse categoryResponse) { + return new SubscriptionResponse(3L, categoryResponse, 노란색); + } } From 65f2169eec0c3ea0b399e994bc4a5bfa57790adb Mon Sep 17 00:00:00 2001 From: hyeonic Date: Thu, 28 Jul 2022 17:09:00 +0900 Subject: [PATCH 0393/1011] =?UTF-8?q?test:=20Subscription=20=EC=A0=95?= =?UTF-8?q?=EC=83=81=20=EC=9A=94=EC=B2=AD=20=EA=B4=80=EB=A0=A8=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/index.adoc | 1 + backend/src/docs/asciidoc/subscription.adoc | 55 ++++++ .../SubscriptionControllerTest.java | 157 ++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 backend/src/docs/asciidoc/subscription.adoc create mode 100644 backend/src/test/java/com/allog/dallog/domain/subscription/presentation/SubscriptionControllerTest.java diff --git a/backend/src/docs/asciidoc/index.adoc b/backend/src/docs/asciidoc/index.adoc index ae796a60..0e441bb0 100644 --- a/backend/src/docs/asciidoc/index.adoc +++ b/backend/src/docs/asciidoc/index.adoc @@ -8,3 +8,4 @@ include::auth.adoc[] include::member.adoc[] include::schedule.adoc[] +include::subscription.adoc[] diff --git a/backend/src/docs/asciidoc/subscription.adoc b/backend/src/docs/asciidoc/subscription.adoc new file mode 100644 index 00000000..db63f28a --- /dev/null +++ b/backend/src/docs/asciidoc/subscription.adoc @@ -0,0 +1,55 @@ +== Subscription(구독) + +=== 구독 등록 + +==== Request + +include::{snippets}/subscription/save/http-request.adoc[] + +==== Path Parameters + +include::{snippets}/subscription/save/path-parameters.adoc[] + +==== Request Headers + +include::{snippets}/subscription/save/request-headers.adoc[] + +==== Request Parameters + +include::{snippets}/subscription/save/request-body.adoc[] + +==== Response + +include::{snippets}/subscription/save/http-response.adoc[] + +=== 내 구독 정보 조회 + +==== Request + +include::{snippets}/subscription/me/http-request.adoc[] + +==== Request Headers + +include::{snippets}/subscription/me/request-headers.adoc[] + +==== Response + +include::{snippets}/subscription/me/http-response.adoc[] + +=== 내 구독 정보 삭제 + +==== Request + +include::{snippets}/subscription/delete/http-request.adoc[] + +==== Path Parameters + +include::{snippets}/subscription/delete/path-parameters.adoc[] + +==== Request Headers + +include::{snippets}/subscription/delete/request-headers.adoc[] + +==== Response + +include::{snippets}/subscription/delete/http-response.adoc[] diff --git a/backend/src/test/java/com/allog/dallog/domain/subscription/presentation/SubscriptionControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/subscription/presentation/SubscriptionControllerTest.java new file mode 100644 index 00000000..3b2d8ca4 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/domain/subscription/presentation/SubscriptionControllerTest.java @@ -0,0 +1,157 @@ +package com.allog.dallog.domain.subscription.presentation; + +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_응답; +import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정_응답; +import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정_응답; +import static com.allog.dallog.common.fixtures.MemberFixtures.관리자_응답; +import static com.allog.dallog.common.fixtures.MemberFixtures.매트_응답; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.노란색_구독_응답; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.빨간색_구독_생성_요청; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.빨간색_구독_응답; +import static com.allog.dallog.common.fixtures.SubscriptionFixtures.파란색_구독_응답; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willDoNothing; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.allog.dallog.domain.auth.application.AuthService; +import com.allog.dallog.domain.category.dto.response.CategoryResponse; +import com.allog.dallog.domain.subscription.application.SubscriptionService; +import com.allog.dallog.domain.subscription.dto.response.SubscriptionResponse; +import com.allog.dallog.domain.subscription.dto.response.SubscriptionsResponse; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.payload.JsonFieldType; +import org.springframework.test.web.servlet.MockMvc; + +@AutoConfigureRestDocs +@WebMvcTest(SubscriptionController.class) +class SubscriptionControllerTest { + + private static final String AUTHORIZATION_HEADER_NAME = "Authorization"; + private static final String AUTHORIZATION_HEADER_VALUE = "Bearer aaaaa.bbbbb.ccccc"; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private AuthService authService; + + @MockBean + private SubscriptionService subscriptionService; + + @DisplayName("회원과 카테고리 정보를 기반으로 구독한다.") + @Test + void 회원과_카테고리_정보를_기반으로_구독한다() throws Exception { + // given + CategoryResponse 공통_일정_응답 = 공통_일정_응답(관리자_응답); + SubscriptionResponse 빨간색_구독_응답 = 빨간색_구독_응답(공통_일정_응답); + + given(authService.extractMemberId(any())).willReturn(매트_응답.getId()); + given(subscriptionService.save(any(), any(), any())).willReturn(빨간색_구독_응답); + + // when & then + mockMvc.perform(post("/api/members/me/categories/{categoryId}/subscriptions", 1L) + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) + .accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(빨간색_구독_생성_요청))) + .andDo(print()) + .andDo(document("subscription/save", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("categoryId").description("카테고리 id") + ), + requestHeaders( + headerWithName("Authorization").description("JWT 토큰") + ), + requestFields( + fieldWithPath("color").type(JsonFieldType.STRING).description("구독 색 장보") + ))) + .andExpect(status().isCreated()); + } + + @DisplayName("자신의 구독 정보를 조회한다.") + @Test + void 자신의_구독_정보를_조회한다() throws Exception { + // given + CategoryResponse 공통_일정_응답 = 공통_일정_응답(관리자_응답); + CategoryResponse BE_일정_응답 = BE_일정_응답(관리자_응답); + CategoryResponse FE_일정_응답 = FE_일정_응답(관리자_응답); + + SubscriptionResponse 빨간색_구독_응답 = 빨간색_구독_응답(공통_일정_응답); + SubscriptionResponse 파란색_구독_응답 = 파란색_구독_응답(BE_일정_응답); + SubscriptionResponse 노란색_구독_응답 = 노란색_구독_응답(FE_일정_응답); + + given(authService.extractMemberId(any())).willReturn(매트_응답.getId()); + + List subscriptionResponses = List.of(빨간색_구독_응답, 파란색_구독_응답, 노란색_구독_응답); + given(subscriptionService.findByMemberId(any())).willReturn(new SubscriptionsResponse(subscriptionResponses)); + + // when & then + mockMvc.perform(get("/api/members/me/subscriptions") + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andDo(document("subscription/me", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestHeaders( + headerWithName("Authorization").description("JWT 토큰") + ))) + .andExpect(status().isOk()); + } + + @DisplayName("구독 id를 기반으로 자신의 구독 정보를 삭제한다.") + @Test + void 구독_id를_기반으로_자신의_구독_정보를_삭제한다() throws Exception { + // given + CategoryResponse 공통_일정_응답 = 공통_일정_응답(관리자_응답); + SubscriptionResponse 빨간색_구독_응답 = 빨간색_구독_응답(공통_일정_응답); + + given(authService.extractMemberId(any())).willReturn(매트_응답.getId()); + willDoNothing().given(subscriptionService).deleteByIdAndMemberId(빨간색_구독_응답.getId(), 매트_응답.getId()); + + // when & then + mockMvc.perform(delete("/api/members/me/subscriptions/{subscriptionId}", 빨간색_구독_응답.getId()) + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andDo(document("subscription/delete", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("subscriptionId").description("구독 id") + ), + requestHeaders( + headerWithName("Authorization").description("JWT 토큰") + ))) + .andExpect(status().isNoContent()); + } +} From 061255fe681bfef18e8f25ad40a24cbac7dc0de9 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Thu, 28 Jul 2022 19:29:03 +0900 Subject: [PATCH 0394/1011] =?UTF-8?q?test:=20SubscriptionController=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EA=B4=80=EB=A0=A8=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/subscription.adoc | 40 ++++++++++++ .../presentation/SubscriptionController.java | 3 +- .../global/presentation/ControllerAdvice.java | 6 +- .../SubscriptionControllerTest.java | 64 ++++++++++++++++++- 4 files changed, 107 insertions(+), 6 deletions(-) diff --git a/backend/src/docs/asciidoc/subscription.adoc b/backend/src/docs/asciidoc/subscription.adoc index db63f28a..0d406532 100644 --- a/backend/src/docs/asciidoc/subscription.adoc +++ b/backend/src/docs/asciidoc/subscription.adoc @@ -22,6 +22,28 @@ include::{snippets}/subscription/save/request-body.adoc[] include::{snippets}/subscription/save/http-response.adoc[] +=== 중복된 구독 등록 + +==== Request + +include::{snippets}/subscription/exist/http-request.adoc[] + +==== Path Parameters + +include::{snippets}/subscription/exist/path-parameters.adoc[] + +==== Request Headers + +include::{snippets}/subscription/exist/request-headers.adoc[] + +==== Request Parameters + +include::{snippets}/subscription/exist/request-body.adoc[] + +==== Response + +include::{snippets}/subscription/exist/http-response.adoc[] + === 내 구독 정보 조회 ==== Request @@ -53,3 +75,21 @@ include::{snippets}/subscription/delete/request-headers.adoc[] ==== Response include::{snippets}/subscription/delete/http-response.adoc[] + +=== 내 구독 정보가 아닌 구독 삭제 + +==== Request + +include::{snippets}/subscription/permission/http-request.adoc[] + +==== Path Parameters + +include::{snippets}/subscription/permission/path-parameters.adoc[] + +==== Request Headers + +include::{snippets}/subscription/permission/request-headers.adoc[] + +==== Response + +include::{snippets}/subscription/permission/http-response.adoc[] diff --git a/backend/src/main/java/com/allog/dallog/domain/subscription/presentation/SubscriptionController.java b/backend/src/main/java/com/allog/dallog/domain/subscription/presentation/SubscriptionController.java index 5cce2216..117bd0c3 100644 --- a/backend/src/main/java/com/allog/dallog/domain/subscription/presentation/SubscriptionController.java +++ b/backend/src/main/java/com/allog/dallog/domain/subscription/presentation/SubscriptionController.java @@ -32,7 +32,8 @@ public ResponseEntity save(@AuthenticationPrincipal final @RequestBody final SubscriptionCreateRequest request) { SubscriptionResponse response = subscriptionService.save(loginMember.getId(), categoryId, request); return ResponseEntity.created( - URI.create("/api/members/me/" + categoryId + "/subscriptions/" + response.getId())).body(response); + URI.create("/api/members/me/categories/" + categoryId + "/subscriptions/" + response.getId())) + .body(response); } @GetMapping("/subscriptions") diff --git a/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java b/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java index 7dfd179f..5d8953ef 100644 --- a/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java +++ b/backend/src/main/java/com/allog/dallog/global/presentation/ControllerAdvice.java @@ -39,9 +39,9 @@ public ResponseEntity handleInvalidData(final RuntimeException e) InvalidTokenException.class, NoPermissionException.class }) - public ResponseEntity handleInvalidAuthorization() { - ErrorResponse errorResponse = new ErrorResponse("사용자 인증에 실패하였습니다."); - return ResponseEntity.internalServerError().body(errorResponse); + public ResponseEntity handleInvalidAuthorization(final RuntimeException e) { + ErrorResponse errorResponse = new ErrorResponse(e.getMessage()); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorResponse); } @ExceptionHandler({ diff --git a/backend/src/test/java/com/allog/dallog/domain/subscription/presentation/SubscriptionControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/subscription/presentation/SubscriptionControllerTest.java index 3b2d8ca4..3bade3e8 100644 --- a/backend/src/test/java/com/allog/dallog/domain/subscription/presentation/SubscriptionControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/subscription/presentation/SubscriptionControllerTest.java @@ -12,6 +12,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.willDoNothing; +import static org.mockito.BDDMockito.willThrow; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; @@ -29,10 +30,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.allog.dallog.domain.auth.application.AuthService; +import com.allog.dallog.domain.auth.exception.NoPermissionException; import com.allog.dallog.domain.category.dto.response.CategoryResponse; import com.allog.dallog.domain.subscription.application.SubscriptionService; import com.allog.dallog.domain.subscription.dto.response.SubscriptionResponse; import com.allog.dallog.domain.subscription.dto.response.SubscriptionsResponse; +import com.allog.dallog.domain.subscription.exception.ExistSubscriptionException; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; import org.junit.jupiter.api.DisplayName; @@ -75,7 +78,7 @@ class SubscriptionControllerTest { given(subscriptionService.save(any(), any(), any())).willReturn(빨간색_구독_응답); // when & then - mockMvc.perform(post("/api/members/me/categories/{categoryId}/subscriptions", 1L) + mockMvc.perform(post("/api/members/me/categories/{categoryId}/subscriptions", 빨간색_구독_응답.getId()) .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) .accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(빨간색_구독_생성_요청))) @@ -95,6 +98,34 @@ class SubscriptionControllerTest { .andExpect(status().isCreated()); } + @DisplayName("회원이 이미 카테고리를 구독한 경우 예외를 던진다.") + @Test + void 회원이_이미_카테고리를_구독한_경우_예외를_던진다() throws Exception { + // given + given(authService.extractMemberId(any())).willReturn(매트_응답.getId()); + given(subscriptionService.save(any(), any(), any())).willThrow(new ExistSubscriptionException()); + + // when & then + mockMvc.perform(post("/api/members/me/categories/{categoryId}/subscriptions", 1L) + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) + .accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(빨간색_구독_생성_요청))) + .andDo(print()) + .andDo(document("subscription/exist", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("categoryId").description("카테고리 id") + ), + requestHeaders( + headerWithName("Authorization").description("JWT 토큰") + ), + requestFields( + fieldWithPath("color").type(JsonFieldType.STRING).description("구독 색 장보") + ))) + .andExpect(status().isBadRequest()); + } + @DisplayName("자신의 구독 정보를 조회한다.") @Test void 자신의_구독_정보를_조회한다() throws Exception { @@ -135,7 +166,8 @@ class SubscriptionControllerTest { SubscriptionResponse 빨간색_구독_응답 = 빨간색_구독_응답(공통_일정_응답); given(authService.extractMemberId(any())).willReturn(매트_응답.getId()); - willDoNothing().given(subscriptionService).deleteByIdAndMemberId(빨간색_구독_응답.getId(), 매트_응답.getId()); + willDoNothing().given(subscriptionService) + .deleteByIdAndMemberId(빨간색_구독_응답.getId(), 매트_응답.getId()); // when & then mockMvc.perform(delete("/api/members/me/subscriptions/{subscriptionId}", 빨간색_구독_응답.getId()) @@ -154,4 +186,32 @@ class SubscriptionControllerTest { ))) .andExpect(status().isNoContent()); } + + @DisplayName("자신이 가지고 있지 않은 구독 정보인 경우 예외를 던진다.") + @Test + void 자신이_가지고_있지_않은_구독_정보인_경우_예외를_던진다() throws Exception { + // given + given(authService.extractMemberId(any())).willReturn(매트_응답.getId()); + willThrow(new NoPermissionException()) + .willDoNothing() + .given(subscriptionService) + .deleteByIdAndMemberId(any(), any()); + + // when & then + mockMvc.perform(delete("/api/members/me/subscriptions/{subscriptionId}", 1L) + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andDo(document("subscription/permission", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("subscriptionId").description("구독 id") + ), + requestHeaders( + headerWithName("Authorization").description("JWT 토큰") + ))) + .andExpect(status().isUnauthorized()); + } } From e6ef514cb69959440482fc980965926e449818d2 Mon Sep 17 00:00:00 2001 From: hyeonic Date: Fri, 29 Jul 2022 10:03:38 +0900 Subject: [PATCH 0395/1011] =?UTF-8?q?chore:=20=EB=AC=B8=EC=84=9C=ED=99=94?= =?UTF-8?q?=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EC=98=A4=ED=83=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subscription/presentation/SubscriptionControllerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/domain/subscription/presentation/SubscriptionControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/subscription/presentation/SubscriptionControllerTest.java index 3bade3e8..082eff73 100644 --- a/backend/src/test/java/com/allog/dallog/domain/subscription/presentation/SubscriptionControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/subscription/presentation/SubscriptionControllerTest.java @@ -93,7 +93,7 @@ class SubscriptionControllerTest { headerWithName("Authorization").description("JWT 토큰") ), requestFields( - fieldWithPath("color").type(JsonFieldType.STRING).description("구독 색 장보") + fieldWithPath("color").type(JsonFieldType.STRING).description("구독 색 정보") ))) .andExpect(status().isCreated()); } @@ -121,7 +121,7 @@ class SubscriptionControllerTest { headerWithName("Authorization").description("JWT 토큰") ), requestFields( - fieldWithPath("color").type(JsonFieldType.STRING).description("구독 색 장보") + fieldWithPath("color").type(JsonFieldType.STRING).description("구독 색 정보") ))) .andExpect(status().isBadRequest()); } From d2c565d9fbe34dc384c7c327a12cb29ad2e0419a Mon Sep 17 00:00:00 2001 From: hyeonic Date: Thu, 28 Jul 2022 17:09:00 +0900 Subject: [PATCH 0396/1011] =?UTF-8?q?test:=20Subscription=20=EC=A0=95?= =?UTF-8?q?=EC=83=81=20=EC=9A=94=EC=B2=AD=20=EA=B4=80=EB=A0=A8=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EB=AC=B8?= =?UTF-8?q?=EC=84=9C=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/subscription.adoc | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/src/docs/asciidoc/subscription.adoc b/backend/src/docs/asciidoc/subscription.adoc index 0d406532..4b7038dd 100644 --- a/backend/src/docs/asciidoc/subscription.adoc +++ b/backend/src/docs/asciidoc/subscription.adoc @@ -44,8 +44,6 @@ include::{snippets}/subscription/exist/request-body.adoc[] include::{snippets}/subscription/exist/http-response.adoc[] -=== 내 구독 정보 조회 - ==== Request include::{snippets}/subscription/me/http-request.adoc[] From 2ac57c900dccad046a149f3fbfaf74dc5235d2ca Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 28 Jul 2022 15:30:57 +0900 Subject: [PATCH 0397/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=83=9D=EC=84=B1=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/category.adoc | 11 +++ .../presentation/CategoryControllerTest.java | 75 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 backend/src/docs/asciidoc/category.adoc create mode 100644 backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java diff --git a/backend/src/docs/asciidoc/category.adoc b/backend/src/docs/asciidoc/category.adoc new file mode 100644 index 00000000..4e3f639e --- /dev/null +++ b/backend/src/docs/asciidoc/category.adoc @@ -0,0 +1,11 @@ +== Category(카테고리) + +=== 카테고리 생성 + +==== Request + +include::{snippets}/categories/http-request.adoc[] + +==== Response + +include::{snippets}/categories/http-response.adoc[] diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java new file mode 100644 index 00000000..ee0b2ef1 --- /dev/null +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -0,0 +1,75 @@ +package com.allog.dallog.domain.category.presentation; + +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_이름; +import static com.allog.dallog.common.fixtures.MemberFixtures.후디; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; +import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.allog.dallog.domain.auth.application.AuthService; +import com.allog.dallog.domain.category.application.CategoryService; +import com.allog.dallog.domain.category.dto.response.CategoryResponse; +import com.allog.dallog.domain.member.dto.MemberResponse; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.time.LocalDateTime; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +@AutoConfigureRestDocs +@WebMvcTest(CategoryController.class) +class CategoryControllerTest { + + private static final String DUMMY_BEARER_JWT = "Bearer aaaaaaaa.bbbbbbbb.cccccccc"; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private AuthService authService; + + @MockBean + private CategoryService categoryService; + + @DisplayName("카테고리를 생성한다.") + @Test + void 카테고리를_생성한다() throws Exception { + // given + MemberResponse 후디 = new MemberResponse(후디()); + CategoryResponse 카테고리 = new CategoryResponse(1L, BE_일정_이름, 후디, LocalDateTime.now()); + given(categoryService.save(any(), any())).willReturn(카테고리); + + // when & then + mockMvc.perform(post("/api/categories") + .header("Authorization", DUMMY_BEARER_JWT) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(BE_일정_생성_요청)) + ).andDo(print()) + .andDo(document("categories", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestHeaders( + headerWithName("Authorization").description("JWT 토큰")) + ) + ) + .andExpect(status().isCreated()); + } +} From bde8a4cb70da4cd91f545f7537dc6f142b71958a Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 28 Jul 2022 16:54:47 +0900 Subject: [PATCH 0398/1011] =?UTF-8?q?test:=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 카테고리 생성에 대한 테스트의 RestDocs identifier 변경 --- backend/src/docs/asciidoc/category.adoc | 14 ++++++-- .../presentation/CategoryControllerTest.java | 34 ++++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/backend/src/docs/asciidoc/category.adoc b/backend/src/docs/asciidoc/category.adoc index 4e3f639e..53e00162 100644 --- a/backend/src/docs/asciidoc/category.adoc +++ b/backend/src/docs/asciidoc/category.adoc @@ -4,8 +4,18 @@ ==== Request -include::{snippets}/categories/http-request.adoc[] +include::{snippets}/categories/save/http-request.adoc[] ==== Response -include::{snippets}/categories/http-response.adoc[] +include::{snippets}/categories/save/http-response.adoc[] + +=== 전체 카테고리 조회 + +==== Request + +include::{snippets}/categories/findAll/http-request.adoc[] + +==== Response + +include::{snippets}/categories/findAll/http-response.adoc[] diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index ee0b2ef1..3e9ed3f7 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -1,7 +1,14 @@ package com.allog.dallog.domain.category.presentation; +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정; import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_생성_요청; import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_이름; +import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정; +import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정; +import static com.allog.dallog.common.fixtures.CategoryFixtures.매트_아고라; +import static com.allog.dallog.common.fixtures.CategoryFixtures.후디_JPA_스터디; +import static com.allog.dallog.common.fixtures.MemberFixtures.관리자; +import static com.allog.dallog.common.fixtures.MemberFixtures.매트; import static com.allog.dallog.common.fixtures.MemberFixtures.후디; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; @@ -11,16 +18,20 @@ import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import com.allog.dallog.domain.auth.application.AuthService; import com.allog.dallog.domain.category.application.CategoryService; +import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.category.dto.response.CategoriesResponse; import com.allog.dallog.domain.category.dto.response.CategoryResponse; import com.allog.dallog.domain.member.dto.MemberResponse; import com.fasterxml.jackson.databind.ObjectMapper; import java.time.LocalDateTime; +import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -63,7 +74,7 @@ class CategoryControllerTest { .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(BE_일정_생성_요청)) ).andDo(print()) - .andDo(document("categories", + .andDo(document("categories/save", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), requestHeaders( @@ -72,4 +83,25 @@ class CategoryControllerTest { ) .andExpect(status().isCreated()); } + + @DisplayName("생성된 카테고리를 전부 조회한다.") + @Test + void 생성된_카테고리를_전부_조회한다() throws Exception { + // given + List 일정_목록 = List.of(공통_일정(관리자()), BE_일정(관리자()), FE_일정(관리자()), 후디_JPA_스터디(후디()), 매트_아고라(매트())); + CategoriesResponse categoriesResponse = new CategoriesResponse(0, 일정_목록); + given(categoryService.findAll(any())).willReturn(categoriesResponse); + + // when & then + mockMvc.perform(get("/api/categories") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ) + .andDo(print()) + .andDo(document("categories/findAll", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint())) + ) + .andExpect(status().isOk()); + } } From 0208e869700ddb57a77702877b8ecd3268550b0d Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 28 Jul 2022 17:09:19 +0900 Subject: [PATCH 0399/1011] =?UTF-8?q?test:=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=AC=B8=EC=84=9C=EC=97=90=20?= =?UTF-8?q?=EC=BF=BC=EB=A6=AC=20=EC=8A=A4=ED=8A=B8=EB=A7=81=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EB=82=B4=EC=9A=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/category.adoc | 4 ++++ .../presentation/CategoryControllerTest.java | 18 ++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/backend/src/docs/asciidoc/category.adoc b/backend/src/docs/asciidoc/category.adoc index 53e00162..519cfeb7 100644 --- a/backend/src/docs/asciidoc/category.adoc +++ b/backend/src/docs/asciidoc/category.adoc @@ -16,6 +16,10 @@ include::{snippets}/categories/save/http-response.adoc[] include::{snippets}/categories/findAll/http-request.adoc[] +==== RequestParameters + +include::{snippets}/categories/findAll/request-parameters.adoc[] + ==== Response include::{snippets}/categories/findAll/http-response.adoc[] diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index 3e9ed3f7..c86cc0ba 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -18,6 +18,8 @@ import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest; import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; @@ -88,19 +90,27 @@ class CategoryControllerTest { @Test void 생성된_카테고리를_전부_조회한다() throws Exception { // given + int page = 0; + int size = 10; + List 일정_목록 = List.of(공통_일정(관리자()), BE_일정(관리자()), FE_일정(관리자()), 후디_JPA_스터디(후디()), 매트_아고라(매트())); - CategoriesResponse categoriesResponse = new CategoriesResponse(0, 일정_목록); + CategoriesResponse categoriesResponse = new CategoriesResponse(page, 일정_목록); given(categoryService.findAll(any())).willReturn(categoriesResponse); // when & then - mockMvc.perform(get("/api/categories") + mockMvc.perform(get("/api/categories?page={page}&size={size}", page, size) .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) ) .andDo(print()) .andDo(document("categories/findAll", - preprocessRequest(prettyPrint()), - preprocessResponse(prettyPrint())) + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestParameters( + parameterWithName("page").description("페이지 번호"), + parameterWithName("size").description("페이지 크기") + ) + ) ) .andExpect(status().isOk()); } From ec7e66140134625302161d623fdb9e6ea736917f Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 28 Jul 2022 21:50:37 +0900 Subject: [PATCH 0400/1011] =?UTF-8?q?test:=20=EC=9E=90=EC=8B=A0=EC=9D=B4?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=ED=95=9C=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/category.adoc | 14 +++++++++ .../presentation/CategoryControllerTest.java | 29 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/backend/src/docs/asciidoc/category.adoc b/backend/src/docs/asciidoc/category.adoc index 519cfeb7..daeb61ae 100644 --- a/backend/src/docs/asciidoc/category.adoc +++ b/backend/src/docs/asciidoc/category.adoc @@ -23,3 +23,17 @@ include::{snippets}/categories/findAll/request-parameters.adoc[] ==== Response include::{snippets}/categories/findAll/http-response.adoc[] + +=== 자신이 생성한 카테고리 조회 + +==== Request + +include::{snippets}/categories/findMine/http-request.adoc[] + +==== RequestParameters + +include::{snippets}/categories/findMine/request-parameters.adoc[] + +==== Response + +include::{snippets}/categories/findMine/response-body.adoc[] diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index c86cc0ba..a616430b 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -114,4 +114,33 @@ class CategoryControllerTest { ) .andExpect(status().isOk()); } + + @DisplayName("멤버 자신이 생성한 카테고리를 전부 조회한다.") + @Test + void 멤버_자신이_생성한_카테고리를_전부_조회한다() throws Exception { + // given + int page = 0; + int size = 10; + + List 일정_목록 = List.of(공통_일정(관리자()), BE_일정(관리자()), FE_일정(관리자())); + CategoriesResponse categoriesResponse = new CategoriesResponse(page, 일정_목록); + given(categoryService.findMine(any(), any())).willReturn(categoriesResponse); + + // when & then + mockMvc.perform(get("/api/categories/me?page={page}&size={size}", page, size) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", DUMMY_BEARER_JWT) + ).andDo(print()) + .andDo(document("categories/findMine", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestParameters( + parameterWithName("page").description("페이지 번호"), + parameterWithName("size").description("페이지 크기") + ) + ) + ) + .andExpect(status().isOk()); + } } From ef9c52a46a3222136dc9a8205778af50bb7091d7 Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 28 Jul 2022 22:12:24 +0900 Subject: [PATCH 0401/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20ID=EB=A1=9C=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC?= =?UTF-8?q?=EB=A5=BC=20=EB=8B=A8=EA=B1=B4=20=EC=A1=B0=ED=9A=8C=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/category.adoc | 14 ++++++++ .../presentation/CategoryControllerTest.java | 34 +++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/backend/src/docs/asciidoc/category.adoc b/backend/src/docs/asciidoc/category.adoc index daeb61ae..f5800d20 100644 --- a/backend/src/docs/asciidoc/category.adoc +++ b/backend/src/docs/asciidoc/category.adoc @@ -37,3 +37,17 @@ include::{snippets}/categories/findMine/request-parameters.adoc[] ==== Response include::{snippets}/categories/findMine/response-body.adoc[] + +=== ID를 통한 카테고리 단건 조회 + +==== Request + +include::{snippets}/categories/findById/http-request.adoc[] + +==== PathParameters + +include::{snippets}/categories/findById/path-parameters.adoc[] + +==== Response + +include::{snippets}/categories/findById/http-response.adoc[] diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index a616430b..7897b9bf 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -19,6 +19,7 @@ import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse; import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -41,6 +42,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; import org.springframework.test.web.servlet.MockMvc; @AutoConfigureRestDocs @@ -75,7 +77,8 @@ class CategoryControllerTest { .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(BE_일정_생성_요청)) - ).andDo(print()) + ) + .andDo(print()) .andDo(document("categories/save", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), @@ -131,7 +134,8 @@ class CategoryControllerTest { .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) .header("Authorization", DUMMY_BEARER_JWT) - ).andDo(print()) + ) + .andDo(print()) .andDo(document("categories/findMine", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), @@ -143,4 +147,30 @@ class CategoryControllerTest { ) .andExpect(status().isOk()); } + + @DisplayName("카테고리 ID로 카테고리를 단건 조회한다.") + @Test + void 카테고리_ID로_카테고리를_단건_조회한다() throws Exception { + // given + Long categoryId = 1L; + + CategoryResponse BE_일정 = new CategoryResponse(BE_일정(후디())); + given(categoryService.findById(any())).willReturn(BE_일정); + + // when & then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/categories/{categoryId}", categoryId) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ) + .andDo(print()) + .andDo(document("categories/findById", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("categoryId").description("카테고리 ID") + ) + ) + ) + .andExpect(status().isOk()); + } } From ea4b7f10bd9d8ec1fd57a473ef6cfb8cac443b3a Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 28 Jul 2022 22:24:21 +0900 Subject: [PATCH 0402/1011] =?UTF-8?q?test:=20JWT=EC=97=90=20=EA=B4=80?= =?UTF-8?q?=ED=95=9C=20=EC=83=81=EC=88=98=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/presentation/CategoryControllerTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index 7897b9bf..0f6b9cb3 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -49,7 +49,8 @@ @WebMvcTest(CategoryController.class) class CategoryControllerTest { - private static final String DUMMY_BEARER_JWT = "Bearer aaaaaaaa.bbbbbbbb.cccccccc"; + private static final String AUTHORIZATION_HEADER_NAME = "Authorization"; + private static final String AUTHORIZATION_HEADER_VALUE = "Bearer aaaaaaaa.bbbbbbbb.cccccccc"; @Autowired private MockMvc mockMvc; @@ -73,7 +74,7 @@ class CategoryControllerTest { // when & then mockMvc.perform(post("/api/categories") - .header("Authorization", DUMMY_BEARER_JWT) + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(BE_일정_생성_요청)) @@ -133,7 +134,7 @@ class CategoryControllerTest { mockMvc.perform(get("/api/categories/me?page={page}&size={size}", page, size) .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) - .header("Authorization", DUMMY_BEARER_JWT) + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) ) .andDo(print()) .andDo(document("categories/findMine", From 4bf4aa6f606bad4bb0b49bae5f770ec30b9f54ef Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 28 Jul 2022 22:53:13 +0900 Subject: [PATCH 0403/1011] =?UTF-8?q?test:=20Response=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=ED=94=BD=EC=8A=A4=EC=B2=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../category/presentation/CategoryControllerTest.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index 0f6b9cb3..727d9cc7 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -2,6 +2,7 @@ import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정; import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_생성_요청; +import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_응답; import static com.allog.dallog.common.fixtures.CategoryFixtures.BE_일정_이름; import static com.allog.dallog.common.fixtures.CategoryFixtures.FE_일정; import static com.allog.dallog.common.fixtures.CategoryFixtures.공통_일정; @@ -10,6 +11,7 @@ import static com.allog.dallog.common.fixtures.MemberFixtures.관리자; import static com.allog.dallog.common.fixtures.MemberFixtures.매트; import static com.allog.dallog.common.fixtures.MemberFixtures.후디; +import static com.allog.dallog.common.fixtures.MemberFixtures.후디_응답; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; @@ -31,7 +33,6 @@ import com.allog.dallog.domain.category.domain.Category; import com.allog.dallog.domain.category.dto.response.CategoriesResponse; import com.allog.dallog.domain.category.dto.response.CategoryResponse; -import com.allog.dallog.domain.member.dto.MemberResponse; import com.fasterxml.jackson.databind.ObjectMapper; import java.time.LocalDateTime; import java.util.List; @@ -68,8 +69,7 @@ class CategoryControllerTest { @Test void 카테고리를_생성한다() throws Exception { // given - MemberResponse 후디 = new MemberResponse(후디()); - CategoryResponse 카테고리 = new CategoryResponse(1L, BE_일정_이름, 후디, LocalDateTime.now()); + CategoryResponse 카테고리 = new CategoryResponse(1L, BE_일정_이름, 후디_응답, LocalDateTime.now()); given(categoryService.save(any(), any())).willReturn(카테고리); // when & then @@ -154,9 +154,8 @@ class CategoryControllerTest { void 카테고리_ID로_카테고리를_단건_조회한다() throws Exception { // given Long categoryId = 1L; - - CategoryResponse BE_일정 = new CategoryResponse(BE_일정(후디())); - given(categoryService.findById(any())).willReturn(BE_일정); + CategoryResponse BE_일정_응답 = BE_일정_응답(후디_응답); + given(categoryService.findById(any())).willReturn(BE_일정_응답); // when & then mockMvc.perform(RestDocumentationRequestBuilders.get("/api/categories/{categoryId}", categoryId) From a0252f4f9465fb1e469632be2a463d63c79a8e5a Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 28 Jul 2022 23:15:38 +0900 Subject: [PATCH 0404/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=88=98=EC=A0=95=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/category.adoc | 14 +++++++++ .../presentation/CategoryControllerTest.java | 31 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/backend/src/docs/asciidoc/category.adoc b/backend/src/docs/asciidoc/category.adoc index f5800d20..be53921b 100644 --- a/backend/src/docs/asciidoc/category.adoc +++ b/backend/src/docs/asciidoc/category.adoc @@ -51,3 +51,17 @@ include::{snippets}/categories/findById/path-parameters.adoc[] ==== Response include::{snippets}/categories/findById/http-response.adoc[] + +=== 카테고리 수정 + +==== Request + +include::{snippets}/categories/updates/http-request.adoc[] + +==== PathParameters + +include::{snippets}/categories/updates/path-parameters.adoc[] + +==== Response + +include::{snippets}/categories/updates/http-response.adoc[] diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index 727d9cc7..47043b45 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -14,6 +14,7 @@ import static com.allog.dallog.common.fixtures.MemberFixtures.후디_응답; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willDoNothing; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; @@ -31,6 +32,7 @@ import com.allog.dallog.domain.auth.application.AuthService; import com.allog.dallog.domain.category.application.CategoryService; import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.category.dto.request.CategoryUpdateRequest; import com.allog.dallog.domain.category.dto.response.CategoriesResponse; import com.allog.dallog.domain.category.dto.response.CategoryResponse; import com.fasterxml.jackson.databind.ObjectMapper; @@ -173,4 +175,33 @@ class CategoryControllerTest { ) .andExpect(status().isOk()); } + + @DisplayName("카테고리를 수정한다.") + @Test + void 카테고리를_수정한다() throws Exception { + // given + Long categoryId = 1L; + willDoNothing() + .given(categoryService) + .update(any(), any(), any()); + CategoryUpdateRequest 카테고리_수정_요청 = new CategoryUpdateRequest(BE_일정_이름); + + // when & then + mockMvc.perform(RestDocumentationRequestBuilders.patch("/api/categories/{categoryId}", categoryId) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) + .content(objectMapper.writeValueAsString(카테고리_수정_요청)) + ) + .andDo(print()) + .andDo(document("categories/updates", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("categoryId").description("카테고리 ID") + ) + ) + ) + .andExpect(status().isNoContent()); + } } From 6e7962dfa449fcd07be8400c06566583dc90c437 Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 28 Jul 2022 23:27:51 +0900 Subject: [PATCH 0405/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=A0=9C=EA=B1=B0=20=EC=BB=A8=ED=8A=B8=EB=A1=A4?= =?UTF-8?q?=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/category.adoc | 14 +++++++++ .../presentation/CategoryControllerTest.java | 29 ++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/backend/src/docs/asciidoc/category.adoc b/backend/src/docs/asciidoc/category.adoc index be53921b..2dcf6ac3 100644 --- a/backend/src/docs/asciidoc/category.adoc +++ b/backend/src/docs/asciidoc/category.adoc @@ -65,3 +65,17 @@ include::{snippets}/categories/updates/path-parameters.adoc[] ==== Response include::{snippets}/categories/updates/http-response.adoc[] + +=== 카테고리 삭제 + +==== Request + +include::{snippets}/categories/delete/http-request.adoc[] + +==== PathParameters + +include::{snippets}/categories/delete/path-parameters.adoc[] + +==== Response + +include::{snippets}/categories/delete/http-response.adoc[] diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index 47043b45..b60c5f1e 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -194,7 +194,34 @@ class CategoryControllerTest { .content(objectMapper.writeValueAsString(카테고리_수정_요청)) ) .andDo(print()) - .andDo(document("categories/updates", + .andDo(document("categories/update", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("categoryId").description("카테고리 ID") + ) + ) + ) + .andExpect(status().isNoContent()); + } + + @DisplayName("카테고리를 제거한다.") + @Test + void 카테고리를_제거한다() throws Exception { + // given + Long categoryId = 1L; + willDoNothing() + .given(categoryService) + .update(any(), any(), any()); + + // when & then + mockMvc.perform(RestDocumentationRequestBuilders.delete("/api/categories/{categoryId}", categoryId) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) + ) + .andDo(print()) + .andDo(document("categories/delete", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint()), pathParameters( From 8693482b9efd314016e3b2e2e2f3877a7163bcde Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 28 Jul 2022 23:46:08 +0900 Subject: [PATCH 0406/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=83=9D=EC=84=B1=EC=8B=9C=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EC=A0=84=EB=8B=AC=20=EC=BC=80=EC=9D=B4=EC=8A=A4=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/category.adoc | 10 ++++++ .../presentation/CategoryControllerTest.java | 31 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/backend/src/docs/asciidoc/category.adoc b/backend/src/docs/asciidoc/category.adoc index 2dcf6ac3..1a88a8e8 100644 --- a/backend/src/docs/asciidoc/category.adoc +++ b/backend/src/docs/asciidoc/category.adoc @@ -10,6 +10,16 @@ include::{snippets}/categories/save/http-request.adoc[] include::{snippets}/categories/save/http-response.adoc[] +=== 카테고리 생성 (유효하지 않은 카테고리 이름) + +==== Request + +include::{snippets}/categories/save/badRequest/http-request.adoc[] + +==== Response + +include::{snippets}/categories/save/badRequest/http-response.adoc[] + === 전체 카테고리 조회 ==== Request diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index b60c5f1e..ddcdf0cf 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -15,6 +15,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.willDoNothing; +import static org.mockito.BDDMockito.willThrow; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; @@ -32,9 +33,11 @@ import com.allog.dallog.domain.auth.application.AuthService; import com.allog.dallog.domain.category.application.CategoryService; import com.allog.dallog.domain.category.domain.Category; +import com.allog.dallog.domain.category.dto.request.CategoryCreateRequest; import com.allog.dallog.domain.category.dto.request.CategoryUpdateRequest; import com.allog.dallog.domain.category.dto.response.CategoriesResponse; import com.allog.dallog.domain.category.dto.response.CategoryResponse; +import com.allog.dallog.domain.category.exception.InvalidCategoryException; import com.fasterxml.jackson.databind.ObjectMapper; import java.time.LocalDateTime; import java.util.List; @@ -92,6 +95,34 @@ class CategoryControllerTest { .andExpect(status().isCreated()); } + @DisplayName("잘못된 이름 형식으로 카테고리를 생성하면 400 Bad Request가 발생한다.") + @Test + void 잘못된_이름_형식으로_카테고리를_생성하면_400_Bad_Request가_발생한다() throws Exception { + // given + willThrow(new InvalidCategoryException("카테고리 이름의 길이는 20을 초과할 수 없습니다.")) + .given(categoryService) + .save(any(), any()); + + CategoryCreateRequest 잘못된_카테고리_생성_요청 = new CategoryCreateRequest("20글자를 초과하는 유효하지 않은 카테고리 이름"); + + // when & then + mockMvc.perform(post("/api/categories") + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(잘못된_카테고리_생성_요청)) + ) + .andDo(print()) + .andDo(document("categories/save/badRequest", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + requestHeaders( + headerWithName("Authorization").description("JWT 토큰")) + ) + ) + .andExpect(status().isBadRequest()); + } + @DisplayName("생성된 카테고리를 전부 조회한다.") @Test void 생성된_카테고리를_전부_조회한다() throws Exception { From ba89cf613cece1cc7d2745fc95a7144779c7c757 Mon Sep 17 00:00:00 2001 From: devHudi Date: Thu, 28 Jul 2022 23:50:46 +0900 Subject: [PATCH 0407/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EB=8B=A8=EA=B1=B4=20=EC=A1=B0=ED=9A=8C=20=EC=8B=9C?= =?UTF-8?q?=20=EC=A1=B4=EC=9E=AC=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=84=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/category.adoc | 10 +++++++ .../presentation/CategoryControllerTest.java | 26 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/backend/src/docs/asciidoc/category.adoc b/backend/src/docs/asciidoc/category.adoc index 1a88a8e8..1116a6ae 100644 --- a/backend/src/docs/asciidoc/category.adoc +++ b/backend/src/docs/asciidoc/category.adoc @@ -62,6 +62,16 @@ include::{snippets}/categories/findById/path-parameters.adoc[] include::{snippets}/categories/findById/http-response.adoc[] +=== ID를 통한 카테고리 단건 조회 (존재하지 않는 경우) + +==== Request + +include::{snippets}/categories/findById/notFound/http-request.adoc[] + +==== Response + +include::{snippets}/categories/findById/notFound/http-response.adoc[] + === 카테고리 수정 ==== Request diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index ddcdf0cf..e5c337d2 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -38,6 +38,7 @@ import com.allog.dallog.domain.category.dto.response.CategoriesResponse; import com.allog.dallog.domain.category.dto.response.CategoryResponse; import com.allog.dallog.domain.category.exception.InvalidCategoryException; +import com.allog.dallog.domain.category.exception.NoSuchCategoryException; import com.fasterxml.jackson.databind.ObjectMapper; import java.time.LocalDateTime; import java.util.List; @@ -207,6 +208,31 @@ class CategoryControllerTest { .andExpect(status().isOk()); } + @DisplayName("카테고리 ID로 카테고리를 단건 조회시 존재하지 않으면 404 Not Found가 발생한다.") + @Test + void 카테고리_ID로_카테고리를_단건_조회시_존재하지_않으면_404_Not_Found를_반환한다() throws Exception { + // given + Long categoryId = 1L; + given(categoryService.findById(any())) + .willThrow(new NoSuchCategoryException()); + + // when & then + mockMvc.perform(RestDocumentationRequestBuilders.get("/api/categories/{categoryId}", categoryId) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + ) + .andDo(print()) + .andDo(document("categories/findById/notFound", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("categoryId").description("카테고리 ID") + ) + ) + ) + .andExpect(status().isNotFound()); + } + @DisplayName("카테고리를 수정한다.") @Test void 카테고리를_수정한다() throws Exception { From 2d410b9892a32358913cc0593877169275ce1ab6 Mon Sep 17 00:00:00 2001 From: devHudi Date: Fri, 29 Jul 2022 00:00:23 +0900 Subject: [PATCH 0408/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=20=EC=8B=9C=20=EC=A1=B4=EC=9E=AC=ED=95=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EC=9D=84=20=EA=B2=BD=EC=9A=B0=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/category.adoc | 26 +++++++- .../presentation/CategoryControllerTest.java | 60 +++++++++++++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/backend/src/docs/asciidoc/category.adoc b/backend/src/docs/asciidoc/category.adoc index 1116a6ae..9c6db800 100644 --- a/backend/src/docs/asciidoc/category.adoc +++ b/backend/src/docs/asciidoc/category.adoc @@ -76,15 +76,25 @@ include::{snippets}/categories/findById/notFound/http-response.adoc[] ==== Request -include::{snippets}/categories/updates/http-request.adoc[] +include::{snippets}/categories/update/http-request.adoc[] ==== PathParameters -include::{snippets}/categories/updates/path-parameters.adoc[] +include::{snippets}/categories/update/path-parameters.adoc[] ==== Response -include::{snippets}/categories/updates/http-response.adoc[] +include::{snippets}/categories/update/http-response.adoc[] + +=== 카테고리 수정 (존재하지 않는 경우) + +==== Request + +include::{snippets}/categories/update/notFound/http-request.adoc[] + +==== Response + +include::{snippets}/categories/update/notFound/http-response.adoc[] === 카테고리 삭제 @@ -99,3 +109,13 @@ include::{snippets}/categories/delete/path-parameters.adoc[] ==== Response include::{snippets}/categories/delete/http-response.adoc[] + +=== 카테고리 삭제 (존재하지 않는 경우) + +==== Request + +include::{snippets}/categories/delete/notFound/http-request.adoc[] + +==== Response + +include::{snippets}/categories/delete/notFound/http-response.adoc[] diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index e5c337d2..2fbdf224 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -262,6 +262,37 @@ class CategoryControllerTest { .andExpect(status().isNoContent()); } + + @DisplayName("카테고리 수정 시 존재하지 않으면 404 Not Found가 발생한다.") + @Test + void 카테고리_수정_시_존재하지_않으면_404_Not_Found를_반환한다() throws Exception { + // given + Long categoryId = 1L; + willThrow(NoSuchCategoryException.class) + .willDoNothing() + .given(categoryService) + .update(any(), any(), any()); + CategoryUpdateRequest 카테고리_수정_요청 = new CategoryUpdateRequest(BE_일정_이름); + + // when & then + mockMvc.perform(RestDocumentationRequestBuilders.patch("/api/categories/{categoryId}", categoryId) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) + .content(objectMapper.writeValueAsString(카테고리_수정_요청)) + ) + .andDo(print()) + .andDo(document("categories/update/notFound", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("categoryId").description("카테고리 ID") + ) + ) + ) + .andExpect(status().isNotFound()); + } + @DisplayName("카테고리를 제거한다.") @Test void 카테고리를_제거한다() throws Exception { @@ -288,4 +319,33 @@ class CategoryControllerTest { ) .andExpect(status().isNoContent()); } + + + @DisplayName("카테고리 제거 시 존재하지 않으면 404 Not Found가 발생한다") + @Test + void 카테고리_제거_시_존재하지_않으면_404_Not_Found가_발생한다() throws Exception { + // given + Long categoryId = 1L; + willThrow(new NoSuchCategoryException("존재하지 않는 카테고리를 삭제할 수 없습니다.")) + .willDoNothing() + .given(categoryService) + .delete(any(), any()); + + // when & then + mockMvc.perform(RestDocumentationRequestBuilders.delete("/api/categories/{categoryId}", categoryId) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) + ) + .andDo(print()) + .andDo(document("categories/delete/notFound", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("categoryId").description("카테고리 ID") + ) + ) + ) + .andExpect(status().isNotFound()); + } } From 615aada3d58fea9cd0c28a6ec5a881dacbea1df0 Mon Sep 17 00:00:00 2001 From: devHudi Date: Fri, 29 Jul 2022 00:06:42 +0900 Subject: [PATCH 0409/1011] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=88=98=EC=A0=95=20=EC=8B=9C=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EC=A0=84=EB=8B=AC=20=EC=BC=80=EC=9D=B4=EC=8A=A4=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/docs/asciidoc/category.adoc | 10 +++++ .../presentation/CategoryControllerTest.java | 37 +++++++++++++++++-- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/backend/src/docs/asciidoc/category.adoc b/backend/src/docs/asciidoc/category.adoc index 9c6db800..94611303 100644 --- a/backend/src/docs/asciidoc/category.adoc +++ b/backend/src/docs/asciidoc/category.adoc @@ -96,6 +96,16 @@ include::{snippets}/categories/update/notFound/http-request.adoc[] include::{snippets}/categories/update/notFound/http-response.adoc[] +=== 카테고리 수정 (유효하지 않은 카테고리 이름) + +==== Request + +include::{snippets}/categories/update/badRequest/http-request.adoc[] + +==== Response + +include::{snippets}/categories/update/badRequest/http-response.adoc[] + === 카테고리 삭제 ==== Request diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index 2fbdf224..0b23925c 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -58,6 +58,8 @@ class CategoryControllerTest { private static final String AUTHORIZATION_HEADER_NAME = "Authorization"; private static final String AUTHORIZATION_HEADER_VALUE = "Bearer aaaaaaaa.bbbbbbbb.cccccccc"; + private static final String INVALID_CATEGORY_NAME = "20글자를 초과하는 유효하지 않은 카테고리 이름"; + private static final String CATEGORY_NAME_OVER_LENGTH_EXCEPTION_MESSAGE = "카테고리 이름의 길이는 20을 초과할 수 없습니다."; @Autowired private MockMvc mockMvc; @@ -100,11 +102,11 @@ class CategoryControllerTest { @Test void 잘못된_이름_형식으로_카테고리를_생성하면_400_Bad_Request가_발생한다() throws Exception { // given - willThrow(new InvalidCategoryException("카테고리 이름의 길이는 20을 초과할 수 없습니다.")) + willThrow(new InvalidCategoryException(CATEGORY_NAME_OVER_LENGTH_EXCEPTION_MESSAGE)) .given(categoryService) .save(any(), any()); - CategoryCreateRequest 잘못된_카테고리_생성_요청 = new CategoryCreateRequest("20글자를 초과하는 유효하지 않은 카테고리 이름"); + CategoryCreateRequest 잘못된_카테고리_생성_요청 = new CategoryCreateRequest(INVALID_CATEGORY_NAME); // when & then mockMvc.perform(post("/api/categories") @@ -262,7 +264,6 @@ class CategoryControllerTest { .andExpect(status().isNoContent()); } - @DisplayName("카테고리 수정 시 존재하지 않으면 404 Not Found가 발생한다.") @Test void 카테고리_수정_시_존재하지_않으면_404_Not_Found를_반환한다() throws Exception { @@ -293,6 +294,36 @@ class CategoryControllerTest { .andExpect(status().isNotFound()); } + @DisplayName("잘못된 이름 형식으로 카테고리를 수정하면 400 Bad Request가 발생한다.") + @Test + void 잘못된_이름_형식으로_카테고리를_수정하면_400_Bad_Request가_발생한다() throws Exception { + // given + Long categoryId = 1L; + willThrow(new InvalidCategoryException(CATEGORY_NAME_OVER_LENGTH_EXCEPTION_MESSAGE)) + .willDoNothing() + .given(categoryService) + .update(any(), any(), any()); + CategoryUpdateRequest 카테고리_수정_요청 = new CategoryUpdateRequest(INVALID_CATEGORY_NAME); + + // when & then + mockMvc.perform(RestDocumentationRequestBuilders.patch("/api/categories/{categoryId}", categoryId) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .header(AUTHORIZATION_HEADER_NAME, AUTHORIZATION_HEADER_VALUE) + .content(objectMapper.writeValueAsString(카테고리_수정_요청)) + ) + .andDo(print()) + .andDo(document("categories/update/badRequest", + preprocessRequest(prettyPrint()), + preprocessResponse(prettyPrint()), + pathParameters( + parameterWithName("categoryId").description("카테고리 ID") + ) + ) + ) + .andExpect(status().isBadRequest()); + } + @DisplayName("카테고리를 제거한다.") @Test void 카테고리를_제거한다() throws Exception { From 69afefbc5b898460243585beacecda197c81e0e1 Mon Sep 17 00:00:00 2001 From: devHudi Date: Mon, 1 Aug 2022 15:48:55 +0900 Subject: [PATCH 0410/1011] =?UTF-8?q?refactor:=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=ED=94=BD=EC=8A=A4=EC=B2=98=EB=A1=9C=20=EB=8C=80?= =?UTF-8?q?=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/category/presentation/CategoryControllerTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java index 0b23925c..80a7ecfc 100644 --- a/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java +++ b/backend/src/test/java/com/allog/dallog/domain/category/presentation/CategoryControllerTest.java @@ -40,7 +40,6 @@ import com.allog.dallog.domain.category.exception.InvalidCategoryException; import com.allog.dallog.domain.category.exception.NoSuchCategoryException; import com.fasterxml.jackson.databind.ObjectMapper; -import java.time.LocalDateTime; import java.util.List; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -77,7 +76,7 @@ class CategoryControllerTest { @Test void 카테고리를_생성한다() throws Exception { // given - CategoryResponse 카테고리 = new CategoryResponse(1L, BE_일정_이름, 후디_응답, LocalDateTime.now()); + CategoryResponse 카테고리 = BE_일정_응답(후디_응답); given(categoryService.save(any(), any())).willReturn(카테고리); // when & then From 6b7499e1456cc38bc7d762ed3927257615600318 Mon Sep 17 00:00:00 2001 From: jhy979 Date: Thu, 28 Jul 2022 12:00:01 +0900 Subject: [PATCH 0411/1011] stlye --- frontend/src/styles/theme.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/styles/theme.ts b/frontend/src/styles/theme.ts index 091b977a..d7bace73 100644 --- a/frontend/src/styles/theme.ts +++ b/frontend/src/styles/theme.ts @@ -2,7 +2,7 @@ import { css, Theme } from '@emotion/react'; const colors = { YELLOW_400: '#fee500', - YELLOW_500: '#FCC419', + YELLOW_500: '#465057', GREEN_500: '#03c75a', WHITE: '#ffffff', GRAY_000: '#f8f9fa', From b1e71ee8905b8091973ff8932086d8f4a20077ac Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 1 Aug 2022 16:15:57 +0900 Subject: [PATCH 0412/1011] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=95=84?= =?UTF-8?q?=EC=9B=83=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/constants/index.ts | 1 + frontend/src/pages/MyPage/MyPage.styles.ts | 29 ++++++++++++++++------ frontend/src/pages/MyPage/MyPage.tsx | 24 ++++++++++++++++-- frontend/src/utils/index.ts | 6 ++++- 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 7bbbc881..93f65b13 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -23,6 +23,7 @@ const CACHE_KEY = { const CONFIRM_MESSAGE = { DELETE_CATEGORY: '정말 삭제하시겠습니까?', UNSUBSCRIBE: '구독을 해제하시겠습니까?', + LOG_OUT: '로그아웃하시겠습니까?', }; const DAYS = ['일', '월', '화', '수', '목', '금', '토']; diff --git a/frontend/src/pages/MyPage/MyPage.styles.ts b/frontend/src/pages/MyPage/MyPage.styles.ts index 541f58ba..78a070c4 100644 --- a/frontend/src/pages/MyPage/MyPage.styles.ts +++ b/frontend/src/pages/MyPage/MyPage.styles.ts @@ -1,11 +1,13 @@ import { css, Theme } from '@emotion/react'; -const myPage = ({ colors }: Theme) => css` +const myPage = css` + position: relative; + top: 50%; + transform: translateY(-40%); + width: 100%; height: 100%; padding: 2rem; - - background: ${colors.GRAY_100}; `; const infoTable = ({ colors }: Theme) => css` @@ -13,11 +15,13 @@ const infoTable = ({ colors }: Theme) => css` padding: 4rem; margin: 0 auto; border: 1px solid ${colors.GRAY_500}; - - background: ${colors.WHITE}; `; -const infoTableHeader = ({ colors }: Theme) => css` +const infoTableHeader = ({ colors, flex }: Theme) => css` + ${flex.row} + + justify-content: space-between; + width: 100%; margin: 0 auto; padding: 4rem; @@ -58,4 +62,15 @@ const imageSize = css` height: 40rem; `; -export { myPage, infoTable, infoTableHeader, textInfo, imageInfo, imageSize }; +const logoutButtonStyle = ({ colors }: Theme) => css` + padding: 2rem; + border-radius: 8px; + filter: drop-shadow(0px 2px 2px ${colors.GRAY_400}); + + background: ${colors.YELLOW_500}; + + font-size: 3rem; + color: ${colors.WHITE}; +`; + +export { myPage, infoTable, infoTableHeader, logoutButtonStyle, textInfo, imageInfo, imageSize }; diff --git a/frontend/src/pages/MyPage/MyPage.tsx b/frontend/src/pages/MyPage/MyPage.tsx index 246a0083..efb0fa24 100644 --- a/frontend/src/pages/MyPage/MyPage.tsx +++ b/frontend/src/pages/MyPage/MyPage.tsx @@ -1,14 +1,18 @@ import { AxiosError, AxiosResponse } from 'axios'; import { useQuery } from 'react-query'; +import { useNavigate } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; import { ProfileType } from '@/@types/profile'; import { userState } from '@/recoil/atoms'; +import Button from '@/components/@common/Button/Button'; import PageLayout from '@/components/@common/PageLayout/PageLayout'; -import { CACHE_KEY } from '@/constants'; +import { CACHE_KEY, CONFIRM_MESSAGE, PATH } from '@/constants'; + +import { clearAccessToken } from '@/utils'; import profileAPI from '@/api/profile'; @@ -17,6 +21,7 @@ import { imageSize, infoTable, infoTableHeader, + logoutButtonStyle, myPage, textInfo, } from './MyPage.styles'; @@ -24,6 +29,8 @@ import { function MyPage() { const { accessToken } = useRecoilValue(userState); + const navigate = useNavigate(); + const { isLoading, error, @@ -40,13 +47,26 @@ function MyPage() { return
    Error
    ; } + const handleClickLogoutButton = () => { + if (window.confirm(CONFIRM_MESSAGE.LOG_OUT)) { + clearAccessToken(); + navigate(PATH.MAIN); + location.reload(); + } + }; + const { displayName, email, profileImageUrl } = profileGetResponse.data; return (
    -
    프로필
    +
    + 프로필 + +
    이름(닉네임) {displayName} diff --git a/frontend/src/utils/index.ts b/frontend/src/utils/index.ts index f1bd5666..75041f90 100644 --- a/frontend/src/utils/index.ts +++ b/frontend/src/utils/index.ts @@ -29,4 +29,8 @@ const setAccessToken = (accessToken: string) => { localStorage.setItem(STORAGE_KEY.ACCESS_TOKEN, accessToken); }; -export { createPostBody, getAccessToken, setAccessToken }; +const clearAccessToken = () => { + localStorage.removeItem(STORAGE_KEY.ACCESS_TOKEN); +}; + +export { clearAccessToken, createPostBody, getAccessToken, setAccessToken }; From a2105944f487a72c3e86ec9e42077788655a7e6b Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 1 Aug 2022 16:17:34 +0900 Subject: [PATCH 0413/1011] =?UTF-8?q?fix:=20YELLOW=5F500=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EB=B3=B5=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/styles/theme.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/styles/theme.ts b/frontend/src/styles/theme.ts index d7bace73..8a191273 100644 --- a/frontend/src/styles/theme.ts +++ b/frontend/src/styles/theme.ts @@ -2,7 +2,7 @@ import { css, Theme } from '@emotion/react'; const colors = { YELLOW_400: '#fee500', - YELLOW_500: '#465057', + YELLOW_500: '#fcc419', GREEN_500: '#03c75a', WHITE: '#ffffff', GRAY_000: '#f8f9fa', From 1cc0db6212c7dcf3522e41ee4512eb526963b87c Mon Sep 17 00:00:00 2001 From: jhy979 Date: Mon, 1 Aug 2022 16:24:17 +0900 Subject: [PATCH 0414/1011] =?UTF-8?q?refactor:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=95=84=EC=9B=83=20=EC=83=81=EC=88=98=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/constants/index.ts | 2 +- frontend/src/pages/MyPage/MyPage.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 93f65b13..d523db9e 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -23,7 +23,7 @@ const CACHE_KEY = { const CONFIRM_MESSAGE = { DELETE_CATEGORY: '정말 삭제하시겠습니까?', UNSUBSCRIBE: '구독을 해제하시겠습니까?', - LOG_OUT: '로그아웃하시겠습니까?', + LOGOUT: '로그아웃하시겠습니까?', }; const DAYS = ['일', '월', '화', '수', '목', '금', '토']; diff --git a/frontend/src/pages/MyPage/MyPage.tsx b/frontend/src/pages/MyPage/MyPage.tsx index efb0fa24..e4b0ee83 100644 --- a/frontend/src/pages/MyPage/MyPage.tsx +++ b/frontend/src/pages/MyPage/MyPage.tsx @@ -48,7 +48,7 @@ function MyPage() { } const handleClickLogoutButton = () => { - if (window.confirm(CONFIRM_MESSAGE.LOG_OUT)) { + if (window.confirm(CONFIRM_MESSAGE.LOGOUT)) { clearAccessToken(); navigate(PATH.MAIN); location.reload(); From b83ec28d26bd08f05e1adde45b0ba8ad066d74e4 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Mon, 1 Aug 2022 16:08:51 +0900 Subject: [PATCH 0415/1011] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EC=8B=9D=EB=B3=84=EC=9E=90=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/CategoryAddModal/CategoryAddModal.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx b/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx index b9d57e22..672f61e6 100644 --- a/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx +++ b/frontend/src/components/CategoryAddModal/CategoryAddModal.tsx @@ -37,7 +37,7 @@ function CategoryAddModal({ closeModal }: CategoryAddModalProps) { const { accessToken } = useRecoilValue(userState); const queryClient = useQueryClient(); - const { mutate: postCategory } = useMutation< + const { mutate } = useMutation< AxiosResponse>, AxiosError, Pick, @@ -61,7 +61,7 @@ function CategoryAddModal({ closeModal }: CategoryAddModalProps) { return; } - postCategory(body); + mutate(body); }; const onSuccessPostCategory = () => { From 1ed4773a2f2af4fdcbb017bec8f26dbdd258d7be Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Mon, 1 Aug 2022 16:12:03 +0900 Subject: [PATCH 0416/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=88=98=EC=A0=95=20=EB=AA=A8=EB=8B=AC=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CategoryModifyModal.styles.ts | 70 +++++++++++++++++++ .../CategoryModifyModal.tsx | 58 +++++++++++++++ .../MyCategoryItem/MyCategoryItem.tsx | 12 +++- 3 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/CategoryModifyModal/CategoryModifyModal.styles.ts create mode 100644 frontend/src/components/CategoryModifyModal/CategoryModifyModal.tsx diff --git a/frontend/src/components/CategoryModifyModal/CategoryModifyModal.styles.ts b/frontend/src/components/CategoryModifyModal/CategoryModifyModal.styles.ts new file mode 100644 index 00000000..71c2daf6 --- /dev/null +++ b/frontend/src/components/CategoryModifyModal/CategoryModifyModal.styles.ts @@ -0,0 +1,70 @@ +import { css, Theme } from '@emotion/react'; + +const modal = ({ colors, flex }: Theme) => css` + ${flex.column} + + width: 120rem; + height: 90rem; + padding: 12.5rem; + border-radius: 12px; + justify-content: space-between; + + background: ${colors.WHITE}; +`; + +const title = ({ colors }: Theme) => css` + font-size: 8rem; + font-weight: bold; + color: ${colors.GRAY_700}; +`; + +const form = ({ flex }: Theme) => css` + ${flex.column}; + + width: 100%; + height: 100%; + justify-content: space-between; +`; + +const content = ({ flex }: Theme) => css` + ${flex.column}; + + width: 100%; + height: 100%; + + justify-content: center; +`; + +const controlButtons = ({ flex }: Theme) => css` + ${flex.row} + + align-self: flex-end; + gap: 5rem; +`; + +const cancelButton = ({ colors }: Theme) => css` + width: 22.5rem; + height: 10rem; + border: 2px solid ${colors.GRAY_500}; + border-radius: 8px; + filter: drop-shadow(0 2px 2px ${colors.GRAY_400}); + + background: ${colors.WHITE}; + + font-size: 5rem; + color: ${colors.GRAY_600}; +`; + +const saveButton = ({ colors }: Theme) => css` + width: 22.5rem; + height: 10rem; + border-radius: 8px; + filter: drop-shadow(0px 2px 2px ${colors.GRAY_400}); + + background: ${colors.YELLOW_500}; + + font-size: 5rem; + color: ${colors.WHITE}; +`; + +export { cancelButton, content, controlButtons, form, modal, saveButton, title }; diff --git a/frontend/src/components/CategoryModifyModal/CategoryModifyModal.tsx b/frontend/src/components/CategoryModifyModal/CategoryModifyModal.tsx new file mode 100644 index 00000000..b7cf1fc3 --- /dev/null +++ b/frontend/src/components/CategoryModifyModal/CategoryModifyModal.tsx @@ -0,0 +1,58 @@ +import { useTheme } from '@emotion/react'; +import { AxiosError, AxiosResponse } from 'axios'; +import { useRef } from 'react'; +import { useMutation, useQueryClient } from 'react-query'; +import { useRecoilValue } from 'recoil'; + +import { CategoryType } from '@/@types/category'; + +import Button from '@/components/@common/Button/Button'; +import FieldSet from '@/components/@common/FieldSet/FieldSet'; + +import { + cancelButton, + content, + controlButtons, + form, + modal, + saveButton, + title, +} from './CategoryModifyModal.styles'; + +interface CategoryModifyModalProps { + category: CategoryType; + closeModal: () => void; +} + +function CategoryModifyModal({ category, closeModal }: CategoryModifyModalProps) { + const theme = useTheme(); + + const inputRef = { + name: useRef(null), + }; + + const handleClickModal = (e: React.MouseEvent) => { + e.stopPropagation(); + }; + + return ( +
    +

    카테고리 수정

    + +
    +
    +
    +
    + + +
    + +
    + ); +} + +export default CategoryModifyModal; diff --git a/frontend/src/components/MyCategoryItem/MyCategoryItem.tsx b/frontend/src/components/MyCategoryItem/MyCategoryItem.tsx index bd4ffc4a..6e0506e5 100644 --- a/frontend/src/components/MyCategoryItem/MyCategoryItem.tsx +++ b/frontend/src/components/MyCategoryItem/MyCategoryItem.tsx @@ -1,11 +1,15 @@ import { useMutation, useQueryClient } from 'react-query'; import { useRecoilValue } from 'recoil'; +import useToggle from '@/hooks/useToggle'; + import { CategoryType } from '@/@types/category'; import { userState } from '@/recoil/atoms'; import Button from '@/components/@common/Button/Button'; +import ModalPortal from '@/components/@common/ModalPortal/ModalPortal'; +import CategoryModifyModal from '@/components/CategoryModifyModal/CategoryModifyModal'; import { CACHE_KEY, CONFIRM_MESSAGE } from '@/constants'; @@ -23,6 +27,9 @@ interface MyCategoryItemProps { function MyCategoryItem({ category }: MyCategoryItemProps) { const { accessToken } = useRecoilValue(userState); + const { state: isCategoryModifyModalOpen, toggleState: toggleCategoryModifyModalOpen } = + useToggle(); + const queryClient = useQueryClient(); const { mutate } = useMutation(() => categoryApi.delete(accessToken, category.id), { onSuccess: () => onSuccessDeleteCategory(), @@ -43,7 +50,10 @@ function MyCategoryItem({ category }: MyCategoryItemProps) {
    {category.name}
    - -
    -
    +

    -
    -
    +
    +
    +
    From 9fe5b3e20c3726cc203ef437e5fd3bad57b332ef Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Tue, 2 Aug 2022 15:08:58 +0900 Subject: [PATCH 0446/1011] =?UTF-8?q?feat:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=9D=B4=EB=A6=84=20=EA=B2=80=EC=83=89=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/api/category.ts | 18 +++++++++++++----- .../CategoryList/CategoryList.stories.tsx | 6 ++---- .../components/CategoryList/CategoryList.tsx | 16 ++++++++++------ .../src/pages/CategoryPage/CategoryPage.tsx | 14 +++++++++++++- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/frontend/src/api/category.ts b/frontend/src/api/category.ts index 508d7091..61f08209 100644 --- a/frontend/src/api/category.ts +++ b/frontend/src/api/category.ts @@ -12,11 +12,19 @@ const categoryApi = { Accept: 'application/json', }, - getEntire: async (page: number, size: number) => { - const response = await dallogApi.get(categoryApi.endpoint.entire, { - params: { page, size }, - headers: categoryApi.headers, - }); + getEntire: async (name: string, page: number, size: number) => { + const response = await dallogApi.get( + categoryApi.endpoint.entire, + name === '' + ? { + params: { page, size }, + headers: categoryApi.headers, + } + : { + params: { name, page, size }, + headers: categoryApi.headers, + } + ); return response; }, diff --git a/frontend/src/components/CategoryList/CategoryList.stories.tsx b/frontend/src/components/CategoryList/CategoryList.stories.tsx index c3ae1306..c293c3d9 100644 --- a/frontend/src/components/CategoryList/CategoryList.stories.tsx +++ b/frontend/src/components/CategoryList/CategoryList.stories.tsx @@ -1,7 +1,5 @@ import { ComponentMeta, ComponentStory } from '@storybook/react'; -import { categoryDB } from '@/mocks/data'; - import CategoryList from './CategoryList'; export default { @@ -9,9 +7,9 @@ export default { component: CategoryList, } as ComponentMeta; -const Template: ComponentStory = () => ; +const Template: ComponentStory = (args) => ; export const Primary = Template.bind({}); Primary.args = { - categoryList: categoryDB.categories, + keyword: '', }; diff --git a/frontend/src/components/CategoryList/CategoryList.tsx b/frontend/src/components/CategoryList/CategoryList.tsx index ac042465..1dfb5461 100644 --- a/frontend/src/components/CategoryList/CategoryList.tsx +++ b/frontend/src/components/CategoryList/CategoryList.tsx @@ -19,7 +19,11 @@ import subscriptionApi from '@/api/subscription'; import { categoryTable, categoryTableHeader, intersectTarget, item } from './CategoryList.styles'; -function CategoryList() { +interface CategoryListProps { + keyword: string; +} + +function CategoryList({ keyword }: CategoryListProps) { const { accessToken } = useRecoilValue(userState); const { @@ -28,8 +32,8 @@ function CategoryList() { fetchNextPage, hasNextPage, } = useInfiniteQuery, AxiosError>( - CACHE_KEY.CATEGORIES, - ({ pageParam = 0 }) => categoryApi.getEntire(pageParam, API.CATEGORY_GET_SIZE), + [CACHE_KEY.CATEGORIES, keyword], + ({ pageParam = 0 }) => categoryApi.getEntire(keyword, pageParam, API.CATEGORY_GET_SIZE), { getNextPageParam: ({ data }) => { if (data.categories.length > 0) { @@ -67,9 +71,9 @@ function CategoryList() { return ( <>
    - 생성 날짜 - 카테고리 이름 - 구독 상태 + 생성 날짜 + 카테고리 이름 + 구독 상태
    {categoryList.map((category) => { diff --git a/frontend/src/pages/CategoryPage/CategoryPage.tsx b/frontend/src/pages/CategoryPage/CategoryPage.tsx index e8e6472e..52958902 100644 --- a/frontend/src/pages/CategoryPage/CategoryPage.tsx +++ b/frontend/src/pages/CategoryPage/CategoryPage.tsx @@ -1,3 +1,5 @@ +import { useRef, useState } from 'react'; + import Button from '@/components/@common/Button/Button'; import Fieldset from '@/components/@common/Fieldset/Fieldset'; import PageLayout from '@/components/@common/PageLayout/PageLayout'; @@ -14,8 +16,17 @@ import { } from './CategoryPage.styles'; function CategoryPage() { + const keywordRef = useRef(null); + const [keyword, setKeyword] = useState(''); + const handleSubmitCategorySearchForm = (e: React.FormEvent) => { e.preventDefault(); + + if (!(keywordRef.current instanceof HTMLInputElement)) { + return; + } + + setKeyword((keywordRef.current as HTMLInputElement).value); }; return ( @@ -28,9 +39,10 @@ function CategoryPage() {
    - +
    ); From a7d02a54642ed45bd5cb68bcb98cdc5419df0c70 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Tue, 2 Aug 2022 15:09:35 +0900 Subject: [PATCH 0447/1011] =?UTF-8?q?style:=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=20=EB=86=92=EC=9D=B4=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/CategoryList/CategoryList.styles.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/CategoryList/CategoryList.styles.ts b/frontend/src/components/CategoryList/CategoryList.styles.ts index cb8a323b..3e6be54f 100644 --- a/frontend/src/components/CategoryList/CategoryList.styles.ts +++ b/frontend/src/components/CategoryList/CategoryList.styles.ts @@ -4,7 +4,7 @@ const categoryTable = css` overflow-y: overlay; width: 100%; - height: 72vh; + height: 100%; `; const categoryTableHeader = ({ flex, colors }: Theme) => css` @@ -23,7 +23,7 @@ const categoryTableHeader = ({ flex, colors }: Theme) => css` `; const intersectTarget = css` - height: 10rem; + height: 1rem; `; const item = css` From 60e389af205191220d792f34da01c3a400c00f00 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Tue, 2 Aug 2022 15:10:06 +0900 Subject: [PATCH 0448/1011] =?UTF-8?q?feat:=20msw=20=EC=B9=B4=ED=85=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=20=EC=9D=B4=EB=A6=84=20=EA=B2=80=EC=83=89=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EB=AA=A8=ED=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/mocks/handlers.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/frontend/src/mocks/handlers.ts b/frontend/src/mocks/handlers.ts index 1f626aa4..a66f8930 100644 --- a/frontend/src/mocks/handlers.ts +++ b/frontend/src/mocks/handlers.ts @@ -24,15 +24,19 @@ const handlers = [ rest.get(API_URL + categoryApi.endpoint.entire, (req, res, ctx) => { const page = parseInt(req.url.searchParams.get('page') as string); const size = API.CATEGORY_GET_SIZE; - const slicedCategories = categoryDB.categories.slice(page * size, page * size + size); - - return res( - ctx.status(200), - ctx.json({ - page, - categories: slicedCategories, - }) - ); + const name = req.url.searchParams.get('name'); + + if (name === null || name === '') { + const entireCategories = categoryDB.categories.slice(page * size, page * size + size); + + return res(ctx.status(200), ctx.json({ page, categories: entireCategories })); + } + + const filteredCategories = categoryDB.categories + .filter((category) => category.name.includes(name)) + .slice(page * size, page * size + size); + + return res(ctx.status(200), ctx.json({ page, categories: filteredCategories })); }), rest.post>(API_URL + categoryApi.endpoint.entire, (req, res, ctx) => { From b1b3e0bcdf5a6e5a5b5988bf0701b1066b1c23d2 Mon Sep 17 00:00:00 2001 From: Daye Lee <508yeah@gmail.com> Date: Tue, 2 Aug 2022 18:02:03 +0900 Subject: [PATCH 0449/1011] =?UTF-8?q?refactor:=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20=EB=B3=80=EC=88=98=EB=AA=85=EC=97=90=20style=20post?= =?UTF-8?q?fix=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../@common/Fieldset/Fieldset.styles.ts | 8 ++++---- .../components/@common/Fieldset/Fieldset.tsx | 8 ++++---- .../CategoryList/CategoryList.styles.ts | 10 +++++----- .../components/CategoryList/CategoryList.tsx | 19 ++++++++++++------- .../pages/CategoryPage/CategoryPage.styles.ts | 18 ++++++++++++------ .../src/pages/CategoryPage/CategoryPage.tsx | 18 +++++++++--------- 6 files changed, 46 insertions(+), 35 deletions(-) diff --git a/frontend/src/components/@common/Fieldset/Fieldset.styles.ts b/frontend/src/components/@common/Fieldset/Fieldset.styles.ts index 302348ac..2cc4cb06 100644 --- a/frontend/src/components/@common/Fieldset/Fieldset.styles.ts +++ b/frontend/src/components/@common/Fieldset/Fieldset.styles.ts @@ -1,6 +1,6 @@ import { css, Theme } from '@emotion/react'; -const fieldset = ({ flex }: Theme) => css` +const fieldsetStyle = ({ flex }: Theme) => css` ${flex.column} width: 100%; @@ -12,11 +12,11 @@ const fieldset = ({ flex }: Theme) => css` font-size: 5rem; `; -const label = css` +const labelStyle = css` padding: 0 1rem; `; -const input = ({ colors }: Theme) => css` +const inputStyle = ({ colors }: Theme) => css` padding: 3rem; width: 100%; @@ -28,4 +28,4 @@ const input = ({ colors }: Theme) => css` font-size: inherit; `; -export { fieldset, label, input }; +export { fieldsetStyle, labelStyle, inputStyle }; diff --git a/frontend/src/components/@common/Fieldset/Fieldset.tsx b/frontend/src/components/@common/Fieldset/Fieldset.tsx index 2a1994c9..1a99c745 100644 --- a/frontend/src/components/@common/Fieldset/Fieldset.tsx +++ b/frontend/src/components/@common/Fieldset/Fieldset.tsx @@ -3,7 +3,7 @@ import { forwardRef } from 'react'; import { FieldsetCssPropType } from '@/@types'; -import { fieldset, input, label } from './Fieldset.styles'; +import { fieldsetStyle, inputStyle, labelStyle } from './Fieldset.styles'; interface FieldsetProps extends React.HTMLAttributes { type?: string; @@ -27,16 +27,16 @@ function Fieldset({ const theme = useTheme(); return ( -
    +
    {labelText && ( -