From 06b86d68b888c816bb4fa463a951e3201c7413dc Mon Sep 17 00:00:00 2001 From: sycha Date: Mon, 22 Nov 2021 14:15:38 +0900 Subject: [PATCH 01/81] =?UTF-8?q?[Docs]=20Swagger=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/package.json | 11 +- backend/src/index.ts | 7 + backend/src/swagger/openapi.yaml | 11 + backend/src/swagger/paths/auth.yaml | 0 backend/src/swagger/paths/chat.yaml | 0 backend/src/swagger/paths/index.yaml | 10 + backend/src/swagger/paths/schedule.yaml | 0 backend/src/swagger/paths/team.yaml | 0 backend/src/swagger/paths/user.yaml | 0 backend/src/swagger/swagger.yaml | 11 + backend/yarn.lock | 261 +++++++++++++++++++++++- 11 files changed, 306 insertions(+), 5 deletions(-) create mode 100644 backend/src/swagger/openapi.yaml create mode 100644 backend/src/swagger/paths/auth.yaml create mode 100644 backend/src/swagger/paths/chat.yaml create mode 100644 backend/src/swagger/paths/index.yaml create mode 100644 backend/src/swagger/paths/schedule.yaml create mode 100644 backend/src/swagger/paths/team.yaml create mode 100644 backend/src/swagger/paths/user.yaml create mode 100644 backend/src/swagger/swagger.yaml diff --git a/backend/package.json b/backend/package.json index 06c7da8..0290606 100644 --- a/backend/package.json +++ b/backend/package.json @@ -4,7 +4,9 @@ "private": true, "scripts": { "start": "nodemon --exec ts-node -r tsconfig-paths/register src/index.ts", - "lint": "eslint src" + "lint": "eslint src", + "api-docs": "swagger-cli bundle src/swagger/openapi.yaml --outfile src/swagger/swagger.yaml --type yaml", + "prestart": "yarn run api-docs" }, "dependencies": { "bcrypt": "^5.0.1", @@ -24,8 +26,11 @@ "redis": "^3.1.2", "reflect-metadata": "^0.1.13", "socket.io": "^4.3.1", + "swagger-cli": "^4.0.4", + "swagger-ui-express": "^4.1.6", "typeorm": "^0.2.38", - "uuid": "^8.3.2" + "uuid": "^8.3.2", + "yamljs": "^0.3.0" }, "devDependencies": { "@types/bcrypt": "^5.0.0", @@ -37,7 +42,9 @@ "@types/passport-github": "^1.1.6", "@types/passport-local": "^1.0.34", "@types/redis": "^2.8.32", + "@types/swagger-ui-express": "^4.1.3", "@types/uuid": "^8.3.1", + "@types/yamljs": "^0.2.31", "@typescript-eslint/eslint-plugin": "^5.2.0", "@typescript-eslint/parser": "^5.2.0", "dotenv": "^10.0.0", diff --git a/backend/src/index.ts b/backend/src/index.ts index 6293ac0..48f6d35 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -13,20 +13,26 @@ import { initStrategy } from './passport'; import { Namespace, Server } from 'socket.io'; import socketInit from './sockets'; +import swaggerUi from 'swagger-ui-express'; +import YAML from 'yamljs'; + import userRouter from '@routes/user-router'; import authRouter from '@routes/auth-router'; import scheduleRouter from '@routes/schedule-router'; import teamRouter from '@routes/team-router'; import chatRouter from '@routes/chat-router'; +import path from 'path'; class App { app: express.Application; server: any; // Server from http? https? port: string; + swaggerSpec: any; constructor() { this.app = express(); this.port = process.env.PORT || '4000'; + this.swaggerSpec = YAML.load(path.join(__dirname, './swagger/swagger.yaml')) this.config(); this.middleware(); this.route(); @@ -59,6 +65,7 @@ class App { this.app.use('/api/schedule', scheduleRouter); this.app.use('/api/team', teamRouter); this.app.use('/api/chat', chatRouter); + this.app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(this.swaggerSpec)) } listen() { diff --git a/backend/src/swagger/openapi.yaml b/backend/src/swagger/openapi.yaml new file mode 100644 index 0000000..d5ac02c --- /dev/null +++ b/backend/src/swagger/openapi.yaml @@ -0,0 +1,11 @@ +openapi: '3.0.0' +info: + version: 1.0.0 + title: BoostTeams API docs + description: BoostTeams의 API 문서입니다 + license: + name: MIT +servers: + - url: http://localhost:4000/ +paths: + $ref: './paths/index.yaml' diff --git a/backend/src/swagger/paths/auth.yaml b/backend/src/swagger/paths/auth.yaml new file mode 100644 index 0000000..e69de29 diff --git a/backend/src/swagger/paths/chat.yaml b/backend/src/swagger/paths/chat.yaml new file mode 100644 index 0000000..e69de29 diff --git a/backend/src/swagger/paths/index.yaml b/backend/src/swagger/paths/index.yaml new file mode 100644 index 0000000..71eb404 --- /dev/null +++ b/backend/src/swagger/paths/index.yaml @@ -0,0 +1,10 @@ +/api/auth: + $ref: './auth.yaml' +/api/chat: + $ref: './chat.yaml' +/api/schedule: + $ref: './schedule.yaml' +/api/team: + $ref: './team.yaml' +/api/user: + $ref: './user.yaml' diff --git a/backend/src/swagger/paths/schedule.yaml b/backend/src/swagger/paths/schedule.yaml new file mode 100644 index 0000000..e69de29 diff --git a/backend/src/swagger/paths/team.yaml b/backend/src/swagger/paths/team.yaml new file mode 100644 index 0000000..e69de29 diff --git a/backend/src/swagger/paths/user.yaml b/backend/src/swagger/paths/user.yaml new file mode 100644 index 0000000..e69de29 diff --git a/backend/src/swagger/swagger.yaml b/backend/src/swagger/swagger.yaml new file mode 100644 index 0000000..0702465 --- /dev/null +++ b/backend/src/swagger/swagger.yaml @@ -0,0 +1,11 @@ +openapi: 3.0.0 +info: + version: 1.0.0 + title: BoostTeams API docs + description: BoostTeams의 API 문서입니다 + license: + name: MIT +servers: + - url: 'http://localhost:4000/' +paths: + /api/auth: ! '' diff --git a/backend/yarn.lock b/backend/yarn.lock index 08745a8..9046218 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -2,6 +2,48 @@ # yarn lockfile v1 +"@apidevtools/json-schema-ref-parser@^9.0.6": + version "9.0.9" + resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b" + integrity sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w== + dependencies: + "@jsdevtools/ono" "^7.1.3" + "@types/json-schema" "^7.0.6" + call-me-maybe "^1.0.1" + js-yaml "^4.1.0" + +"@apidevtools/openapi-schemas@^2.0.4": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz#9fa08017fb59d80538812f03fc7cac5992caaa17" + integrity sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ== + +"@apidevtools/swagger-cli@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@apidevtools/swagger-cli/-/swagger-cli-4.0.4.tgz#c645c291f56e4add583111aca9edeee23d60fa10" + integrity sha512-hdDT3B6GLVovCsRZYDi3+wMcB1HfetTU20l2DC8zD3iFRNMC6QNAZG5fo/6PYeHWBEv7ri4MvnlKodhNB0nt7g== + dependencies: + "@apidevtools/swagger-parser" "^10.0.1" + chalk "^4.1.0" + js-yaml "^3.14.0" + yargs "^15.4.1" + +"@apidevtools/swagger-methods@^3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz#b789a362e055b0340d04712eafe7027ddc1ac267" + integrity sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg== + +"@apidevtools/swagger-parser@^10.0.1": + version "10.0.3" + resolved "https://registry.yarnpkg.com/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz#32057ae99487872c4dd96b314a1ab4b95d89eaf5" + integrity sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g== + dependencies: + "@apidevtools/json-schema-ref-parser" "^9.0.6" + "@apidevtools/openapi-schemas" "^2.0.4" + "@apidevtools/swagger-methods" "^3.0.2" + "@jsdevtools/ono" "^7.1.3" + call-me-maybe "^1.0.1" + z-schema "^5.0.1" + "@cspotcode/source-map-consumer@0.8.0": version "0.8.0" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" @@ -43,6 +85,11 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@jsdevtools/ono@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" + integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== + "@mapbox/node-pre-gyp@^1.0.0": version "1.0.6" resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.6.tgz#f859d601a210537e27530f363028cde56e0cf962" @@ -177,7 +224,7 @@ "@types/qs" "*" "@types/serve-static" "*" -"@types/json-schema@^7.0.9": +"@types/json-schema@^7.0.6", "@types/json-schema@^7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== @@ -278,11 +325,24 @@ "@types/mime" "^1" "@types/node" "*" +"@types/swagger-ui-express@^4.1.3": + version "4.1.3" + resolved "https://registry.yarnpkg.com/@types/swagger-ui-express/-/swagger-ui-express-4.1.3.tgz#7adbbbf5343b45869debef1e9ff39c9ba73e380f" + integrity sha512-jqCjGU/tGEaqIplPy3WyQg+Nrp6y80DCFnDEAvVKWkJyv0VivSSDCChkppHRHAablvInZe6pijDFMnavtN0vqA== + dependencies: + "@types/express" "*" + "@types/serve-static" "*" + "@types/uuid@^8.3.1": version "8.3.1" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.1.tgz#1a32969cf8f0364b3d8c8af9cc3555b7805df14f" integrity sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg== +"@types/yamljs@^0.2.31": + version "0.2.31" + resolved "https://registry.yarnpkg.com/@types/yamljs/-/yamljs-0.2.31.tgz#b1a620b115c96db7b3bfdf0cf54aee0c57139245" + integrity sha512-QcJ5ZczaXAqbVD3o8mw/mEBhRvO5UAdTtbvgwL/OgoWubvNBh6/MxLBAigtcgIFaq3shon9m3POIxQaLQt4fxQ== + "@types/zen-observable@0.8.3": version "0.8.3" resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.3.tgz#781d360c282436494b32fe7d9f7f8e64b3118aa3" @@ -468,6 +528,13 @@ arg@^4.1.0: resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== +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" @@ -632,11 +699,21 @@ call-bind@^1.0.0, call-bind@^1.0.2: 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 sha1-JtII6onje1y95gJQoV8DHBak1ms= + 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== +camelcase@^5.0.0: + 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.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.1.tgz#250fd350cfd555d0d2160b1d51510eaf8326e86e" @@ -692,6 +769,15 @@ cli-highlight@^2.1.11: parse5-htmlparser2-tree-adapter "^6.0.0" yargs "^16.0.0" +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -725,6 +811,11 @@ color-support@^1.1.2: resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== +commander@^2.7.1: + 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== + component-emitter@~1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -848,6 +939,11 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" @@ -1221,6 +1317,11 @@ espree@^9.0.0: acorn-jsx "^5.3.1" eslint-visitor-keys "^3.0.0" +esprima@^4.0.0: + 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" @@ -1363,6 +1464,14 @@ find-up@^2.1.0: dependencies: locate-path "^2.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" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -1435,7 +1544,7 @@ generate-function@^2.3.1: dependencies: is-property "^1.0.2" -get-caller-file@^2.0.5: +get-caller-file@^2.0.1, 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== @@ -1485,7 +1594,7 @@ glob-parent@^6.0.1: dependencies: is-glob "^4.0.3" -glob@^7.1.3, glob@^7.1.6: +glob@^7.0.5, glob@^7.1.3, glob@^7.1.6: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -1875,6 +1984,14 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= +js-yaml@^3.14.0: + 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.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" @@ -1967,6 +2084,18 @@ locate-path@^2.0.0: p-locate "^2.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" + +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -1977,6 +2106,11 @@ lodash.isboolean@^3.0.3: resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= + lodash.isinteger@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" @@ -2355,6 +2489,13 @@ p-limit@^1.1.0: dependencies: p-try "^1.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-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -2362,11 +2503,23 @@ p-locate@^2.0.0: dependencies: p-limit "^1.1.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-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= +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== + package-json@^6.3.0: version "6.5.0" resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" @@ -2449,6 +2602,11 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +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" @@ -2663,6 +2821,11 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -2855,6 +3018,11 @@ socket.io@^4.3.1: socket.io-adapter "~2.3.2" socket.io-parser "~4.0.4" +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + sqlstring@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.2.tgz#cdae7169389a1375b18e885f2e60b3e460809514" @@ -2953,6 +3121,25 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +swagger-cli@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/swagger-cli/-/swagger-cli-4.0.4.tgz#c3f0b94277073c776b9bcc3ae7507b372f3ff414" + integrity sha512-Cp8YYuLny3RJFQ4CvOBTaqmOOgYsem52dPx1xM5S4EUWFblIh2Q8atppMZvXKUr1e9xH5RwipYpmdUzdPcxWcA== + dependencies: + "@apidevtools/swagger-cli" "4.0.4" + +swagger-ui-dist@^3.18.1: + version "3.52.5" + resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-3.52.5.tgz#9aa8101a2be751f5145195b9e048bc21b12fac60" + integrity sha512-8z18eX8G/jbTXYzyNIaobrnD7PSN7yU/YkSasMmajrXtw0FGS64XjrKn5v37d36qmU3o1xLeuYnktshRr7uIFw== + +swagger-ui-express@^4.1.6: + version "4.1.6" + resolved "https://registry.yarnpkg.com/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz#682294af3d5c70f74a1fa4d6a9b503a9ee55ea82" + integrity sha512-Xs2BGGudvDBtL7RXcYtNvHsFtP1DBFPMJFRxHe5ez/VG/rzVOEjazJOOSc/kSCyxreCTKfJrII6MJlL9a6t8vw== + dependencies: + swagger-ui-dist "^3.18.1" + tar@^6.1.11: version "6.1.11" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" @@ -3193,6 +3380,11 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== +validator@^13.7.0: + version "13.7.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857" + integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw== + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -3222,6 +3414,11 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -3248,6 +3445,15 @@ word-wrap@^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== +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -3295,6 +3501,11 @@ xmlbuilder@~11.0.0: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== +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" @@ -3310,11 +3521,44 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yamljs@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/yamljs/-/yamljs-0.3.0.tgz#dc060bf267447b39f7304e9b2bfbe8b5a7ddb03b" + integrity sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ== + dependencies: + argparse "^1.0.7" + glob "^7.0.5" + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^20.2.2: 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@^15.4.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + yargs@^16.0.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" @@ -3346,6 +3590,17 @@ yn@3.1.1: resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== +z-schema@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/z-schema/-/z-schema-5.0.2.tgz#f410394b2c9fcb9edaf6a7511491c0bb4e89a504" + integrity sha512-40TH47ukMHq5HrzkeVE40Ad7eIDKaRV2b+Qpi2prLc9X9eFJFzV7tMe5aH12e6avaSS/u5l653EQOv+J9PirPw== + dependencies: + lodash.get "^4.4.2" + lodash.isequal "^4.5.0" + validator "^13.7.0" + optionalDependencies: + commander "^2.7.1" + zen-observable-ts@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz#2d1aa9d79b87058e9b75698b92791c1838551f83" From 78231b34ec141cf5380ef94eee3caa40c1f88986 Mon Sep 17 00:00:00 2001 From: Kang Minji Date: Mon, 22 Nov 2021 15:09:46 +0900 Subject: [PATCH 02/81] =?UTF-8?q?[Refactor]=20api=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20data=20=EC=82=AD=EC=A0=9C,=20=EB=84=A4?= =?UTF-8?q?=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 --- backend/src/services/chat-room-service.ts | 10 ++++++---- frontend/src/components/Chat/ChatContent/index.tsx | 2 +- frontend/src/types/chat.ts | 3 +-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/backend/src/services/chat-room-service.ts b/backend/src/services/chat-room-service.ts index 6d95e23..943b4da 100644 --- a/backend/src/services/chat-room-service.ts +++ b/backend/src/services/chat-room-service.ts @@ -20,7 +20,7 @@ class ChatRoomService { } async createChatRoom(chatRoomInfo: ChatRoomInfoType) { - const { team_id, chat_room_name, user_id_list } = chatRoomInfo; + const { team_id, chat_room_name, user_list } = chatRoomInfo; const newChatRoom = await this.chatRoomRepository .createQueryBuilder() .insert() @@ -30,7 +30,7 @@ class ChatRoomService { if (!newChatRoom) throw new Error('채팅방 생성 오류'); const chat_room_id = newChatRoom.raw.insertId; - const chatUsers = user_id_list.map((user) => { + const chatUsers = user_list.map((user) => { return { user_id: user.user_id, chat_room_id }; }); const addUserResult = await this.chatRoomUserRepository @@ -40,12 +40,14 @@ class ChatRoomService { .values(chatUsers) .execute(); if (!addUserResult) throw new Error('채팅방 유저 초대 오류'); - return { chat_room_id, chat_room_name, user_id_list }; + return { chat_room_id, chat_room_name, user_list }; } async getChatRooms(teamId: number, userId: number) { const chatRoomsResult = await this.chatRoomRepository .createQueryBuilder('chat_room') + .select('chat_room.chat_room_id') + .addSelect('chat_room.chat_room_name') .innerJoin('chat_room.chat_room_users', 'chat_room_user') .where('chat_room.team_id = :teamId', { teamId }) .andWhere('chat_room_user.user_id =:userId', { userId }) @@ -62,7 +64,7 @@ interface UserIdType { interface ChatRoomInfoType { team_id: number; chat_room_name: string; - user_id_list: UserIdType[]; + user_list: UserIdType[]; } export default ChatRoomService; diff --git a/frontend/src/components/Chat/ChatContent/index.tsx b/frontend/src/components/Chat/ChatContent/index.tsx index 5f4b049..b51b880 100644 --- a/frontend/src/components/Chat/ChatContent/index.tsx +++ b/frontend/src/components/Chat/ChatContent/index.tsx @@ -36,7 +36,7 @@ const ChatContent: React.FC = ({ teamId, chatMode, inviteUsers, setChatMo const roomInfo = { team_id: teamId, chat_room_name: chatRoomName, - user_id_list: [...userIdList, { user_id: myInfo.id }], + user_list: [...userIdList, { user_id: myInfo.id }], }; const newChatRoomInfo = await createChatRoom(roomInfo); if (!newChatRoomInfo) return; diff --git a/frontend/src/types/chat.ts b/frontend/src/types/chat.ts index d9b61c3..1fe4d2f 100644 --- a/frontend/src/types/chat.ts +++ b/frontend/src/types/chat.ts @@ -42,12 +42,11 @@ export interface TeamUsersType { export interface ChatRoomReqType { team_id: number; chat_room_name: string; - user_id_list: { user_id: number }[]; + user_list: { user_id: number }[]; } export interface ChatRoomResType { chat_room_id: number; - team_id: number; chat_room_name: string; } From 38c50999d0e928f34f8ad4f56034bb1e4ac561d0 Mon Sep 17 00:00:00 2001 From: Kang Minji Date: Mon, 22 Nov 2021 15:11:03 +0900 Subject: [PATCH 03/81] =?UTF-8?q?[Feat]=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EA=B0=80=EC=A0=B8=EC=98=A4=EA=B8=B0=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 채팅방 정보 (유저 리스트) 를 가져오는 api를 구현하였습니다. --- backend/src/controllers/chat-controller.ts | 10 ++++++++++ backend/src/routes/chat-router.ts | 1 + backend/src/services/chat-room-service.ts | 18 +++++++++++++++--- frontend/src/apis/chat.ts | 5 ++++- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/backend/src/controllers/chat-controller.ts b/backend/src/controllers/chat-controller.ts index 8b35005..b4bee84 100644 --- a/backend/src/controllers/chat-controller.ts +++ b/backend/src/controllers/chat-controller.ts @@ -21,6 +21,16 @@ const ChatController = { } catch (err) { res.sendStatus(409); } + }, + + async getChatRoomInfo(req: Request, res: Response) { + try { + const { chatRoomId } = req.params; + const chatRoomInfo = await ChatRoomService.getInstance().getChatRoomInfo(chatRoomId); + res.status(200).json(chatRoomInfo); + } catch (err) { + res.sendStatus(409); + } } }; diff --git a/backend/src/routes/chat-router.ts b/backend/src/routes/chat-router.ts index 91c0079..e7179f5 100644 --- a/backend/src/routes/chat-router.ts +++ b/backend/src/routes/chat-router.ts @@ -5,5 +5,6 @@ const router = express.Router(); router.post('/room', ChatController.createChatRoom); router.get('/room', ChatController.getChatRooms); +router.get('/room/:chatRoomId', ChatController.getChatRoomInfo); export default router; diff --git a/backend/src/services/chat-room-service.ts b/backend/src/services/chat-room-service.ts index 943b4da..c553350 100644 --- a/backend/src/services/chat-room-service.ts +++ b/backend/src/services/chat-room-service.ts @@ -44,7 +44,7 @@ class ChatRoomService { } async getChatRooms(teamId: number, userId: number) { - const chatRoomsResult = await this.chatRoomRepository + const chatRooms = await this.chatRoomRepository .createQueryBuilder('chat_room') .select('chat_room.chat_room_id') .addSelect('chat_room.chat_room_name') @@ -52,8 +52,20 @@ class ChatRoomService { .where('chat_room.team_id = :teamId', { teamId }) .andWhere('chat_room_user.user_id =:userId', { userId }) .getMany(); - if (!chatRoomsResult) throw new Error('채팅방 목록 불러오기 오류'); - return { chat_rooms: chatRoomsResult }; + if (!chatRooms) throw new Error('채팅방 목록 불러오기 오류'); + return { chat_rooms: chatRooms }; + } + + async getChatRoomInfo(chatRoomId) { + const chatRoomInfo = await this.chatRoomRepository + .createQueryBuilder('chat_room') + .select('chat_room.chat_room_id') + .addSelect('chat_room_user.user_id') + .innerJoin('chat_room.chat_room_users', 'chat_room_user') + .where('chat_room.chat_room_id = :chatRoomId', { chatRoomId }) + .getOne(); + if (!chatRoomInfo) throw new Error('채팅방 정보 불러오기 오류'); + return chatRoomInfo; } } diff --git a/frontend/src/apis/chat.ts b/frontend/src/apis/chat.ts index 6edf691..24a5e2a 100644 --- a/frontend/src/apis/chat.ts +++ b/frontend/src/apis/chat.ts @@ -53,7 +53,10 @@ export const getChatRoomInfo = async (chatRoomId: number): Promise { + return { userId: user.user_id }; + }); + return { chatRoomId: data.chat_room_id, userList }; } catch (err) { toast.error('😣 채팅방 정보 가져오기에 실패하였습니다!'); return undefined; From b45c76f28ae0a26fc8b7b49aa11c6fe1cb8c1332 Mon Sep 17 00:00:00 2001 From: Kang Minji Date: Mon, 22 Nov 2021 15:13:24 +0900 Subject: [PATCH 04/81] =?UTF-8?q?[Style]=20=ED=8C=80=20=EC=86=8C=EC=BC=93?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=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 --- backend/src/sockets/team.ts | 38 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/backend/src/sockets/team.ts b/backend/src/sockets/team.ts index fabc851..01eba31 100644 --- a/backend/src/sockets/team.ts +++ b/backend/src/sockets/team.ts @@ -5,21 +5,21 @@ interface UserType { userId: number; } -const initTeam = (socket: Socket): void => { - const setUserStatusToOnline = (teamId: number, userId: number, socketId: string): void => { - if (!onlineUsersByTeam[teamId]) onlineUsersByTeam[teamId] = [{ userId }]; - else { - const users = onlineUsersByTeam[teamId].filter((user: UserType) => user.userId !== userId); - onlineUsersByTeam[teamId] = [...users, { userId }]; - } - onlineUsersInfo[socketId] = { teamId, userId }; - }; +const setUserStatusToOnline = (teamId: number, userId: number, socketId: string): void => { + if (!onlineUsersByTeam[teamId]) onlineUsersByTeam[teamId] = [{ userId }]; + else { + const users = onlineUsersByTeam[teamId].filter((user: UserType) => user.userId !== userId); + onlineUsersByTeam[teamId] = [...users, { userId }]; + } + onlineUsersInfo[socketId] = { teamId, userId }; +}; - const setUserStatusToOffline = (teamId: number, userId: number, socketId: string): void => { - onlineUsersByTeam[teamId] = onlineUsersByTeam[teamId].filter((user: UserType) => user.userId !== userId); - delete onlineUsersInfo[socketId]; - }; +const setUserStatusToOffline = (teamId: number, userId: number, socketId: string): void => { + onlineUsersByTeam[teamId] = onlineUsersByTeam[teamId].filter((user: UserType) => user.userId !== userId); + delete onlineUsersInfo[socketId]; +}; +const initTeam = (socket: Socket): void => { const sendOnlineUsers = (socket: Socket, teamId: number): void => { socket.emit('online users', { onlineUsers: onlineUsersByTeam[teamId] }); }; @@ -28,6 +28,12 @@ const initTeam = (socket: Socket): void => { socket.to('users').emit('online users', { onlineUsers: onlineUsersByTeam[teamId] }); }; + socket.on('enter users room', () => { + const { teamId } = onlineUsersInfo[socket.id]; + socket.join('users'); + sendOnlineUsers(socket, teamId); + }); + socket.on('leave users room', () => { socket.leave('users'); }); @@ -37,12 +43,6 @@ const initTeam = (socket: Socket): void => { sendOnlineUsersToRoom(socket, teamId); }); - socket.on('enter users room', () => { - const { teamId } = onlineUsersInfo[socket.id]; - socket.join('users'); - sendOnlineUsers(socket, teamId); - }); - socket.on('disconnect', () => { const { teamId, userId } = onlineUsersInfo[socket.id]; setUserStatusToOffline(teamId, userId, socket.id); From 89a5feca5281c1c507182a45e00cfd3b04562d2c Mon Sep 17 00:00:00 2001 From: Kang Minji Date: Mon, 22 Nov 2021 15:30:13 +0900 Subject: [PATCH 05/81] =?UTF-8?q?[Style]=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 --- backend/src/controllers/chat-controller.ts | 4 ++-- backend/src/routes/chat-router.ts | 2 +- backend/src/services/chat-room-service.ts | 4 ++-- frontend/src/apis/chat.ts | 6 +++--- .../src/components/Chat/ChatContent/index.tsx | 2 +- frontend/src/components/Chat/ChatHeader/index.tsx | 4 ++-- .../src/components/Chat/ChatSidebar/index.tsx | 2 +- frontend/src/pages/ChatPage/index.tsx | 6 +++--- frontend/src/stores/chat.ts | 10 +++++----- frontend/src/types/chat.ts | 15 ++++++++------- 10 files changed, 28 insertions(+), 27 deletions(-) diff --git a/backend/src/controllers/chat-controller.ts b/backend/src/controllers/chat-controller.ts index b4bee84..35ae4b2 100644 --- a/backend/src/controllers/chat-controller.ts +++ b/backend/src/controllers/chat-controller.ts @@ -23,10 +23,10 @@ const ChatController = { } }, - async getChatRoomInfo(req: Request, res: Response) { + async getChatRoomUsers(req: Request, res: Response) { try { const { chatRoomId } = req.params; - const chatRoomInfo = await ChatRoomService.getInstance().getChatRoomInfo(chatRoomId); + const chatRoomInfo = await ChatRoomService.getInstance().getChatRoomUsers(chatRoomId); res.status(200).json(chatRoomInfo); } catch (err) { res.sendStatus(409); diff --git a/backend/src/routes/chat-router.ts b/backend/src/routes/chat-router.ts index e7179f5..49e54eb 100644 --- a/backend/src/routes/chat-router.ts +++ b/backend/src/routes/chat-router.ts @@ -5,6 +5,6 @@ const router = express.Router(); router.post('/room', ChatController.createChatRoom); router.get('/room', ChatController.getChatRooms); -router.get('/room/:chatRoomId', ChatController.getChatRoomInfo); +router.get('/room/:chatRoomId', ChatController.getChatRoomUsers); export default router; diff --git a/backend/src/services/chat-room-service.ts b/backend/src/services/chat-room-service.ts index c553350..f8df74d 100644 --- a/backend/src/services/chat-room-service.ts +++ b/backend/src/services/chat-room-service.ts @@ -56,7 +56,7 @@ class ChatRoomService { return { chat_rooms: chatRooms }; } - async getChatRoomInfo(chatRoomId) { + async getChatRoomUsers(chatRoomId) { const chatRoomInfo = await this.chatRoomRepository .createQueryBuilder('chat_room') .select('chat_room.chat_room_id') @@ -64,7 +64,7 @@ class ChatRoomService { .innerJoin('chat_room.chat_room_users', 'chat_room_user') .where('chat_room.chat_room_id = :chatRoomId', { chatRoomId }) .getOne(); - if (!chatRoomInfo) throw new Error('채팅방 정보 불러오기 오류'); + if (!chatRoomInfo) throw new Error('채팅방 유저 가져오기 오류'); return chatRoomInfo; } } diff --git a/frontend/src/apis/chat.ts b/frontend/src/apis/chat.ts index 24a5e2a..d173881 100644 --- a/frontend/src/apis/chat.ts +++ b/frontend/src/apis/chat.ts @@ -4,7 +4,7 @@ import { ChatRoomReqType, ChatRoomResType, ChatRoomType, - ChatRoomInfoType, + ChatRoomUsersType, MessageList, ChatRoomsType, } from '@src/types/chat'; @@ -48,7 +48,7 @@ export const getChatRooms = async (teamId: number, userId: number): Promise => { +export const getChatRoomUsers = async (chatRoomId: number): Promise => { try { const res = await fetchApi.get(`/api/chat/room/${chatRoomId}`); if (res.status === 409) throw new Error(); @@ -59,7 +59,7 @@ export const getChatRoomInfo = async (chatRoomId: number): Promise = ({ teamId, chatMode, inviteUsers, setChatMo inputRef.current.value = ''; initInviteUser(); setTeamUsersTrigger((trigger) => trigger + 1); - setCurrentChatRoom({ currentChatRoom: newChatRoomInfo.chatRoomId }); + setCurrentChatRoom({ currChatRoomId: newChatRoomInfo.chatRoomId }); setChatModeToChat(); }; diff --git a/frontend/src/components/Chat/ChatHeader/index.tsx b/frontend/src/components/Chat/ChatHeader/index.tsx index 461c434..4939828 100644 --- a/frontend/src/components/Chat/ChatHeader/index.tsx +++ b/frontend/src/components/Chat/ChatHeader/index.tsx @@ -17,7 +17,7 @@ interface Props { } const ChatHeader: React.FC = ({ teamId, chatMode, inviteUsers, addInviteUser, deleteInviteUser }) => { - const currChatRoom = useRecoilValue(currentChatRoomState).currentChatRoom; + const { currChatRoomId } = useRecoilValue(currentChatRoomState); return ( @@ -29,7 +29,7 @@ const ChatHeader: React.FC = ({ teamId, chatMode, inviteUsers, addInviteU deleteInviteUser={deleteInviteUser} /> ) : ( - currChatRoom !== -1 &&
+ currChatRoomId !== -1 &&
)} ); diff --git a/frontend/src/components/Chat/ChatSidebar/index.tsx b/frontend/src/components/Chat/ChatSidebar/index.tsx index 82ce6f9..d57acb4 100644 --- a/frontend/src/components/Chat/ChatSidebar/index.tsx +++ b/frontend/src/components/Chat/ChatSidebar/index.tsx @@ -23,7 +23,7 @@ const ChatSidebar: React.FC = ({ teamId, setChatModeToNone, setChatModeTo const handleEnterChatRoom = (chatRoomId: number) => { setCurrentChatRoom(() => { - return { currentChatRoom: chatRoomId }; + return { currChatRoomId: chatRoomId }; }); setChatModeToChat(); }; diff --git a/frontend/src/pages/ChatPage/index.tsx b/frontend/src/pages/ChatPage/index.tsx index 9865209..ac1ac54 100644 --- a/frontend/src/pages/ChatPage/index.tsx +++ b/frontend/src/pages/ChatPage/index.tsx @@ -1,6 +1,6 @@ import React, { useState, useReducer, useEffect } from 'react'; import { RouteComponentProps } from 'react-router'; -import { useSetRecoilState } from 'recoil'; +import { useResetRecoilState } from 'recoil'; import { UserIdType, ChatModeType } from '@src/types/chat'; import { currentChatRoomState } from '@stores/chat'; @@ -32,7 +32,7 @@ const ChatPage: React.FC = ({ match }) => { const teamId = Number(match.params.teamId); const [chatMode, setChatMode] = useState('none'); const [inviteUsers, dispatchInviteUsers] = useReducer(inviteUsersReducer, []); - const setCurrentChatRoom = useSetRecoilState(currentChatRoomState); + const resetCurrentChatRoom = useResetRecoilState(currentChatRoomState); const setChatModeToNone = () => setChatMode('none'); const setChatModeToCreate = () => setChatMode('create'); @@ -43,7 +43,7 @@ const ChatPage: React.FC = ({ match }) => { const initInviteUser = () => dispatchInviteUsers({ type: 'INIT' }); useEffect(() => { - setCurrentChatRoom({ currentChatRoom: -1 }); + resetCurrentChatRoom(); setChatModeToNone(); initInviteUser(); }, [teamId]); diff --git a/frontend/src/stores/chat.ts b/frontend/src/stores/chat.ts index 821f13e..aae7b09 100644 --- a/frontend/src/stores/chat.ts +++ b/frontend/src/stores/chat.ts @@ -1,11 +1,11 @@ import { atom, selector, selectorFamily } from 'recoil'; -import { getChatRoomInfo, getChatRooms } from '@apis/chat'; +import { getChatRooms, getChatRoomUsers } from '@apis/chat'; import { readTeamUsers } from '@apis/users'; import userState from './user'; export const currentChatRoomState = atom({ key: 'currentChatRoomState', - default: { currentChatRoom: -1 }, + default: { currChatRoomId: -1 }, }); export const chatRoomsTrigger = atom({ @@ -24,10 +24,10 @@ export const chatRoomsSelector = selectorFamily({ }, }); -export const chatRoomInfoState = selector({ - key: 'chatRoomInfoState', +export const chatRoomUsersSelector = selector({ + key: 'chatRoomUsersSelector', get: async ({ get }) => { - const data = await getChatRoomInfo(get(currentChatRoomState).currentChatRoom); + const data = await getChatRoomUsers(get(currentChatRoomState).currChatRoomId); return data; }, }); diff --git a/frontend/src/types/chat.ts b/frontend/src/types/chat.ts index 1fe4d2f..6525764 100644 --- a/frontend/src/types/chat.ts +++ b/frontend/src/types/chat.ts @@ -14,7 +14,7 @@ export interface UserIdType { userId: number; } -export interface ChatRoomInfoType { +export interface ChatRoomUsersType { chatRoomId: number; userList: UserIdType[]; } @@ -33,6 +33,7 @@ export interface TeamUserType { name: string; email: string; color: number; + chatRoomId: number; } export interface TeamUsersType { @@ -51,10 +52,10 @@ export interface ChatRoomResType { } export const messagesEx = [ - { messageId: 1, userId: 1, content: 'hi', createdAt: new Date() }, - { messageId: 2, userId: 2, content: 'hi', createdAt: new Date() }, - { messageId: 3, userId: 3, content: 'hi', createdAt: new Date() }, - { messageId: 4, userId: 4, content: 'hi', createdAt: new Date() }, - { messageId: 5, userId: 1, content: 'hi', createdAt: new Date() }, - { messageId: 6, userId: 2, content: 'hi', createdAt: new Date() }, + { messageId: 1, userId: 1, content: 'hi', createdAt: new Date(), chatRoomId: 1 }, + { messageId: 2, userId: 2, content: 'hi', createdAt: new Date(), chatRoomId: 1 }, + { messageId: 3, userId: 3, content: 'hi', createdAt: new Date(), chatRoomId: 1 }, + { messageId: 4, userId: 4, content: 'hi', createdAt: new Date(), chatRoomId: 1 }, + { messageId: 5, userId: 1, content: 'hi', createdAt: new Date(), chatRoomId: 1 }, + { messageId: 6, userId: 2, content: 'hi', createdAt: new Date(), chatRoomId: 1 }, ]; From ea15aed0aa2bf94fa62a8c355572e666d2759e02 Mon Sep 17 00:00:00 2001 From: Kang Minji Date: Mon, 22 Nov 2021 15:30:49 +0900 Subject: [PATCH 06/81] =?UTF-8?q?[Feat]=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=EC=9D=B8=EC=9B=90=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 리코일 chatRoomUsers 값을 이용하여 표시하였다. --- frontend/src/components/Chat/ChatHeader/Header.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/Chat/ChatHeader/Header.tsx b/frontend/src/components/Chat/ChatHeader/Header.tsx index 54b4295..d80c685 100644 --- a/frontend/src/components/Chat/ChatHeader/Header.tsx +++ b/frontend/src/components/Chat/ChatHeader/Header.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { useRecoilValue } from 'recoil'; -import { currentChatRoomState, chatRoomsSelector } from '@stores/chat'; +import { currentChatRoomState, chatRoomsSelector, chatRoomUsersSelector } from '@stores/chat'; import { ChatRoomsType } from '@src/types/chat'; import { FaUserPlus, FaPen } from 'react-icons/fa'; @@ -13,25 +13,26 @@ interface Props { } const Header: React.FC = ({ teamId }) => { - const currChatRoom = useRecoilValue(currentChatRoomState).currentChatRoom; + const { currChatRoomId } = useRecoilValue(currentChatRoomState); const chatRooms = useRecoilValue(chatRoomsSelector(teamId)); + const chatRoomUsers = useRecoilValue(chatRoomUsersSelector).userList; return ( -

{chatRooms[currChatRoom].chatRoomName}

+

{chatRooms[currChatRoomId].chatRoomName}

- 0 + {chatRoomUsers.length}
); From 6345e79ec94f9b5058136f5f04dc60dcffdc99e3 Mon Sep 17 00:00:00 2001 From: Kang Minji Date: Mon, 22 Nov 2021 15:42:45 +0900 Subject: [PATCH 07/81] =?UTF-8?q?[Refactor]=20=EC=B1=84=ED=8C=85=20?= =?UTF-8?q?=EB=B0=A9=20=EB=AA=A9=EB=A1=9D=20state=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=B5=9C=EA=B7=BC=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 최근 메시지는 더 잦은 변경이 일어날 것이라 상태를 분리하였습니다. --- frontend/src/apis/chat.ts | 2 -- frontend/src/components/Chat/ChatSidebar/index.tsx | 4 ++-- frontend/src/stores/chat.ts | 6 ++++++ frontend/src/types/chat.ts | 5 ++++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/frontend/src/apis/chat.ts b/frontend/src/apis/chat.ts index d173881..fe8467d 100644 --- a/frontend/src/apis/chat.ts +++ b/frontend/src/apis/chat.ts @@ -17,7 +17,6 @@ export const createChatRoom = async (roomInfo: ChatRoomReqType): Promise = ({ teamId, setChatModeToNone, setChatModeTo

{chatRoom.chatRoomName}

{timeSince(new Date())} - {/* teamUsers[chatRoom.lastMessage.userId].name */} - {`${'이름'}: ${chatRoom.lastMessage.content}`} + {/* teamUsers[lastMessage.userId].name */} + {`${'이름'}: ${'내용'}`} ))} diff --git a/frontend/src/stores/chat.ts b/frontend/src/stores/chat.ts index aae7b09..4278dde 100644 --- a/frontend/src/stores/chat.ts +++ b/frontend/src/stores/chat.ts @@ -1,4 +1,5 @@ import { atom, selector, selectorFamily } from 'recoil'; +import { ChatRoomsLastMessageType } from '@src/types/chat'; import { getChatRooms, getChatRoomUsers } from '@apis/chat'; import { readTeamUsers } from '@apis/users'; import userState from './user'; @@ -24,6 +25,11 @@ export const chatRoomsSelector = selectorFamily({ }, }); +export const chatRoomsLastMessageState = atom({ + key: 'chatRoomsLastMessageState', + default: {} as ChatRoomsLastMessageType, +}); + export const chatRoomUsersSelector = selector({ key: 'chatRoomUsersSelector', get: async ({ get }) => { diff --git a/frontend/src/types/chat.ts b/frontend/src/types/chat.ts index 6525764..9cfde6d 100644 --- a/frontend/src/types/chat.ts +++ b/frontend/src/types/chat.ts @@ -3,13 +3,16 @@ export type ChatModeType = 'none' | 'create' | 'chat'; export interface ChatRoomType { chatRoomId: number; chatRoomName: string; - lastMessage: MessageType; } export interface ChatRoomsType { [chatRoomId: number]: ChatRoomType; } +export interface ChatRoomsLastMessageType { + [chatRoomId: number]: MessageType; +} + export interface UserIdType { userId: number; } From 88768aca5baa5bb39b66a5ef5c71a89399094f08 Mon Sep 17 00:00:00 2001 From: Kang Minji Date: Mon, 22 Nov 2021 16:01:58 +0900 Subject: [PATCH 08/81] =?UTF-8?q?[Feat]=20=EC=B1=84=ED=8C=85=EB=B0=A9=20?= =?UTF-8?q?=EC=B0=B8=EA=B0=80=20=EC=86=8C=EC=BC=93=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/sockets/chat.ts | 19 +++++++++++++++++++ backend/src/sockets/index.ts | 2 ++ frontend/src/pages/ChatPage/index.tsx | 23 ++++++++++++++++++++--- 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 backend/src/sockets/chat.ts diff --git a/backend/src/sockets/chat.ts b/backend/src/sockets/chat.ts new file mode 100644 index 0000000..4134bfd --- /dev/null +++ b/backend/src/sockets/chat.ts @@ -0,0 +1,19 @@ +import { Socket } from 'socket.io'; + +const initChat = (socket: Socket) => { + socket.on('enter chat rooms', ({ chatRooms }: { chatRooms: { chatRoomId: number }[] }) => { + chatRooms.forEach(({ chatRoomId }) => { + console.log(`join chat-${chatRoomId}`); + socket.join(`chat-${chatRoomId}`); + }); + }); + + socket.on('leave chat rooms', ({ chatRooms }: { chatRooms: { chatRoomId: number }[] }) => { + chatRooms.forEach(({ chatRoomId }) => { + console.log(`leave chat-${chatRoomId}`); + socket.leave(`chat-${chatRoomId}`); + }); + }); +}; + +export default initChat; diff --git a/backend/src/sockets/index.ts b/backend/src/sockets/index.ts index 590af4b..d704c2a 100644 --- a/backend/src/sockets/index.ts +++ b/backend/src/sockets/index.ts @@ -1,10 +1,12 @@ import { Namespace, Socket } from 'socket.io'; import initTeam from './team'; import initTeamBoard from './teamBoard'; +import initChat from './chat'; const socketInit = (namespace: Namespace): void => { namespace.on('connect', (socket: Socket) => { initTeam(socket); initTeamBoard(socket); + initChat(socket); }); }; diff --git a/frontend/src/pages/ChatPage/index.tsx b/frontend/src/pages/ChatPage/index.tsx index ac1ac54..a40bb99 100644 --- a/frontend/src/pages/ChatPage/index.tsx +++ b/frontend/src/pages/ChatPage/index.tsx @@ -1,9 +1,10 @@ -import React, { useState, useReducer, useEffect } from 'react'; +import React, { useState, useReducer, useEffect, useContext } from 'react'; import { RouteComponentProps } from 'react-router'; -import { useResetRecoilState } from 'recoil'; +import { useRecoilValue, useResetRecoilState } from 'recoil'; import { UserIdType, ChatModeType } from '@src/types/chat'; -import { currentChatRoomState } from '@stores/chat'; +import { chatRoomsSelector, currentChatRoomState } from '@stores/chat'; +import { SocketContext } from '@utils/socketContext'; import ChatTemplate from '@templates/ChatTemplate'; @@ -30,8 +31,10 @@ type Props = RouteComponentProps; const ChatPage: React.FC = ({ match }) => { const teamId = Number(match.params.teamId); + const socketRef = useContext(SocketContext); const [chatMode, setChatMode] = useState('none'); const [inviteUsers, dispatchInviteUsers] = useReducer(inviteUsersReducer, []); + const chatRooms = useRecoilValue(chatRoomsSelector(teamId)); const resetCurrentChatRoom = useResetRecoilState(currentChatRoomState); const setChatModeToNone = () => setChatMode('none'); @@ -42,12 +45,26 @@ const ChatPage: React.FC = ({ match }) => { const deleteInviteUser = (id: number) => dispatchInviteUsers({ type: 'DELETE', id }); const initInviteUser = () => dispatchInviteUsers({ type: 'INIT' }); + const chatRoomIdList = Object.keys(chatRooms).map((chatRoomId) => { + return { chatRoomId }; + }); + useEffect(() => { resetCurrentChatRoom(); setChatModeToNone(); initInviteUser(); }, [teamId]); + useEffect(() => { + if (socketRef.current) { + socketRef.current.emit('enter chat rooms', { chatRooms: chatRoomIdList }); + } + return () => { + socketRef.current.emit('leave chat rooms', { chatRooms: chatRoomIdList }); + socketRef.current.off('enter chat room'); + }; + }, [socketRef.current, teamId]); + return ( Date: Mon, 22 Nov 2021 16:27:20 +0900 Subject: [PATCH 09/81] =?UTF-8?q?[Feat]=20Redis=20API=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/redis/index.ts | 41 ++++++++++++++++++++++++++++++++++---- backend/tsconfig.path.json | 3 ++- backend/yarn.lock | 18 +++++++++++++++-- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/backend/src/redis/index.ts b/backend/src/redis/index.ts index 3d1d6ef..5b8eebf 100644 --- a/backend/src/redis/index.ts +++ b/backend/src/redis/index.ts @@ -17,10 +17,43 @@ export default class Redis { } return Redis.instance; } - get(key: string) { - console.log('redis get'); + // key === 'board' || 'chat' + // field === roomId || chatId + async get(key: string, field: string) { + return new Promise((resolve, reject) => { + Redis.client.hget(key, field, (err, obj) => { + if (err) reject(err); + else resolve(obj); + }); + }); } - set(key: string, value: any) { - console.log('redis set'); + + async set(key: string, field: string, value: any) { + return new Promise((resolve, reject) => { + Redis.client.hget(key, field, (err, obj) => { + if (err) reject(err); + else { + const updatedValue = [...JSON.parse(obj), value]; + Redis.client.hset(key, field, JSON.stringify(updatedValue), () => { + resolve(updatedValue); + }); + } + }); + }); } } + +/* +client = { + board : { + team#1 : [{postIt#1-1},{postIt#1-2},{postIt#1-3}], + team#2 : [{postIt#2-1},{postIt#2-2},{postIt#2-3}], + team#3 : [{postIt#3-1},{postIt#3-2},{postIt#3-3}], + }, + chat : { + room#1 : [{chat#1-1},{chat#1-2}], + room#2 : [{chat#2-1},{chat#2-2}], + room#3 : [{chat#3-1},{chat#3-2}], + }, +} +*/ diff --git a/backend/tsconfig.path.json b/backend/tsconfig.path.json index b07255b..3396bcb 100644 --- a/backend/tsconfig.path.json +++ b/backend/tsconfig.path.json @@ -10,7 +10,8 @@ "@repositories/*": ["src/repositories/*"], "@routes/*": ["src/routes/*"], "@services/*": ["src/services/*"], - "@sockets/*": ["src/sockets/*"] + "@sockets/*": ["src/sockets/*"], + "@redis/*": ["src/redis/*"] } } } diff --git a/backend/yarn.lock b/backend/yarn.lock index 08745a8..1481f5e 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -116,6 +116,13 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== +"@types/async-redis@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@types/async-redis/-/async-redis-1.1.2.tgz#8b44948155b9f1c709ae69ee457c8124f58ada00" + integrity sha512-iqHv95+qElhz8hKlby07LlAf8+xoHlVaUYiEZAJOh+cg4673XuWdUEW1mvbx1j7bxBWJcdzcSkLQqJq5h/AtOQ== + dependencies: + "@types/redis" "*" + "@types/bcrypt@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@types/bcrypt/-/bcrypt-5.0.0.tgz#a835afa2882d165aff5690893db314eaa98b9f20" @@ -263,7 +270,7 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== -"@types/redis@^2.8.32": +"@types/redis@*", "@types/redis@^2.8.32": version "2.8.32" resolved "https://registry.yarnpkg.com/@types/redis/-/redis-2.8.32.tgz#1d3430219afbee10f8cfa389dad2571a05ecfb11" integrity sha512-7jkMKxcGq9p242exlbsVzuJb57KqHRhNl4dHoQu2Y5v9bCAbtIXXH0R3HleSQW4CTOqpHIYUW3t6tpUj4BVQ+w== @@ -503,6 +510,13 @@ array.prototype.flat@^1.2.5: define-properties "^1.1.3" es-abstract "^1.19.0" +async-redis@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/async-redis/-/async-redis-2.0.0.tgz#478704e48e2ae7a84a7cfd55ab946f463fba9cab" + integrity sha512-cGv40n9h3gpAGMGnX1v5ncgHJ2C3TsRmK6Ekt282jVftiky3v0X13PSfnLoRix9uva7ctb2j9lwA3d2qc4KKTA== + dependencies: + redis "3.1.2" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -2624,7 +2638,7 @@ redis-parser@^3.0.0: dependencies: redis-errors "^1.0.0" -redis@^3.1.2: +redis@3.1.2, redis@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/redis/-/redis-3.1.2.tgz#766851117e80653d23e0ed536254677ab647638c" integrity sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw== From 595ad9162ec72a6bd4d90e5d15e99be07d48e3bd Mon Sep 17 00:00:00 2001 From: Kang Minji Date: Mon, 22 Nov 2021 16:46:46 +0900 Subject: [PATCH 10/81] =?UTF-8?q?[Fix]=20=EC=B1=84=ED=8C=85=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=EC=97=90=EC=84=9C=20=ED=8C=80=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=8B=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Chat/ChatHeader/index.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/Chat/ChatHeader/index.tsx b/frontend/src/components/Chat/ChatHeader/index.tsx index 4939828..b5efc8b 100644 --- a/frontend/src/components/Chat/ChatHeader/index.tsx +++ b/frontend/src/components/Chat/ChatHeader/index.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { useRecoilValue } from 'recoil'; -import { UserIdType } from '@src/types/chat'; -import { currentChatRoomState } from '@stores/chat'; +import { UserIdType, ChatRoomsType } from '@src/types/chat'; +import { currentChatRoomState, chatRoomsSelector } from '@stores/chat'; import SearchHeader from './SearchHeader'; import Header from './Header'; @@ -17,8 +17,11 @@ interface Props { } const ChatHeader: React.FC = ({ teamId, chatMode, inviteUsers, addInviteUser, deleteInviteUser }) => { + const chatRooms = useRecoilValue(chatRoomsSelector(teamId)); const { currChatRoomId } = useRecoilValue(currentChatRoomState); + const checkRoomAndTeam = () => chatRooms[currChatRoomId] !== undefined; + return ( {chatMode === 'create' ? ( @@ -29,7 +32,7 @@ const ChatHeader: React.FC = ({ teamId, chatMode, inviteUsers, addInviteU deleteInviteUser={deleteInviteUser} /> ) : ( - currChatRoomId !== -1 &&
+ checkRoomAndTeam() &&
)} ); From c505ac11a927a91a70132868a323cdc3f7beffbd Mon Sep 17 00:00:00 2001 From: LeeMir Date: Mon, 22 Nov 2021 16:51:05 +0900 Subject: [PATCH 11/81] =?UTF-8?q?[Refactor]=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EB=B0=8F=20=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 기존 PostitType을 IPostit으로 변경 후 types/ 안으로 분리하였습니다. 그리고 socketApi에 맞는 ISocketApi를 만들었습니다. any를 최대한 줄였습니다. --- .../src/components/Board/Canvas/index.tsx | 83 +++---------------- frontend/src/components/Board/Modal/index.tsx | 32 ++++--- .../src/components/Board/Postit/index.tsx | 30 +++---- frontend/src/pages/BoardPage/index.tsx | 75 ++++++++++------- .../src/templates/BoardTemplate/index.tsx | 27 +++--- frontend/src/types/board.ts | 21 +++++ 6 files changed, 125 insertions(+), 143 deletions(-) create mode 100644 frontend/src/types/board.ts diff --git a/frontend/src/components/Board/Canvas/index.tsx b/frontend/src/components/Board/Canvas/index.tsx index 3ee99f8..a975d75 100644 --- a/frontend/src/components/Board/Canvas/index.tsx +++ b/frontend/src/components/Board/Canvas/index.tsx @@ -1,52 +1,30 @@ import React from 'react'; import { Stage, Layer } from 'react-konva'; -import { PostitType } from '@pages/BoardPage'; +import { KonvaEventObject } from 'konva/lib/Node'; import { REM } from '@utils/constants'; +import { IPostit } from '@src/types/board'; +import { Dispatch, SetStateAction } from 'hoist-non-react-statics/node_modules/@types/react'; import Postit from '../Postit'; interface Props { - postits: any[]; - socketApi: any; - setPostits: (postit: PostitType[]) => void; - setModalType: (type: string) => void; - setClickedPostit: (postit: PostitType) => void; + postits: IPostit[]; + handleDrag: (e: KonvaEventObject) => void; + handleDragStart: (e: KonvaEventObject) => void; + handleDragEnd: (e: KonvaEventObject) => void; + setModalType: Dispatch>; + setClickedPostit: (postit: IPostit) => void; handleModalOpen: () => void; } const Canvas: React.FC = ({ postits, - socketApi, - setPostits, + handleDrag, + handleDragStart, + handleDragEnd, setModalType, setClickedPostit, handleModalOpen, }) => { - const handleDragStart = (e: any) => { - const id = Number(e.target.id()); - const postitList = [...postits]; - const postitIdx = postitList.findIndex((postit) => postit.id === id); - const postit = { ...postitList.splice(postitIdx, 1)[0], isDragging: true }; - postitList.push(postit); - setPostits(postitList); - }; - - const handleDragEnd = (e: any) => { - const id = Number(e.target.id()); - const postitList = [...postits]; - const postitIdx = postitList.findIndex((postit) => postit.id === id); - postitList[postitIdx] = { - ...postitList[postitIdx], - x: e.target.x(), - y: e.target.y(), - isDragging: false, - }; - setPostits(postitList); - }; - - const handleDrag = (event: any) => { - socketApi.dragPostit(event); - }; - return ( @@ -69,40 +47,3 @@ const Canvas: React.FC = ({ }; export default Canvas; - -/* -const Canvas: React.FC = ({ postits, setModalType, setClickedPostit, handleModalOpen }) => { - const socket = useContext(SocketContext); - const dragPostit = (id: number, x: number, y: number) => socket.current.emit('drag postit', { id, x, y }); - - return ( - - - { - setModalType('create'); - handleModalOpen(); - }} - text='새 포스트잇 작성' - /> - {postits.map((postit) => ( - - ))} - - - ); -}; -export default Canvas; -*/ diff --git a/frontend/src/components/Board/Modal/index.tsx b/frontend/src/components/Board/Modal/index.tsx index fad1839..9076439 100644 --- a/frontend/src/components/Board/Modal/index.tsx +++ b/frontend/src/components/Board/Modal/index.tsx @@ -1,15 +1,15 @@ import React, { useRef, useState, useEffect } from 'react'; import userState from '@stores/user'; import { useRecoilValue } from 'recoil'; -import { PostitType } from '@pages/BoardPage'; import Modal from '@components/common/Modal'; import ColorPicker from '@components/common/ColorPicker'; +import { IPostit, ISocketApi } from '@src/types/board'; import { Container, Input, Textarea, TitleContainer } from './style'; interface Props { - socketApi: any; + socketApi: ISocketApi; modalType: string; - clickedPostit: PostitType; + clickedPostit: IPostit | undefined; handleModalClose: () => void; } @@ -20,7 +20,7 @@ const CreatePostItModal: React.FC = ({ socketApi, modalType, clickedPosti const [color, setColor] = useState(0); const makePostitObj = (modalType: string, title: string, content: string) => { - if (modalType === 'update') { + if (modalType === 'update' && clickedPostit) { const updatedPostit = clickedPostit; updatedPostit.id = Number(updatedPostit.id); updatedPostit.title = title; @@ -29,16 +29,14 @@ const CreatePostItModal: React.FC = ({ socketApi, modalType, clickedPosti updatedPostit.updatedBy = user.id; return updatedPostit; } - if (modalType === 'create') { - return { - title, - color, - content, - createdBy: user.id, - updatedBy: user.id, - }; - } - return undefined; + // if (modalType === 'create') + return { + title, + color, + content, + createdBy: user.id, + updatedBy: user.id, + }; }; const handleSubmit = () => { @@ -54,7 +52,7 @@ const CreatePostItModal: React.FC = ({ socketApi, modalType, clickedPosti }; useEffect(() => { - if (modalType === 'update') { + if (modalType === 'update' && clickedPostit) { setColor(clickedPostit.color); } }, []); @@ -66,13 +64,13 @@ const CreatePostItModal: React.FC = ({ socketApi, modalType, clickedPosti