From e32bb0ae6f390158e6d30841828d90ded62983ed Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Tue, 23 Feb 2021 11:25:54 +0530 Subject: [PATCH 001/115] Trigger deployment to beta From 34a4b9c98a62e9a6df9e2d6cc0c506979602d7d5 Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Tue, 23 Feb 2021 12:24:41 +0530 Subject: [PATCH 002/115] Update dependencies --- package.json | 16 ++--- yarn.lock | 188 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 130 insertions(+), 74 deletions(-) diff --git a/package.json b/package.json index d42e0ba..079ad95 100644 --- a/package.json +++ b/package.json @@ -22,20 +22,20 @@ "@badrap/bar-of-progress": "0.1.2", "@headlessui/react": "0.3.1", "classnames": "2.2.6", - "fauna-schema-migrate": "0.1.3-beta", + "fauna-schema-migrate": "0.1.7", "faunadb": "4.1.0", "luxon": "1.26.0", "markdown-to-jsx": "7.1.1", "next": "10.0.7", "next-auth": "3.5.0", - "next-themes": "0.0.10", + "next-themes": "0.0.11", "nightwind": "1.1.6", "phosphor-react": "1.1.2", "react": "17.0.1", "react-dom": "17.0.1", - "react-hook-form": "6.15.3", + "react-hook-form": "6.15.4", "react-hot-toast": "1.0.2", - "react-query": "3.9.8", + "react-query": "3.11.0", "slugify": "1.4.7", "tabler-icons": "1.35.0" }, @@ -48,22 +48,22 @@ "@types/next-auth": "3.1.24", "@types/node": "14.14.31", "@types/react": "17.0.2", - "@typescript-eslint/eslint-plugin": "4.15.1", - "@typescript-eslint/parser": "4.15.1", + "@typescript-eslint/eslint-plugin": "4.15.2", + "@typescript-eslint/parser": "4.15.2", "autoprefixer": "10.2.4", "babel-eslint": "10.1.0", "cli-real-favicon": "0.0.8", "eslint": "7.20.0", "eslint-config-prettier": "8.0.0", "eslint-config-react-app": "6.0.0", - "eslint-plugin-flowtype": "5.2.2", + "eslint-plugin-flowtype": "5.3.0", "eslint-plugin-import": "2.22.1", "eslint-plugin-jest": "24.1.5", "eslint-plugin-jsx-a11y": "6.4.1", "eslint-plugin-prettier": "3.3.1", "eslint-plugin-react": "7.22.0", "eslint-plugin-react-hooks": "4.2.0", - "husky": ">=4.3.8", + "husky": ">=5.1.1", "lint-staged": ">=10.5.4", "npm-run-all": "4.1.5", "postcss": "8.2.6", diff --git a/yarn.lock b/yarn.lock index 27a019e..cee7418 100644 --- a/yarn.lock +++ b/yarn.lock @@ -87,6 +87,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2": + version "7.13.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.2.tgz#9511c87d2808b2cf5fb9e9c5cf0d1ab789d75499" + integrity sha512-U9plpxyudmZNYe12YI6cXyeWTWYCTq2u1h+C0XVtC3+BoiuzTh1BHlMJgxMrbKTombYkf7wQGqoxYkptFehuZw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" @@ -450,13 +457,13 @@ resolved "https://registry.yarnpkg.com/@types/yoga-layout/-/yoga-layout-1.9.2.tgz#efaf9e991a7390dc081a0b679185979a83a9639a" integrity sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw== -"@typescript-eslint/eslint-plugin@4.15.1": - version "4.15.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.1.tgz#835f64aa0a403e5e9e64c10ceaf8d05c3f015180" - integrity sha512-yW2epMYZSpNJXZy22Biu+fLdTG8Mn6b22kR3TqblVk50HGNV8Zya15WAXuQCr8tKw4Qf1BL4QtI6kv6PCkLoJw== +"@typescript-eslint/eslint-plugin@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.2.tgz#981b26b4076c62a5a55873fbef3fe98f83360c61" + integrity sha512-uiQQeu9tWl3f1+oK0yoAv9lt/KXO24iafxgQTkIYO/kitruILGx3uH+QtIAHqxFV+yIsdnJH+alel9KuE3J15Q== dependencies: - "@typescript-eslint/experimental-utils" "4.15.1" - "@typescript-eslint/scope-manager" "4.15.1" + "@typescript-eslint/experimental-utils" "4.15.2" + "@typescript-eslint/scope-manager" "4.15.2" debug "^4.1.1" functional-red-black-tree "^1.0.1" lodash "^4.17.15" @@ -464,15 +471,15 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@4.15.1": - version "4.15.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.1.tgz#d744d1ac40570a84b447f7aa1b526368afd17eec" - integrity sha512-9LQRmOzBRI1iOdJorr4jEnQhadxK4c9R2aEAsm7WE/7dq8wkKD1suaV0S/JucTL8QlYUPU1y2yjqg+aGC0IQBQ== +"@typescript-eslint/experimental-utils@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.2.tgz#5efd12355bd5b535e1831282e6cf465b9a71cf36" + integrity sha512-Fxoshw8+R5X3/Vmqwsjc8nRO/7iTysRtDqx6rlfLZ7HbT8TZhPeQqbPjTyk2RheH3L8afumecTQnUc9EeXxohQ== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.15.1" - "@typescript-eslint/types" "4.15.1" - "@typescript-eslint/typescript-estree" "4.15.1" + "@typescript-eslint/scope-manager" "4.15.2" + "@typescript-eslint/types" "4.15.2" + "@typescript-eslint/typescript-estree" "4.15.2" eslint-scope "^5.0.0" eslint-utils "^2.0.0" @@ -488,23 +495,23 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@4.15.1": - version "4.15.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.15.1.tgz#4c91a0602733db63507e1dbf13187d6c71a153c4" - integrity sha512-V8eXYxNJ9QmXi5ETDguB7O9diAXlIyS+e3xzLoP/oVE4WCAjssxLIa0mqCLsCGXulYJUfT+GV70Jv1vHsdKwtA== +"@typescript-eslint/parser@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.15.2.tgz#c804474321ef76a3955aec03664808f0d6e7872e" + integrity sha512-SHeF8xbsC6z2FKXsaTb1tBCf0QZsjJ94H6Bo51Y1aVEZ4XAefaw5ZAilMoDPlGghe+qtq7XdTiDlGfVTOmvA+Q== dependencies: - "@typescript-eslint/scope-manager" "4.15.1" - "@typescript-eslint/types" "4.15.1" - "@typescript-eslint/typescript-estree" "4.15.1" + "@typescript-eslint/scope-manager" "4.15.2" + "@typescript-eslint/types" "4.15.2" + "@typescript-eslint/typescript-estree" "4.15.2" debug "^4.1.1" -"@typescript-eslint/scope-manager@4.15.1": - version "4.15.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.15.1.tgz#f6511eb38def2a8a6be600c530c243bbb56ac135" - integrity sha512-ibQrTFcAm7yG4C1iwpIYK7vDnFg+fKaZVfvyOm3sNsGAerKfwPVFtYft5EbjzByDJ4dj1WD8/34REJfw/9wdVA== +"@typescript-eslint/scope-manager@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.15.2.tgz#5725bda656995960ae1d004bfd1cd70320f37f4f" + integrity sha512-Zm0tf/MSKuX6aeJmuXexgdVyxT9/oJJhaCkijv0DvJVT3ui4zY6XYd6iwIo/8GEZGy43cd7w1rFMiCLHbRzAPQ== dependencies: - "@typescript-eslint/types" "4.15.1" - "@typescript-eslint/visitor-keys" "4.15.1" + "@typescript-eslint/types" "4.15.2" + "@typescript-eslint/visitor-keys" "4.15.2" "@typescript-eslint/scope-manager@4.8.1": version "4.8.1" @@ -514,23 +521,23 @@ "@typescript-eslint/types" "4.8.1" "@typescript-eslint/visitor-keys" "4.8.1" -"@typescript-eslint/types@4.15.1": - version "4.15.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.15.1.tgz#da702f544ef1afae4bc98da699eaecd49cf31c8c" - integrity sha512-iGsaUyWFyLz0mHfXhX4zO6P7O3sExQpBJ2dgXB0G5g/8PRVfBBsmQIc3r83ranEQTALLR3Vko/fnCIVqmH+mPw== +"@typescript-eslint/types@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.15.2.tgz#04acf3a2dc8001a88985291744241e732ef22c60" + integrity sha512-r7lW7HFkAarfUylJ2tKndyO9njwSyoy6cpfDKWPX6/ctZA+QyaYscAHXVAfJqtnY6aaTwDYrOhp+ginlbc7HfQ== "@typescript-eslint/types@4.8.1": version "4.8.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.8.1.tgz#23829c73c5fc6f4fcd5346a7780b274f72fee222" integrity sha512-ave2a18x2Y25q5K05K/U3JQIe2Av4+TNi/2YuzyaXLAsDx6UZkz1boZ7nR/N6Wwae2PpudTZmHFXqu7faXfHmA== -"@typescript-eslint/typescript-estree@4.15.1": - version "4.15.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.1.tgz#fa9a9ff88b4a04d901ddbe5b248bc0a00cd610be" - integrity sha512-z8MN3CicTEumrWAEB2e2CcoZa3KP9+SMYLIA2aM49XW3cWIaiVSOAGq30ffR5XHxRirqE90fgLw3e6WmNx5uNw== +"@typescript-eslint/typescript-estree@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.2.tgz#c2f7a1e94f3428d229d5ecff3ead6581ee9b62fa" + integrity sha512-cGR8C2g5SPtHTQvAymEODeqx90pJHadWsgTtx6GbnTWKqsg7yp6Eaya9nFzUd4KrKhxdYTTFBiYeTPQaz/l8bw== dependencies: - "@typescript-eslint/types" "4.15.1" - "@typescript-eslint/visitor-keys" "4.15.1" + "@typescript-eslint/types" "4.15.2" + "@typescript-eslint/visitor-keys" "4.15.2" debug "^4.1.1" globby "^11.0.1" is-glob "^4.0.1" @@ -551,12 +558,12 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@4.15.1": - version "4.15.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.1.tgz#c76abbf2a3be8a70ed760f0e5756bf62de5865dd" - integrity sha512-tYzaTP9plooRJY8eNlpAewTOqtWW/4ff/5wBjNVaJ0S0wC4Gpq/zDVRTJa5bq2v1pCNQ08xxMCndcvR+h7lMww== +"@typescript-eslint/visitor-keys@4.15.2": + version "4.15.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.2.tgz#3d1c7979ce75bf6acf9691109bd0d6b5706192b9" + integrity sha512-TME1VgSb7wTwgENN5KVj4Nqg25hP8DisXxNBojM4Nn31rYaNDIocNm5cmjOFfh42n7NVERxWrDFoETO/76ePyg== dependencies: - "@typescript-eslint/types" "4.15.1" + "@typescript-eslint/types" "4.15.2" eslint-visitor-keys "^2.0.0" "@typescript-eslint/visitor-keys@4.8.1": @@ -888,6 +895,11 @@ base64-js@^1.0.2, base64-js@^1.2.0, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +big-integer@^1.6.16: + version "1.6.48" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e" + integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w== + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -950,6 +962,19 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" +broadcast-channel@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-3.4.1.tgz#65b63068d0a5216026a19905c9b2d5e9adf0928a" + integrity sha512-VXYivSkuBeQY+pL5hNQQNvBdKKQINBAROm4G8lAbWQfOZ7Yn4TMcgLNlJyEqlkxy5G8JJBsI3VJ1u8FUTOROcg== + dependencies: + "@babel/runtime" "^7.7.2" + detect-node "^2.0.4" + js-sha3 "0.8.0" + microseconds "0.2.0" + nano-time "1.0.0" + rimraf "3.0.2" + unload "2.2.0" + brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" @@ -1749,6 +1774,11 @@ detect-libc@^1.0.3: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= +detect-node@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" + integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== + detective@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" @@ -2072,10 +2102,10 @@ eslint-module-utils@^2.6.0: debug "^2.6.9" pkg-dir "^2.0.0" -eslint-plugin-flowtype@5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.2.2.tgz#c6e5dd2fad4e757a1c63e652da6cff597659554f" - integrity sha512-C4PlPYpszr9h1cBfUbTNRI1IdxUCF0qrXAHkXS2+bESp7WUUCnvb3UBBnYlaQLvJYJ2lRz+2SPQQ/WyV7p/Tow== +eslint-plugin-flowtype@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.3.0.tgz#5cd1f222633294444d695202e3322ce0262f5a41" + integrity sha512-QMA0+QXL+5bXM91T6qeO1yriEL79a6spXs1VUWk9IwExiNxl3AV8OFS8H4gsfYM54tIzMbF6qt8Z6J02r37ABw== dependencies: lodash "^4.17.15" string-natural-compare "^3.0.1" @@ -2354,10 +2384,10 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -fauna-schema-migrate@0.1.3-beta: - version "0.1.3-beta" - resolved "https://registry.yarnpkg.com/fauna-schema-migrate/-/fauna-schema-migrate-0.1.3-beta.tgz#79f7256d041acad4e2f160c68491deeda6ac1616" - integrity sha512-ic3Br7vyDACGZXskF5Bz+gUrEgzCd2fYqSzGAOYjiKrt4aAoGv3KN9MQ4ltORHDWunHPCKXHl1fzg/50OwV3qQ== +fauna-schema-migrate@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/fauna-schema-migrate/-/fauna-schema-migrate-0.1.7.tgz#d78b555a794a170c43362ea9ed5a224016db0723" + integrity sha512-MVItOjqEXsWHLFjmTlL9wvibp7xBaS9MgvYlQ2LI5bOXkBr4oEbpPc/ulHDGKB98GfcN/TEQeVunsHaRiTLa/Q== dependencies: "@babel/parser" "^7.12.7" "@types/deep-equal" "^1.0.1" @@ -2801,10 +2831,10 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -husky@>=4.3.8: - version "5.0.9" - resolved "https://registry.yarnpkg.com/husky/-/husky-5.0.9.tgz#6d38706643d66ed395bcd4ee952d02e3f15eb3a3" - integrity sha512-0SjcaY21a+IRdx7p7r/X33Vc09UR2m8SbP8yfkhUX2/jAmwcz+GR7i9jXkp2pP3GfX23JhMkVP6SWwXB18uXtg== +husky@>=5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/husky/-/husky-5.1.1.tgz#8678953fd8deb86f387cbf1ad50bb2f7f96e83f2" + integrity sha512-80LZ736V0Nr4/st0c2COYaMbEQhHNmAbLMN8J/kLk7/mo0QdUkUGNDjv/7jVkhug377Wh8wfbWyaVXEJ/h2B/Q== iconv-lite@0.4.24: version "0.4.24" @@ -3256,6 +3286,11 @@ js-beautify@^1.13.0: mkdirp "^1.0.4" nopt "^5.0.0" +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-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" @@ -3719,6 +3754,11 @@ micromatch@^4.0.2: braces "^3.0.1" picomatch "^2.0.5" +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" @@ -3810,6 +3850,13 @@ mz@^2.4.0: object-assign "^4.0.1" thenify-all "^1.0.0" +nano-time@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef" + integrity sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8= + dependencies: + big-integer "^1.6.16" + nanoid@^3.1.16: version "3.1.16" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.16.tgz#b21f0a7d031196faf75314d7c65d36352beeef64" @@ -3855,10 +3902,10 @@ next-auth@3.5.0: require_optional "^1.0.1" typeorm "^0.2.30" -next-themes@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.0.10.tgz#86fe5f8a4654416f5d9157993217180174e582b8" - integrity sha512-YapL2GVJDooOuGYCYyCywYXRMpulBngG5Qay/HkMK9RyL9xOZ6C3vEgac2dzLWpo3uDVlk+0Qc9XgwGfLHwq/w== +next-themes@0.0.11: + version "0.0.11" + resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.0.11.tgz#395409788c16041646d448418219f597e6adb5d3" + integrity sha512-tqZwWJSWnOwpklhsnWcsOwehaHv05BnkNJO26jcPwHA9o+QFWxymBKyZRvI2/yBvlxavoKv+PS2TMj23bKOAOw== next@10.0.7: version "10.0.7" @@ -4747,10 +4794,10 @@ react-dom@17.0.1: object-assign "^4.1.1" scheduler "^0.20.1" -react-hook-form@6.15.3: - version "6.15.3" - resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-6.15.3.tgz#ab4ccad9cde42a121fdfb828d9aff0d3d008441f" - integrity sha512-593jDlfP66NlMUOW5aNlCTzFWcFAOIyeFIGQtDreVLZ6n2o5D0DBIv/F+6mGZY0kCZs7yArs/YcgZBFLm1IXbg== +react-hook-form@6.15.4: + version "6.15.4" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-6.15.4.tgz#328003e1ccc096cd158899ffe7e3b33735a9b024" + integrity sha512-K+Sw33DtTMengs8OdqFJI3glzNl1wBzSefD/ksQw/hJf9CnOHQAU6qy82eOrh0IRNt2G53sjr7qnnw1JDjvx1w== react-hookstore@^1.5.1: version "1.5.1" @@ -4769,12 +4816,13 @@ react-is@16.13.1, react-is@^16.8.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-query@3.9.8: - version "3.9.8" - resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.9.8.tgz#b6345af86f81b342eb228b11d2415a7a04ca5ada" - integrity sha512-cO3DdlHFSE/FDeIhrYVfYaUPm7ElmMW/3sp1QaMSP/aiGfsM62a2gRwd34YVA4dBchNk22L9yu2fZ657A6cdvA== +react-query@3.11.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.11.0.tgz#138b8f6bffbdc53b9ae78d295df72402393ce069" + integrity sha512-C0pi1Y96DH4cIElzFd8N4hXYoQ4r6Z5jMRleSlote+qabF9N2SKtoea/Vhvb8URVYlIx7fwIbevnNt3Ij3Mjvg== dependencies: "@babel/runtime" "^7.5.5" + broadcast-channel "^3.4.1" match-sorter "^6.0.2" react-reconciler@^0.24.0: @@ -4983,7 +5031,7 @@ rimraf@2: dependencies: glob "^7.1.3" -rimraf@^3.0.2: +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== @@ -5852,6 +5900,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: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" From b7af14e6fe8988ac0b71350542756efd0c29cd12 Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Tue, 23 Feb 2021 12:46:28 +0530 Subject: [PATCH 003/115] Change the query key for all-goals-by-user --- src/components/goals/NewGoal.tsx | 5 +---- src/pages/[username]/index.tsx | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/goals/NewGoal.tsx b/src/components/goals/NewGoal.tsx index 596525c..963ca00 100644 --- a/src/components/goals/NewGoal.tsx +++ b/src/components/goals/NewGoal.tsx @@ -40,10 +40,7 @@ export default function NewGoal() { toast.success('You have successfully set your goal.', { id: toastId.current, }) - queryClient.refetchQueries([ - '/api/fauna/goals/all-goals-by-user', - (session.user as User).id, - ]) + queryClient.refetchQueries('/api/fauna/goals/all-goals-by-user') queryClient.refetchQueries('/api/fauna/goals/get-current-goal') }, onError: () => { diff --git a/src/pages/[username]/index.tsx b/src/pages/[username]/index.tsx index 2b64b12..69f6e4e 100644 --- a/src/pages/[username]/index.tsx +++ b/src/pages/[username]/index.tsx @@ -41,7 +41,7 @@ export default function UserProfile({ }: InferGetServerSidePropsType) { const [session, loading] = useSession() const { isLoading, isError, data } = useQuery( - ['/api/fauna/goals/all-goals-by-user', user.id], + '/api/fauna/goals/all-goals-by-user', () => fetch(`/api/fauna/goals/all-goals-by-user`, { method: 'POST', From 4543e2444853acb6d68040f096f7734683a4c766 Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Tue, 23 Feb 2021 13:10:25 +0530 Subject: [PATCH 004/115] Add syntax highlighting --- package.json | 1 + src/components/Code.tsx | 89 +++++++++++++++++++++++++++++++++++++ src/components/Markdown.tsx | 5 ++- src/components/index.tsx | 1 + yarn.lock | 5 +++ 5 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 src/components/Code.tsx diff --git a/package.json b/package.json index 079ad95..6ce089c 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "next-themes": "0.0.11", "nightwind": "1.1.6", "phosphor-react": "1.1.2", + "prism-react-renderer": "1.2.0", "react": "17.0.1", "react-dom": "17.0.1", "react-hook-form": "6.15.4", diff --git a/src/components/Code.tsx b/src/components/Code.tsx new file mode 100644 index 0000000..4084989 --- /dev/null +++ b/src/components/Code.tsx @@ -0,0 +1,89 @@ +import Highlight, { defaultProps, Language } from 'prism-react-renderer' +import theme from 'prism-react-renderer/themes/nightOwl' + +const aliasesMap: Record = { + markup: [], + bash: ['sh', 'shellscript'], + clike: [], + c: [], + cpp: [], + css: [], + javascript: ['js'], + jsx: [], + coffeescript: [], + actionscript: [], + 'css-extr': [], + diff: [], + git: [], + go: [], + graphql: [], + handlebars: [], + json: [], + less: [], + makefile: [], + markdown: [], + objectivec: [], + ocaml: [], + python: ['py', 'py3'], + reason: [], + sass: [], + scss: [], + sql: [], + stylus: [], + tsx: [], + typescript: ['ts'], + wasm: [], + yaml: [], +} + +function Code({ + children, + className, +}: { + children: string + className: string +}) { + let languageOfCode = (className?.split('-')?.[1] ?? '') as any + const languages = Object.keys(aliasesMap) as Array + if (!languages.includes(languageOfCode)) { + for (const lang of languages) { + const aliases = aliasesMap[lang] + const match = aliases.find( + // eslint-disable-next-line no-loop-func + (language) => language === languageOfCode + ) + if (match) { + languageOfCode = lang + break + } + } + } + + return ( + + {({ className, style, tokens, getLineProps, getTokenProps }) => ( +
+          
+            {tokens.map((line, i) => (
+              
+ {line.map((token, key) => ( + + ))} +
+ ))} +
+
+ )} +
+ ) +} + +export function Pre({ children }) { + const props = children.props + return +} diff --git a/src/components/Markdown.tsx b/src/components/Markdown.tsx index 8b41b95..01243fd 100644 --- a/src/components/Markdown.tsx +++ b/src/components/Markdown.tsx @@ -1,6 +1,6 @@ import MarkdownOriginal, { MarkdownToJSX } from 'markdown-to-jsx' import React from 'react' -import { A } from '.' +import { A, Pre } from '@/components' export default function Markdown(props: { [key: string]: any @@ -18,6 +18,9 @@ export default function Markdown(props: { a: { component: A, }, + pre: { + component: Pre, + }, }, }} /> diff --git a/src/components/index.tsx b/src/components/index.tsx index 896710b..61442e4 100644 --- a/src/components/index.tsx +++ b/src/components/index.tsx @@ -11,3 +11,4 @@ export { default as Markdown } from './Markdown' export { default as HomePageFeed } from './HomePageFeed' export { default as Hero } from './Hero' export * from './modal' +export { Pre } from './Code' diff --git a/yarn.lock b/yarn.lock index cee7418..181e96d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4643,6 +4643,11 @@ pretty-hrtime@^1.0.3: resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= +prism-react-renderer@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.2.0.tgz#5ad4f90c3e447069426c8a53a0eafde60909cdf4" + integrity sha512-GHqzxLYImx1iKN1jJURcuRoA/0ygCcNhfGw1IT8nPIMzarmKQ3Nc+JcG0gi8JXQzuh0C5ShE4npMIoqNin40hg== + 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" From d415278e11443a363215e894d9f19aa7bdfc9036 Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Tue, 23 Feb 2021 15:48:23 +0530 Subject: [PATCH 005/115] Truncate the bio to 2 lines in members page --- package.json | 1 + src/components/HomePageFeed.tsx | 1 - src/components/members/Member.tsx | 4 +++- tailwind.config.js | 1 + yarn.lock | 5 +++++ 5 files changed, 10 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 6ce089c..c6468d6 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "dependencies": { "@badrap/bar-of-progress": "0.1.2", "@headlessui/react": "0.3.1", + "@tailwindcss/line-clamp": "0.2.0", "classnames": "2.2.6", "fauna-schema-migrate": "0.1.7", "faunadb": "4.1.0", diff --git a/src/components/HomePageFeed.tsx b/src/components/HomePageFeed.tsx index a503c93..92b68aa 100644 --- a/src/components/HomePageFeed.tsx +++ b/src/components/HomePageFeed.tsx @@ -3,7 +3,6 @@ import { ChatCenteredDots, Gear, RocketLaunch, - ShareNetwork, ThumbsUp, UserCircle, Users, diff --git a/src/components/members/Member.tsx b/src/components/members/Member.tsx index 86ff8c2..4a716bc 100644 --- a/src/components/members/Member.tsx +++ b/src/components/members/Member.tsx @@ -61,7 +61,9 @@ export default function Member({ user }: { user: User }) {
Bio
-
{account.bio}
+
+ {account.bio} +
Role
Social Media
{socials && ( diff --git a/tailwind.config.js b/tailwind.config.js index e1bfdae..be8d89b 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -50,6 +50,7 @@ module.exports = { require('@tailwindcss/forms'), require('@tailwindcss/typography'), require('@tailwindcss/aspect-ratio'), + require('@tailwindcss/line-clamp'), require('nightwind'), ], } diff --git a/yarn.lock b/yarn.lock index 181e96d..a8a2a7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -276,6 +276,11 @@ dependencies: mini-svg-data-uri "^1.2.3" +"@tailwindcss/line-clamp@0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@tailwindcss/line-clamp/-/line-clamp-0.2.0.tgz#7f30f26ed3835d64d1eb5a9b0d60cf5291dd2a3b" + integrity sha512-+jXSdRK3/9V/BCPCr+iNpMMhxWMMv62vn/AS2b3/ClmueGuhCijW3bUwO1IiHnE7uCaF74Sli8jUCv9djwvpLg== + "@tailwindcss/typography@0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.4.0.tgz#b80974ad6af93df7b06e1981cb4d79698b6ad5c7" From 2ae46747f9ad46810e51c27dfc3e47d7dc286c2c Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Tue, 23 Feb 2021 16:20:16 +0530 Subject: [PATCH 006/115] Increase the max height of the goal preview on the home page --- src/components/HomePageFeed.tsx | 2 +- tailwind.config.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/HomePageFeed.tsx b/src/components/HomePageFeed.tsx index 92b68aa..581a691 100644 --- a/src/components/HomePageFeed.tsx +++ b/src/components/HomePageFeed.tsx @@ -492,7 +492,7 @@ function HomePageAside({ goalId }: { goalId: string }) { {Boolean(goalId) && (
diff --git a/tailwind.config.js b/tailwind.config.js index be8d89b..7a31367 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -19,6 +19,7 @@ module.exports = { 13: '3.25rem', 26: '6.5rem', 100: '25rem', + 150: '37.5rem', }, colors: { blueGray: colors.blueGray, From e8c1d0d2c176f6858d2851561cf59399888eed68 Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Tue, 23 Feb 2021 16:38:26 +0530 Subject: [PATCH 007/115] Remove vertical line connecting the comments --- src/components/goals/UpdateComment.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/components/goals/UpdateComment.tsx b/src/components/goals/UpdateComment.tsx index b19c575..ec7d3fe 100644 --- a/src/components/goals/UpdateComment.tsx +++ b/src/components/goals/UpdateComment.tsx @@ -23,14 +23,7 @@ export default function UpdateComment({ }) { return (
  • -
    - {!isLastComment && ( - - )} - +
    From 92e9481a4fe626070339305ba51f43ccc41e1b3a Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Wed, 24 Feb 2021 16:00:51 +0530 Subject: [PATCH 008/115] Allow the user to edit an update --- src/components/HomePageFeed.tsx | 257 +++++++++++++---------- src/components/goals/EditUpdate.tsx | 129 ++++++++++++ src/pages/api/fauna/goals/edit-update.ts | 49 +++++ 3 files changed, 329 insertions(+), 106 deletions(-) create mode 100644 src/components/goals/EditUpdate.tsx create mode 100644 src/pages/api/fauna/goals/edit-update.ts diff --git a/src/components/HomePageFeed.tsx b/src/components/HomePageFeed.tsx index 581a691..d45344f 100644 --- a/src/components/HomePageFeed.tsx +++ b/src/components/HomePageFeed.tsx @@ -1,9 +1,12 @@ -import { Avatar } from '@/ui' +import { Avatar, Menu } from '@/ui' import { ChatCenteredDots, + DotsThreeOutlineVertical, Gear, + Pencil, RocketLaunch, ThumbsUp, + Trash, UserCircle, Users, } from 'phosphor-react' @@ -34,7 +37,8 @@ import { import { Goal } from './goals' import type { GoalResponse } from 'src/pages/[username]' import { scrollToContentWithId } from 'src/utils' -import { IconBrandDiscord } from 'tabler-icons' +import { IconBrandDiscord, IconMenu } from 'tabler-icons' +import EditUpdate from './goals/EditUpdate' type LikeData = { count: number @@ -65,6 +69,7 @@ export function HomePageFeedUpdate({ update: HomePageFeedUpdateType setGoalId: () => void }) { + const [isInEditMode, setIsInEditMode] = useState(false) const [isLikeModalOpen, setIsLikeModalOpen] = useState(false) const [session] = useSession() const [showComments, setShowComments] = useState(false) @@ -120,114 +125,154 @@ export function HomePageFeedUpdate({ className="bg-white px-4 py-6 shadow sm:p-6 sm:rounded-lg" id={`homepage-update-${update.id}`} > -
    -
    -
    -
    - - - -
    -
    -

    - - {postedBy.name} + {isInEditMode ? ( + setIsInEditMode(false)} + updateFromHomePage={true} + /> + ) : ( + <> +

    +
    +
    + +
    +

    + + {postedBy.name} + +

    +

    + +

    +
    + +
    +
    + + Open quick actions + + + } + > + setIsInEditMode(true)} + > + Edit + + Delete + +
    +
    +
    +
    + + + + 🚀 Goal: {goal.title} + -

    -

    - -

    +
    -
    -
    - - - - 🚀 Goal: {goal.title} - - -
    -
    -
    -
    - {description} -
    -
    -
    -
    - - - - - - + - replies - - -
    -
    -
    + + + +
    +
    + - {showComments && ( - <> - - - {update.comments.data.map((comment, index) => ( - - {comment.description} - - ))} - - {session && } - + {showComments && ( + <> + + + {update.comments.data.map((comment, index) => ( + + {comment.description} + + ))} + + {session && } + + + )} )}
  • diff --git a/src/components/goals/EditUpdate.tsx b/src/components/goals/EditUpdate.tsx new file mode 100644 index 0000000..24d3d35 --- /dev/null +++ b/src/components/goals/EditUpdate.tsx @@ -0,0 +1,129 @@ +import { User } from 'src/pages/members' +import { Avatar, Button, TextArea } from '@/ui' +import { useForm } from 'react-hook-form' +import { useSession } from 'next-auth/client' +import { useMutation, useQueryClient } from 'react-query' +import toast, { Toaster } from 'react-hot-toast' +import { useRef, useState } from 'react' +import { Markdown } from '@/components' + +type Inputs = { + description: string +} + +export default function EditUpdate({ + goalId, + update, + updateFromHomePage = false, + cancelEditMode, +}: { + goalId: string + update: { id: string; description: string } + updateFromHomePage?: boolean + cancelEditMode: () => void +}) { + const [descriptionStorage, setDescriptionStorage] = useState( + update.description + ) + const queryClient = useQueryClient() + const [session, loading] = useSession() + const { handleSubmit, register, errors, reset } = useForm() + const toastId = useRef('') + const { mutate } = useMutation( + (data: Inputs) => + fetch(`/api/fauna/goals/edit-update`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + id: update.id, + description: data.description, + }), + }).then((res) => { + if (!res.ok) { + throw new Error('Something went wrong!!') + } + return res.json() + }), + { + onSuccess: () => { + toast.success('You have successfully edited the update.', { + id: toastId.current, + }) + queryClient.refetchQueries([ + '/api/fauna/goals/all-goals-by-user', + (session.user as User).id, + ]) + if (updateFromHomePage) { + queryClient.refetchQueries('/api/fauna/all-updates') + queryClient.refetchQueries(['/api/fauna/recent-updates', goalId]) + } + reset() + cancelEditMode() + }, + onError: () => { + toast.error('Something went wrong!!!', { id: toastId.current }) + }, + } + ) + const onSubmit = (data: Inputs) => { + const id = toast.loading('Posting your update...') + toastId.current = id + mutate(data) + setDescriptionStorage(update.description) + } + if (loading) { + return

    loading...

    + } + return ( + <> + +
    +
    +
    +
    + +
    +
    +
    +
    + + {descriptionStorage && ( +
    + {descriptionStorage} +
    + )} + +
    + + +
    +
    +
    +
    +
    + + ) +} diff --git a/src/pages/api/fauna/goals/edit-update.ts b/src/pages/api/fauna/goals/edit-update.ts new file mode 100644 index 0000000..aefcaf0 --- /dev/null +++ b/src/pages/api/fauna/goals/edit-update.ts @@ -0,0 +1,49 @@ +import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { getSession } from 'next-auth/client' + +import faunadb from 'faunadb' +import { User } from 'src/pages/members' +const q = faunadb.query +const isProduction = process.env.NODE_ENV === 'production' +const client = new faunadb.Client({ + secret: process.env.FAUNADB_SECRET ?? 'secret', + scheme: isProduction ? 'https' : 'http', + domain: isProduction ? 'db.fauna.com' : 'localhost', + ...(isProduction ? {} : { port: 8443 }), +}) + +const FaunaCreateHandler: NextApiHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + const session = await getSession({ req }) + + if (!session) { + return res.status(401).json({ message: 'Unauthorized' }) + } + const { id, description } = req.body + const userId = (session.user as User).id + try { + const updateDoc = q.Get(q.Ref(q.Collection('goal_updates'), id)) + const updatePostedById = q.Select(['data', 'postedBy', 'id'], updateDoc) + const response = await client.query( + q.If( + q.Equals(updatePostedById, userId), + q.Update(q.Ref(q.Collection('goal_updates'), id), { + data: { + description, + }, + }), + q.Abort('You are not authorized to edit this!!!') + ) + ) + + res.status(200).json({ response }) + } catch (error) { + console.error(error) + console.error({ msg: error.message }) + res.status(500).json({ message: error.description }) + } +} + +export default FaunaCreateHandler From 63db4e4c10060bd5da06e9b2c720886009fc17be Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Wed, 24 Feb 2021 16:49:55 +0530 Subject: [PATCH 009/115] Allow users to delete their updates --- src/components/HomePageFeed.tsx | 334 ++++++++++++--------- src/components/goals/EditGoal.tsx | 5 +- src/components/goals/EditUpdate.tsx | 5 +- src/components/goals/NewUpdate.tsx | 5 +- src/pages/api/fauna/goals/delete-update.ts | 45 +++ 5 files changed, 238 insertions(+), 156 deletions(-) create mode 100644 src/pages/api/fauna/goals/delete-update.ts diff --git a/src/components/HomePageFeed.tsx b/src/components/HomePageFeed.tsx index d45344f..76f39bf 100644 --- a/src/components/HomePageFeed.tsx +++ b/src/components/HomePageFeed.tsx @@ -13,9 +13,9 @@ import { import * as React from 'react' import { HomePageFeedUpdateType } from 'src/pages' import { DateTime } from 'luxon' -import { useMutation, useQuery } from 'react-query' +import { useMutation, useQuery, useQueryClient } from 'react-query' import classNames from 'classnames' -import { useEffect, useReducer, useState } from 'react' +import { useEffect, useReducer, useState, useRef } from 'react' import { signIn, useSession } from 'next-auth/client' import { User } from 'src/pages/members' import useFollowUser from './profile/useFollowUser' @@ -37,8 +37,9 @@ import { import { Goal } from './goals' import type { GoalResponse } from 'src/pages/[username]' import { scrollToContentWithId } from 'src/utils' -import { IconBrandDiscord, IconMenu } from 'tabler-icons' +import { IconBrandDiscord } from 'tabler-icons' import EditUpdate from './goals/EditUpdate' +import toast, { Toaster } from 'react-hot-toast' type LikeData = { count: number @@ -69,12 +70,14 @@ export function HomePageFeedUpdate({ update: HomePageFeedUpdateType setGoalId: () => void }) { + const queryClient = useQueryClient() const [isInEditMode, setIsInEditMode] = useState(false) const [isLikeModalOpen, setIsLikeModalOpen] = useState(false) const [session] = useSession() const [showComments, setShowComments] = useState(false) const { postedBy, createdAt: createdAtInMillis, goal, description } = update const createdAt = DateTime.fromMillis(createdAtInMillis) + const toastId = useRef('') const { isLoading, isError, data } = useQuery( ['api/fauna/has-liked', update.id], () => { @@ -106,6 +109,35 @@ export function HomePageFeedUpdate({ }) }) + const { mutate: deleteUpdate } = useMutation( + () => { + return fetch(`/api/fauna/goals/delete-update`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + id: update.id, + }), + }).then((res) => { + if (!res.ok) { + throw new Error('something went wrong!!!') + } + return res.json() + }) + }, + { + onSuccess: () => { + toast.success('Deleted your update!!', { + id: toastId.current, + icon: , + }) + queryClient.refetchQueries('/api/fauna/all-updates') + queryClient.refetchQueries(['/api/fauna/recent-updates', goal.id]) + }, + } + ) + const [{ count: likesCount, hasLiked }, dispatch] = useReducer( reducer, initialState @@ -121,161 +153,175 @@ export function HomePageFeedUpdate({ }, [data?.liked, isError, isLoading, update.likes.data]) return ( -
  • - {isInEditMode ? ( - setIsInEditMode(false)} - updateFromHomePage={true} - /> - ) : ( - <> -
    -
    -
    -
    - - - -
    -
    -

    - - {postedBy.name} + <> + +

  • + {isInEditMode ? ( + setIsInEditMode(false)} + updateFromHomePage={true} + /> + ) : ( + <> +
    +
    +
    +
    + + -

    -

    - -

    -
    +
    +
    +

    + + {postedBy.name} + +

    +

    + +

    +
    -
    -
    - - Open quick actions - - - } - > - setIsInEditMode(true)} +
    +
    + + Open quick actions + + + } > - Edit - - Delete - + setIsInEditMode(true)} + > + Edit + + { + deleteUpdate() + const id = toast.loading('Deleting your update...') + toastId.current = id + }} + > + Delete + +
    +
    -
  • -
    - - - - 🚀 Goal: {goal.title} - - -
    -
    -
    -
    - {description} -
    -
    -
    -
    - +
    - - - - - + +
    -
    -
    - - {showComments && ( - <> - - - {update.comments.data.map((comment, index) => ( - +
    + {description} +
    +
  • +
    +
    + + + + + + + +
    +
    + + + {showComments && ( + <> + + + {update.comments.data.map((comment, index) => ( + + {comment.description} + + ))} + + {session && } + + + )} + + )} + + ) } diff --git a/src/components/goals/EditGoal.tsx b/src/components/goals/EditGoal.tsx index 8ec1380..ec5d6ae 100644 --- a/src/components/goals/EditGoal.tsx +++ b/src/components/goals/EditGoal.tsx @@ -51,10 +51,7 @@ export default function EditGoal({ toast.success('You have successfully updated your goal.', { id: toastId.current, }) - queryClient.refetchQueries([ - '/api/fauna/goals/all-goals-by-user', - (session.user as User).id, - ]) + queryClient.refetchQueries('/api/fauna/goals/all-goals-by-user') onCancelClick() }, onError: () => { diff --git a/src/components/goals/EditUpdate.tsx b/src/components/goals/EditUpdate.tsx index 24d3d35..b6907d6 100644 --- a/src/components/goals/EditUpdate.tsx +++ b/src/components/goals/EditUpdate.tsx @@ -51,10 +51,7 @@ export default function EditUpdate({ toast.success('You have successfully edited the update.', { id: toastId.current, }) - queryClient.refetchQueries([ - '/api/fauna/goals/all-goals-by-user', - (session.user as User).id, - ]) + queryClient.refetchQueries('/api/fauna/goals/all-goals-by-user') if (updateFromHomePage) { queryClient.refetchQueries('/api/fauna/all-updates') queryClient.refetchQueries(['/api/fauna/recent-updates', goalId]) diff --git a/src/components/goals/NewUpdate.tsx b/src/components/goals/NewUpdate.tsx index 7ca686e..04fd4ca 100644 --- a/src/components/goals/NewUpdate.tsx +++ b/src/components/goals/NewUpdate.tsx @@ -45,10 +45,7 @@ export default function NewUpdate({ toast.success('You have successfully added an update.', { id: toastId.current, }) - queryClient.refetchQueries([ - '/api/fauna/goals/all-goals-by-user', - (session.user as User).id, - ]) + queryClient.refetchQueries('/api/fauna/goals/all-goals-by-user') if (updateFromHomePage) { queryClient.refetchQueries('/api/fauna/all-updates') queryClient.refetchQueries(['/api/fauna/recent-updates', goal.id]) diff --git a/src/pages/api/fauna/goals/delete-update.ts b/src/pages/api/fauna/goals/delete-update.ts new file mode 100644 index 0000000..c3a25b9 --- /dev/null +++ b/src/pages/api/fauna/goals/delete-update.ts @@ -0,0 +1,45 @@ +import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { getSession } from 'next-auth/client' + +import faunadb from 'faunadb' +import { User } from 'src/pages/members' +const q = faunadb.query +const isProduction = process.env.NODE_ENV === 'production' +const client = new faunadb.Client({ + secret: process.env.FAUNADB_SECRET ?? 'secret', + scheme: isProduction ? 'https' : 'http', + domain: isProduction ? 'db.fauna.com' : 'localhost', + ...(isProduction ? {} : { port: 8443 }), +}) + +const FaunaCreateHandler: NextApiHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + const session = await getSession({ req }) + + if (!session) { + return res.status(401).json({ message: 'Unauthorized' }) + } + const { id } = req.body + const userId = (session.user as User).id + try { + const updateDoc = q.Get(q.Ref(q.Collection('goal_updates'), id)) + const updatePostedById = q.Select(['data', 'postedBy', 'id'], updateDoc) + const response = await client.query( + q.If( + q.Equals(updatePostedById, userId), + q.Delete(q.Ref(q.Collection('goal_updates'), id)), + q.Abort('You are not authorized to delete this!!!') + ) + ) + + res.status(200).json({ response }) + } catch (error) { + console.error(error) + console.error({ msg: error.message }) + res.status(500).json({ message: error.description }) + } +} + +export default FaunaCreateHandler From 69396a5a385dffe45633ad155c1d73e7e1e1711b Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Wed, 24 Feb 2021 17:31:46 +0530 Subject: [PATCH 010/115] Only show quick action menu for the current user's updates --- src/components/HomePageFeed.tsx | 71 +++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/src/components/HomePageFeed.tsx b/src/components/HomePageFeed.tsx index 76f39bf..339d1fa 100644 --- a/src/components/HomePageFeed.tsx +++ b/src/components/HomePageFeed.tsx @@ -135,6 +135,11 @@ export function HomePageFeedUpdate({ queryClient.refetchQueries('/api/fauna/all-updates') queryClient.refetchQueries(['/api/fauna/recent-updates', goal.id]) }, + onError: () => { + toast.error('Something went wrong!!!', { + id: toastId.current, + }) + }, } ) @@ -192,38 +197,44 @@ export function HomePageFeedUpdate({

    -
    -
    - - Open quick actions - - - } - > - setIsInEditMode(true)} + {session && (session.user as User).id === update.postedBy.id && ( +
    +
    + + + Open quick actions + + + + } > - Edit - - { - deleteUpdate() - const id = toast.loading('Deleting your update...') - toastId.current = id - }} - > - Delete - - + setIsInEditMode(true)} + > + Edit + + { + deleteUpdate() + const id = toast.loading( + 'Deleting your update...' + ) + toastId.current = id + }} + > + Delete + +
    +
    - + )}
    + + +
    + diff --git a/src/components/goals/index.tsx b/src/components/goals/index.tsx index 6bead33..2bfc196 100644 --- a/src/components/goals/index.tsx +++ b/src/components/goals/index.tsx @@ -11,3 +11,4 @@ export type { GoalType } from './GoalFeed' export { default as UpdateComment } from './UpdateComment' export { default as NewComment } from './NewComment' export { default as UpdateComments, UpdateCommentsList } from './UpdateComments' +export { default as EditUpdate } from './EditUpdate' diff --git a/src/components/index.tsx b/src/components/index.tsx index 61442e4..eef4d9a 100644 --- a/src/components/index.tsx +++ b/src/components/index.tsx @@ -12,3 +12,4 @@ export { default as HomePageFeed } from './HomePageFeed' export { default as Hero } from './Hero' export * from './modal' export { Pre } from './Code' +export { useLikes } from './useLikes' diff --git a/src/pages/api/fauna/all-updates.ts b/src/pages/api/fauna/all-updates.ts index 6c19f9a..8b7b33b 100644 --- a/src/pages/api/fauna/all-updates.ts +++ b/src/pages/api/fauna/all-updates.ts @@ -47,6 +47,16 @@ const FaunaCreateHandler: NextApiHandler = async ( createdAt: q.ToMillis( q.Select(['data', 'timestamps', 'createdAt'], commentDoc) ), + likes: q.Count( + q.Filter( + q.Paginate( + q.Match(q.Index('all_likes_by_comment'), commentRef) + ), + (commentLikeRef) => { + return q.Select(['data', 'liked'], q.Get(commentLikeRef)) + } + ) + ), postedBy: { id: q.Select(['ref', 'id'], postedByDoc), name: q.Select(['data', 'name'], postedByDoc, null), diff --git a/src/pages/api/fauna/has-liked-comment.ts b/src/pages/api/fauna/has-liked-comment.ts new file mode 100644 index 0000000..9efc0f0 --- /dev/null +++ b/src/pages/api/fauna/has-liked-comment.ts @@ -0,0 +1,52 @@ +import { User } from 'src/pages/members' +import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { getSession } from 'next-auth/client' + +import faunadb from 'faunadb' +const q = faunadb.query +const isProduction = process.env.NODE_ENV === 'production' +const client = new faunadb.Client({ + secret: process.env.FAUNADB_SECRET ?? 'secret', + scheme: isProduction ? 'https' : 'http', + domain: isProduction ? 'db.fauna.com' : 'localhost', + ...(isProduction ? {} : { port: 8443 }), +}) + +const FaunaCreateHandler: NextApiHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + const session = await getSession({ req }) + + if (!session) { + return res.status(200).json({ liked: false }) + } + + const userId = (session.user as User).id + + try { + const { commentId } = req.body + const response = await client.query( + q.Let( + { + ref: q.Match(q.Index('unique_comment_user_like'), [ + q.Ref(q.Collection('update_comments'), commentId), + q.Ref(q.Collection('users'), userId), + ]), + }, + q.If( + q.Exists(q.Var('ref')), + q.Select(['data', 'liked'], q.Get(q.Var('ref'))), + false + ) + ) + ) + res.status(200).json({ liked: response }) + } catch (error) { + console.error(error) + console.error({ msg: error.message }) + res.status(500).json({ message: error.message }) + } +} + +export default FaunaCreateHandler diff --git a/src/pages/api/fauna/toggle-comment-like.ts b/src/pages/api/fauna/toggle-comment-like.ts new file mode 100644 index 0000000..f92ad6a --- /dev/null +++ b/src/pages/api/fauna/toggle-comment-like.ts @@ -0,0 +1,75 @@ +import { User } from 'src/pages/members' +import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { getSession } from 'next-auth/client' + +import faunadb from 'faunadb' +const q = faunadb.query +const isProduction = process.env.NODE_ENV === 'production' +const client = new faunadb.Client({ + secret: process.env.FAUNADB_SECRET ?? 'secret', + scheme: isProduction ? 'https' : 'http', + domain: isProduction ? 'db.fauna.com' : 'localhost', + ...(isProduction ? {} : { port: 8443 }), +}) + +const FaunaCreateHandler: NextApiHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + const session = await getSession({ req }) + + if (!session) { + return res.status(401).json({ message: 'Unauthorized' }) + } + + const userId = (session.user as User).id + + try { + const { commentId } = req.body + const response = await client.query( + q.Let( + { + ref: q.Match(q.Index('unique_comment_user_like'), [ + q.Ref(q.Collection('update_comments'), commentId), + q.Ref(q.Collection('users'), userId), + ]), + }, + q.If( + q.Exists(q.Var('ref')), + q.Update( + q.Ref( + q.Collection('comment_likes'), + q.Select(['ref', 'id'], q.Get(q.Var('ref'))) + ), + { + data: { + liked: q.Not(q.Select(['data', 'liked'], q.Get(q.Var('ref')))), + timestamps: { + updatedAt: q.Now(), + }, + }, + } + ), + q.Create(q.Collection('comment_likes'), { + data: { + user: q.Ref(q.Collection('users'), userId), + comment: q.Ref(q.Collection('update_comments'), commentId), + liked: true, + timestamps: { + createdAt: q.Now(), + updatedAt: q.Now(), + }, + }, + }) + ) + ) + ) + res.status(200).json({ response }) + } catch (error) { + console.error(error) + console.error({ msg: error.message }) + res.status(500).json({ message: error.message }) + } +} + +export default FaunaCreateHandler diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 0296894..80ea9db 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -8,6 +8,9 @@ export type UpdateCommentType = { description: string createdAt: number postedBy: User + likes: { + data: number + } } export type HomePageFeedUpdateType = { From f86cd7d2967e72b1d210cc9cbab2bd36d41360da Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Thu, 25 Feb 2021 13:33:12 +0530 Subject: [PATCH 015/115] Add a way to edit comment --- src/components/HomePageFeed.tsx | 1 + src/components/goals/EditComment.tsx | 125 +++++++++++++++ src/components/goals/UpdateComment.tsx | 182 ++++++++++++++-------- src/components/goals/index.tsx | 1 + src/pages/api/fauna/goals/edit-comment.ts | 49 ++++++ 5 files changed, 294 insertions(+), 64 deletions(-) create mode 100644 src/components/goals/EditComment.tsx create mode 100644 src/pages/api/fauna/goals/edit-comment.ts diff --git a/src/components/HomePageFeed.tsx b/src/components/HomePageFeed.tsx index b243022..eaeec33 100644 --- a/src/components/HomePageFeed.tsx +++ b/src/components/HomePageFeed.tsx @@ -265,6 +265,7 @@ export function HomePageFeedUpdate({ {update.comments.data.map((comment, index) => ( void +}) { + const [descriptionStorage, setDescriptionStorage] = useState( + comment.description + ) + const queryClient = useQueryClient() + const [session, loading] = useSession() + const { handleSubmit, register, errors, reset } = useForm() + const toastId = useRef('') + const { mutate } = useMutation( + (data: Inputs) => + fetch(`/api/fauna/goals/edit-comment`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + id: comment.id, + description: data.description, + }), + }).then((res) => { + if (!res.ok) { + throw new Error('Something went wrong!!') + } + return res.json() + }), + { + onSuccess: () => { + toast.success('You have successfully updated your comment.', { + id: toastId.current, + }) + queryClient.refetchQueries('/api/fauna/all-updates') + cancelEditMode() + reset() + }, + onError: () => { + toast.error('Something went wrong!!!', { id: toastId.current }) + }, + } + ) + const onSubmit = (data: Inputs) => { + const id = toast.loading('Saving your comment...') + toastId.current = id + mutate(data) + setDescriptionStorage('') + } + if (loading) { + return

    loading...

    + } + return ( + <> + +
    +
    +
    +
    + + + +
    +
    +
    +
    + + {descriptionStorage && ( +
    + {descriptionStorage} +
    + )} + +
    + + +
    +
    +
    +
    +
    + + ) +} diff --git a/src/components/goals/UpdateComment.tsx b/src/components/goals/UpdateComment.tsx index d2ea689..cf9bcec 100644 --- a/src/components/goals/UpdateComment.tsx +++ b/src/components/goals/UpdateComment.tsx @@ -1,11 +1,17 @@ -import { Avatar } from '@/ui' +import { Avatar, Menu } from '@/ui' import React, { useState } from 'react' -import { Markdown, A, LikeModal, useLikes } from '@/components' +import { Markdown, A, LikeModal, useLikes, EditComment } from '@/components' import { DateTime } from 'luxon' import { UpdateCommentType } from 'src/pages' import { useSession } from 'next-auth/client' import classNames from 'classnames' -import { ThumbsUp } from 'phosphor-react' +import { + DotsThreeOutlineVertical, + Pencil, + ThumbsUp, + Trash, +} from 'phosphor-react' +import { User } from 'src/pages/members' export type GoalUpdateType = { id: string @@ -14,14 +20,17 @@ export type GoalUpdateType = { } export default function UpdateComment({ + updateId, comment, children, isLastComment = false, }: { + updateId: string children: string comment: UpdateCommentType isLastComment?: boolean }) { + const [isInEditMode, setIsInEditMode] = useState(false) const postedOn = DateTime.fromMillis(comment.createdAt) const [session] = useSession() const [isLikeModalOpen, setIsLikeModalOpen] = useState(false) @@ -43,75 +52,120 @@ export default function UpdateComment({ }) return (
  • -
    -
    -
    - - - -
    -
    -
    - -

    - Posted on{' '} - -

    + {isInEditMode ? ( + setIsInEditMode(false)} + /> + ) : ( +
    +
    + -
    -
    - {children} +
    +
    +
    + +

    + Posted on{' '} + +

    +
    + {session && (session.user as User).id === comment.postedBy.id && ( +
    +
    + + Open quick actions + + + } + > + setIsInEditMode(true)} + > + Edit + + { + // deleteUpdate() + // const id = toast.loading('Deleting your update...') + // toastId.current = id + }} + > + Delete + + +
    +
    + )} +
    +
    +
    + {children} +
    -
    -
    -
    - - + - - {likesCount} - - likes - - - + +
    -
    + )}
  • ) } diff --git a/src/components/goals/index.tsx b/src/components/goals/index.tsx index 2bfc196..c567cde 100644 --- a/src/components/goals/index.tsx +++ b/src/components/goals/index.tsx @@ -12,3 +12,4 @@ export { default as UpdateComment } from './UpdateComment' export { default as NewComment } from './NewComment' export { default as UpdateComments, UpdateCommentsList } from './UpdateComments' export { default as EditUpdate } from './EditUpdate' +export { default as EditComment } from './EditComment' diff --git a/src/pages/api/fauna/goals/edit-comment.ts b/src/pages/api/fauna/goals/edit-comment.ts new file mode 100644 index 0000000..bf11f14 --- /dev/null +++ b/src/pages/api/fauna/goals/edit-comment.ts @@ -0,0 +1,49 @@ +import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { getSession } from 'next-auth/client' + +import faunadb from 'faunadb' +import { User } from 'src/pages/members' +const q = faunadb.query +const isProduction = process.env.NODE_ENV === 'production' +const client = new faunadb.Client({ + secret: process.env.FAUNADB_SECRET ?? 'secret', + scheme: isProduction ? 'https' : 'http', + domain: isProduction ? 'db.fauna.com' : 'localhost', + ...(isProduction ? {} : { port: 8443 }), +}) + +const FaunaCreateHandler: NextApiHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + const session = await getSession({ req }) + + if (!session) { + return res.status(401).json({ message: 'Unauthorized' }) + } + const { id, description } = req.body + const userId = (session.user as User).id + try { + const commentDoc = q.Get(q.Ref(q.Collection('update_comments'), id)) + const commentPostedById = q.Select(['data', 'postedBy', 'id'], commentDoc) + const response = await client.query( + q.If( + q.Equals(commentPostedById, userId), + q.Update(q.Ref(q.Collection('update_comments'), id), { + data: { + description, + }, + }), + q.Abort('You are not authorized to edit this!!!') + ) + ) + + res.status(200).json({ response }) + } catch (error) { + console.error(error) + console.error({ msg: error.message }) + res.status(500).json({ message: error.description }) + } +} + +export default FaunaCreateHandler From d2917f4ebffa279df5a56b7d374c8a1d345d71cc Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Thu, 25 Feb 2021 13:36:56 +0530 Subject: [PATCH 016/115] Add a way to delete comment --- src/components/goals/UpdateComment.tsx | 44 ++++++++++++++++++-- src/pages/api/fauna/goals/delete-comment.ts | 45 +++++++++++++++++++++ 2 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 src/pages/api/fauna/goals/delete-comment.ts diff --git a/src/components/goals/UpdateComment.tsx b/src/components/goals/UpdateComment.tsx index cf9bcec..4c7f1e0 100644 --- a/src/components/goals/UpdateComment.tsx +++ b/src/components/goals/UpdateComment.tsx @@ -1,5 +1,5 @@ import { Avatar, Menu } from '@/ui' -import React, { useState } from 'react' +import React, { useRef, useState } from 'react' import { Markdown, A, LikeModal, useLikes, EditComment } from '@/components' import { DateTime } from 'luxon' import { UpdateCommentType } from 'src/pages' @@ -12,6 +12,8 @@ import { Trash, } from 'phosphor-react' import { User } from 'src/pages/members' +import { useMutation, useQueryClient } from 'react-query' +import toast from 'react-hot-toast' export type GoalUpdateType = { id: string @@ -30,9 +32,11 @@ export default function UpdateComment({ comment: UpdateCommentType isLastComment?: boolean }) { + const queryClient = useQueryClient() const [isInEditMode, setIsInEditMode] = useState(false) const postedOn = DateTime.fromMillis(comment.createdAt) const [session] = useSession() + const toastId = useRef('') const [isLikeModalOpen, setIsLikeModalOpen] = useState(false) const { count: likesCount, hasLiked, toggleLike } = useLikes({ initialCount: comment.likes.data, @@ -50,6 +54,38 @@ export default function UpdateComment({ }, }, }) + const { mutate: deleteComment } = useMutation( + () => { + return fetch(`/api/fauna/goals/delete-comment`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + id: comment.id, + }), + }).then((res) => { + if (!res.ok) { + throw new Error('something went wrong!!!') + } + return res.json() + }) + }, + { + onSuccess: () => { + toast.success('Deleted your comment!!', { + id: toastId.current, + icon: , + }) + queryClient.refetchQueries('/api/fauna/all-updates') + }, + onError: () => { + toast.error('Something went wrong!!!', { + id: toastId.current, + }) + }, + } + ) return (
  • {isInEditMode ? ( @@ -111,9 +147,9 @@ export default function UpdateComment({ { - // deleteUpdate() - // const id = toast.loading('Deleting your update...') - // toastId.current = id + deleteComment() + const id = toast.loading('Deleting your comment...') + toastId.current = id }} > Delete diff --git a/src/pages/api/fauna/goals/delete-comment.ts b/src/pages/api/fauna/goals/delete-comment.ts new file mode 100644 index 0000000..8ab3c7a --- /dev/null +++ b/src/pages/api/fauna/goals/delete-comment.ts @@ -0,0 +1,45 @@ +import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { getSession } from 'next-auth/client' + +import faunadb from 'faunadb' +import { User } from 'src/pages/members' +const q = faunadb.query +const isProduction = process.env.NODE_ENV === 'production' +const client = new faunadb.Client({ + secret: process.env.FAUNADB_SECRET ?? 'secret', + scheme: isProduction ? 'https' : 'http', + domain: isProduction ? 'db.fauna.com' : 'localhost', + ...(isProduction ? {} : { port: 8443 }), +}) + +const FaunaCreateHandler: NextApiHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + const session = await getSession({ req }) + + if (!session) { + return res.status(401).json({ message: 'Unauthorized' }) + } + const { id } = req.body + const userId = (session.user as User).id + try { + const commentDoc = q.Get(q.Ref(q.Collection('update_comments'), id)) + const commentPostedById = q.Select(['data', 'postedBy', 'id'], commentDoc) + const response = await client.query( + q.If( + q.Equals(commentPostedById, userId), + q.Delete(q.Ref(q.Collection('update_comments'), id)), + q.Abort('You are not authorized to delete this!!!') + ) + ) + + res.status(200).json({ response }) + } catch (error) { + console.error(error) + console.error({ msg: error.message }) + res.status(500).json({ message: error.description }) + } +} + +export default FaunaCreateHandler From b9f45432973c9be8e2be867de75b8ad940cac4eb Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Fri, 26 Feb 2021 12:42:54 +0530 Subject: [PATCH 017/115] Show members count in the members page --- src/components/members/Members.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/members/Members.tsx b/src/components/members/Members.tsx index e4d49c1..d487ae6 100644 --- a/src/components/members/Members.tsx +++ b/src/components/members/Members.tsx @@ -3,7 +3,16 @@ import Member from './Member' export default function Members({ users }: { users: User[] }) { return ( -
    +
    +
    +

    + Coderplex Community +

    +

    + {users.length}{' '} + people are a part of this amazing community. +

    +
      {users.map((user) => ( From 8a5e50c113cf8f51bfab29e9b9d9b48ae1de67f4 Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Fri, 26 Feb 2021 13:54:48 +0530 Subject: [PATCH 018/115] Add a deadline to goals --- src/components/goals/EditGoal.tsx | 17 +++++++++---- src/components/goals/GoalFeed.tsx | 3 +++ src/components/goals/GoalMeta.tsx | 24 +++++++++++++++++++ src/components/goals/NewGoal.tsx | 13 ++++++++-- src/pages/[username]/index.tsx | 2 ++ .../api/fauna/goals/all-goals-by-user.ts | 5 ++++ src/pages/api/fauna/goals/update-goal.ts | 3 ++- 7 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/components/goals/EditGoal.tsx b/src/components/goals/EditGoal.tsx index ec5d6ae..249cb7f 100644 --- a/src/components/goals/EditGoal.tsx +++ b/src/components/goals/EditGoal.tsx @@ -3,13 +3,12 @@ import { useForm } from 'react-hook-form' import { useMutation, useQueryClient } from 'react-query' import toast, { Toaster } from 'react-hot-toast' import { useEffect, useRef, useState } from 'react' -import { useSession } from 'next-auth/client' -import { User } from 'src/pages/members' import { Markdown, GoalType } from '@/components' type Inputs = { title: string description: string + deadline: Date } export default function EditGoal({ @@ -26,7 +25,6 @@ export default function EditGoal({ const queryClient = useQueryClient() const { register, handleSubmit, errors, trigger } = useForm() const toastId = useRef('') - const [session] = useSession() const { mutate } = useMutation( (data: Inputs) => fetch(`/api/fauna/goals/update-goal`, { @@ -39,6 +37,7 @@ export default function EditGoal({ title: data.title, description: data.description, creatorId: goal.creatorId, + deadline: data.deadline, }), }).then((res) => { if (!res.ok) { @@ -71,7 +70,7 @@ export default function EditGoal({
      -
      + + + + {descriptionStorage && ( +
      + {descriptionStorage} +
      + )} + +
      + + +
      +
      +
      +
      +
      + + ) +} diff --git a/src/pages/api/fauna/goals/edit-update.ts b/src/pages/api/fauna/goals/edit-update.ts new file mode 100644 index 0000000..aefcaf0 --- /dev/null +++ b/src/pages/api/fauna/goals/edit-update.ts @@ -0,0 +1,49 @@ +import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { getSession } from 'next-auth/client' + +import faunadb from 'faunadb' +import { User } from 'src/pages/members' +const q = faunadb.query +const isProduction = process.env.NODE_ENV === 'production' +const client = new faunadb.Client({ + secret: process.env.FAUNADB_SECRET ?? 'secret', + scheme: isProduction ? 'https' : 'http', + domain: isProduction ? 'db.fauna.com' : 'localhost', + ...(isProduction ? {} : { port: 8443 }), +}) + +const FaunaCreateHandler: NextApiHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + const session = await getSession({ req }) + + if (!session) { + return res.status(401).json({ message: 'Unauthorized' }) + } + const { id, description } = req.body + const userId = (session.user as User).id + try { + const updateDoc = q.Get(q.Ref(q.Collection('goal_updates'), id)) + const updatePostedById = q.Select(['data', 'postedBy', 'id'], updateDoc) + const response = await client.query( + q.If( + q.Equals(updatePostedById, userId), + q.Update(q.Ref(q.Collection('goal_updates'), id), { + data: { + description, + }, + }), + q.Abort('You are not authorized to edit this!!!') + ) + ) + + res.status(200).json({ response }) + } catch (error) { + console.error(error) + console.error({ msg: error.message }) + res.status(500).json({ message: error.description }) + } +} + +export default FaunaCreateHandler From fff599e7c0914f3a11956910f90e02709e1e333a Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Wed, 24 Feb 2021 16:49:55 +0530 Subject: [PATCH 060/115] Allow users to delete their updates --- src/components/HomePageFeed.tsx | 334 ++++++++++++--------- src/components/goals/EditGoal.tsx | 5 +- src/components/goals/EditUpdate.tsx | 5 +- src/components/goals/NewUpdate.tsx | 5 +- src/pages/api/fauna/goals/delete-update.ts | 45 +++ 5 files changed, 238 insertions(+), 156 deletions(-) create mode 100644 src/pages/api/fauna/goals/delete-update.ts diff --git a/src/components/HomePageFeed.tsx b/src/components/HomePageFeed.tsx index d45344f..76f39bf 100644 --- a/src/components/HomePageFeed.tsx +++ b/src/components/HomePageFeed.tsx @@ -13,9 +13,9 @@ import { import * as React from 'react' import { HomePageFeedUpdateType } from 'src/pages' import { DateTime } from 'luxon' -import { useMutation, useQuery } from 'react-query' +import { useMutation, useQuery, useQueryClient } from 'react-query' import classNames from 'classnames' -import { useEffect, useReducer, useState } from 'react' +import { useEffect, useReducer, useState, useRef } from 'react' import { signIn, useSession } from 'next-auth/client' import { User } from 'src/pages/members' import useFollowUser from './profile/useFollowUser' @@ -37,8 +37,9 @@ import { import { Goal } from './goals' import type { GoalResponse } from 'src/pages/[username]' import { scrollToContentWithId } from 'src/utils' -import { IconBrandDiscord, IconMenu } from 'tabler-icons' +import { IconBrandDiscord } from 'tabler-icons' import EditUpdate from './goals/EditUpdate' +import toast, { Toaster } from 'react-hot-toast' type LikeData = { count: number @@ -69,12 +70,14 @@ export function HomePageFeedUpdate({ update: HomePageFeedUpdateType setGoalId: () => void }) { + const queryClient = useQueryClient() const [isInEditMode, setIsInEditMode] = useState(false) const [isLikeModalOpen, setIsLikeModalOpen] = useState(false) const [session] = useSession() const [showComments, setShowComments] = useState(false) const { postedBy, createdAt: createdAtInMillis, goal, description } = update const createdAt = DateTime.fromMillis(createdAtInMillis) + const toastId = useRef('') const { isLoading, isError, data } = useQuery( ['api/fauna/has-liked', update.id], () => { @@ -106,6 +109,35 @@ export function HomePageFeedUpdate({ }) }) + const { mutate: deleteUpdate } = useMutation( + () => { + return fetch(`/api/fauna/goals/delete-update`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + id: update.id, + }), + }).then((res) => { + if (!res.ok) { + throw new Error('something went wrong!!!') + } + return res.json() + }) + }, + { + onSuccess: () => { + toast.success('Deleted your update!!', { + id: toastId.current, + icon: , + }) + queryClient.refetchQueries('/api/fauna/all-updates') + queryClient.refetchQueries(['/api/fauna/recent-updates', goal.id]) + }, + } + ) + const [{ count: likesCount, hasLiked }, dispatch] = useReducer( reducer, initialState @@ -121,161 +153,175 @@ export function HomePageFeedUpdate({ }, [data?.liked, isError, isLoading, update.likes.data]) return ( -
    • - {isInEditMode ? ( - setIsInEditMode(false)} - updateFromHomePage={true} - /> - ) : ( - <> -
      -
      -
      -
      - - - -
      -
      -

      - - {postedBy.name} + <> + +

    • + {isInEditMode ? ( + setIsInEditMode(false)} + updateFromHomePage={true} + /> + ) : ( + <> +
      +
      +
      +
      + + -

      -

      - -

      -
      +
      +
      +

      + + {postedBy.name} + +

      +

      + +

      +
      -
      -
      - - Open quick actions - - - } - > - setIsInEditMode(true)} +
      +
      + + Open quick actions + + + } > - Edit - - Delete - + setIsInEditMode(true)} + > + Edit + + { + deleteUpdate() + const id = toast.loading('Deleting your update...') + toastId.current = id + }} + > + Delete + +
      +
      -
    • -
      - - - - 🚀 Goal: {goal.title} - - -
      -
      -
      -
      - {description} -
      -
      -
      -
      - +
      - - - - - + +
      -
      -
      - - {showComments && ( - <> - - - {update.comments.data.map((comment, index) => ( - +
      + {description} +
      +
    +
    +
    + +
  • + + + {likesCount} + + likes + + + + + + + + + + + {showComments && ( + <> + + + {update.comments.data.map((comment, index) => ( + + {comment.description} + + ))} + + {session && } + + + )} + + )} + + ) } diff --git a/src/components/goals/EditGoal.tsx b/src/components/goals/EditGoal.tsx index 8ec1380..ec5d6ae 100644 --- a/src/components/goals/EditGoal.tsx +++ b/src/components/goals/EditGoal.tsx @@ -51,10 +51,7 @@ export default function EditGoal({ toast.success('You have successfully updated your goal.', { id: toastId.current, }) - queryClient.refetchQueries([ - '/api/fauna/goals/all-goals-by-user', - (session.user as User).id, - ]) + queryClient.refetchQueries('/api/fauna/goals/all-goals-by-user') onCancelClick() }, onError: () => { diff --git a/src/components/goals/EditUpdate.tsx b/src/components/goals/EditUpdate.tsx index 24d3d35..b6907d6 100644 --- a/src/components/goals/EditUpdate.tsx +++ b/src/components/goals/EditUpdate.tsx @@ -51,10 +51,7 @@ export default function EditUpdate({ toast.success('You have successfully edited the update.', { id: toastId.current, }) - queryClient.refetchQueries([ - '/api/fauna/goals/all-goals-by-user', - (session.user as User).id, - ]) + queryClient.refetchQueries('/api/fauna/goals/all-goals-by-user') if (updateFromHomePage) { queryClient.refetchQueries('/api/fauna/all-updates') queryClient.refetchQueries(['/api/fauna/recent-updates', goalId]) diff --git a/src/components/goals/NewUpdate.tsx b/src/components/goals/NewUpdate.tsx index 7ca686e..04fd4ca 100644 --- a/src/components/goals/NewUpdate.tsx +++ b/src/components/goals/NewUpdate.tsx @@ -45,10 +45,7 @@ export default function NewUpdate({ toast.success('You have successfully added an update.', { id: toastId.current, }) - queryClient.refetchQueries([ - '/api/fauna/goals/all-goals-by-user', - (session.user as User).id, - ]) + queryClient.refetchQueries('/api/fauna/goals/all-goals-by-user') if (updateFromHomePage) { queryClient.refetchQueries('/api/fauna/all-updates') queryClient.refetchQueries(['/api/fauna/recent-updates', goal.id]) diff --git a/src/pages/api/fauna/goals/delete-update.ts b/src/pages/api/fauna/goals/delete-update.ts new file mode 100644 index 0000000..c3a25b9 --- /dev/null +++ b/src/pages/api/fauna/goals/delete-update.ts @@ -0,0 +1,45 @@ +import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { getSession } from 'next-auth/client' + +import faunadb from 'faunadb' +import { User } from 'src/pages/members' +const q = faunadb.query +const isProduction = process.env.NODE_ENV === 'production' +const client = new faunadb.Client({ + secret: process.env.FAUNADB_SECRET ?? 'secret', + scheme: isProduction ? 'https' : 'http', + domain: isProduction ? 'db.fauna.com' : 'localhost', + ...(isProduction ? {} : { port: 8443 }), +}) + +const FaunaCreateHandler: NextApiHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + const session = await getSession({ req }) + + if (!session) { + return res.status(401).json({ message: 'Unauthorized' }) + } + const { id } = req.body + const userId = (session.user as User).id + try { + const updateDoc = q.Get(q.Ref(q.Collection('goal_updates'), id)) + const updatePostedById = q.Select(['data', 'postedBy', 'id'], updateDoc) + const response = await client.query( + q.If( + q.Equals(updatePostedById, userId), + q.Delete(q.Ref(q.Collection('goal_updates'), id)), + q.Abort('You are not authorized to delete this!!!') + ) + ) + + res.status(200).json({ response }) + } catch (error) { + console.error(error) + console.error({ msg: error.message }) + res.status(500).json({ message: error.description }) + } +} + +export default FaunaCreateHandler From 2ee332aa9446881d868c6b93458b333711d1c089 Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Wed, 24 Feb 2021 17:31:46 +0530 Subject: [PATCH 061/115] Only show quick action menu for the current user's updates --- src/components/HomePageFeed.tsx | 71 +++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/src/components/HomePageFeed.tsx b/src/components/HomePageFeed.tsx index 76f39bf..339d1fa 100644 --- a/src/components/HomePageFeed.tsx +++ b/src/components/HomePageFeed.tsx @@ -135,6 +135,11 @@ export function HomePageFeedUpdate({ queryClient.refetchQueries('/api/fauna/all-updates') queryClient.refetchQueries(['/api/fauna/recent-updates', goal.id]) }, + onError: () => { + toast.error('Something went wrong!!!', { + id: toastId.current, + }) + }, } ) @@ -192,38 +197,44 @@ export function HomePageFeedUpdate({

    -
    -
    - - Open quick actions - - - } - > - setIsInEditMode(true)} + {session && (session.user as User).id === update.postedBy.id && ( +
    +
    + + + Open quick actions + + + + } > - Edit - - { - deleteUpdate() - const id = toast.loading('Deleting your update...') - toastId.current = id - }} - > - Delete - - + setIsInEditMode(true)} + > + Edit + + { + deleteUpdate() + const id = toast.loading( + 'Deleting your update...' + ) + toastId.current = id + }} + > + Delete + +
    +
    - + )}
    + + +
    + diff --git a/src/components/goals/index.tsx b/src/components/goals/index.tsx index 6bead33..2bfc196 100644 --- a/src/components/goals/index.tsx +++ b/src/components/goals/index.tsx @@ -11,3 +11,4 @@ export type { GoalType } from './GoalFeed' export { default as UpdateComment } from './UpdateComment' export { default as NewComment } from './NewComment' export { default as UpdateComments, UpdateCommentsList } from './UpdateComments' +export { default as EditUpdate } from './EditUpdate' diff --git a/src/components/index.tsx b/src/components/index.tsx index 61442e4..eef4d9a 100644 --- a/src/components/index.tsx +++ b/src/components/index.tsx @@ -12,3 +12,4 @@ export { default as HomePageFeed } from './HomePageFeed' export { default as Hero } from './Hero' export * from './modal' export { Pre } from './Code' +export { useLikes } from './useLikes' diff --git a/src/pages/api/fauna/all-updates.ts b/src/pages/api/fauna/all-updates.ts index 6c19f9a..8b7b33b 100644 --- a/src/pages/api/fauna/all-updates.ts +++ b/src/pages/api/fauna/all-updates.ts @@ -47,6 +47,16 @@ const FaunaCreateHandler: NextApiHandler = async ( createdAt: q.ToMillis( q.Select(['data', 'timestamps', 'createdAt'], commentDoc) ), + likes: q.Count( + q.Filter( + q.Paginate( + q.Match(q.Index('all_likes_by_comment'), commentRef) + ), + (commentLikeRef) => { + return q.Select(['data', 'liked'], q.Get(commentLikeRef)) + } + ) + ), postedBy: { id: q.Select(['ref', 'id'], postedByDoc), name: q.Select(['data', 'name'], postedByDoc, null), diff --git a/src/pages/api/fauna/has-liked-comment.ts b/src/pages/api/fauna/has-liked-comment.ts new file mode 100644 index 0000000..9efc0f0 --- /dev/null +++ b/src/pages/api/fauna/has-liked-comment.ts @@ -0,0 +1,52 @@ +import { User } from 'src/pages/members' +import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { getSession } from 'next-auth/client' + +import faunadb from 'faunadb' +const q = faunadb.query +const isProduction = process.env.NODE_ENV === 'production' +const client = new faunadb.Client({ + secret: process.env.FAUNADB_SECRET ?? 'secret', + scheme: isProduction ? 'https' : 'http', + domain: isProduction ? 'db.fauna.com' : 'localhost', + ...(isProduction ? {} : { port: 8443 }), +}) + +const FaunaCreateHandler: NextApiHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + const session = await getSession({ req }) + + if (!session) { + return res.status(200).json({ liked: false }) + } + + const userId = (session.user as User).id + + try { + const { commentId } = req.body + const response = await client.query( + q.Let( + { + ref: q.Match(q.Index('unique_comment_user_like'), [ + q.Ref(q.Collection('update_comments'), commentId), + q.Ref(q.Collection('users'), userId), + ]), + }, + q.If( + q.Exists(q.Var('ref')), + q.Select(['data', 'liked'], q.Get(q.Var('ref'))), + false + ) + ) + ) + res.status(200).json({ liked: response }) + } catch (error) { + console.error(error) + console.error({ msg: error.message }) + res.status(500).json({ message: error.message }) + } +} + +export default FaunaCreateHandler diff --git a/src/pages/api/fauna/toggle-comment-like.ts b/src/pages/api/fauna/toggle-comment-like.ts new file mode 100644 index 0000000..f92ad6a --- /dev/null +++ b/src/pages/api/fauna/toggle-comment-like.ts @@ -0,0 +1,75 @@ +import { User } from 'src/pages/members' +import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { getSession } from 'next-auth/client' + +import faunadb from 'faunadb' +const q = faunadb.query +const isProduction = process.env.NODE_ENV === 'production' +const client = new faunadb.Client({ + secret: process.env.FAUNADB_SECRET ?? 'secret', + scheme: isProduction ? 'https' : 'http', + domain: isProduction ? 'db.fauna.com' : 'localhost', + ...(isProduction ? {} : { port: 8443 }), +}) + +const FaunaCreateHandler: NextApiHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + const session = await getSession({ req }) + + if (!session) { + return res.status(401).json({ message: 'Unauthorized' }) + } + + const userId = (session.user as User).id + + try { + const { commentId } = req.body + const response = await client.query( + q.Let( + { + ref: q.Match(q.Index('unique_comment_user_like'), [ + q.Ref(q.Collection('update_comments'), commentId), + q.Ref(q.Collection('users'), userId), + ]), + }, + q.If( + q.Exists(q.Var('ref')), + q.Update( + q.Ref( + q.Collection('comment_likes'), + q.Select(['ref', 'id'], q.Get(q.Var('ref'))) + ), + { + data: { + liked: q.Not(q.Select(['data', 'liked'], q.Get(q.Var('ref')))), + timestamps: { + updatedAt: q.Now(), + }, + }, + } + ), + q.Create(q.Collection('comment_likes'), { + data: { + user: q.Ref(q.Collection('users'), userId), + comment: q.Ref(q.Collection('update_comments'), commentId), + liked: true, + timestamps: { + createdAt: q.Now(), + updatedAt: q.Now(), + }, + }, + }) + ) + ) + ) + res.status(200).json({ response }) + } catch (error) { + console.error(error) + console.error({ msg: error.message }) + res.status(500).json({ message: error.message }) + } +} + +export default FaunaCreateHandler diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 0296894..80ea9db 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -8,6 +8,9 @@ export type UpdateCommentType = { description: string createdAt: number postedBy: User + likes: { + data: number + } } export type HomePageFeedUpdateType = { From 4e4bc189edc0c750c670e996fcd0b79ded9b1289 Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Thu, 25 Feb 2021 13:33:12 +0530 Subject: [PATCH 066/115] Add a way to edit comment --- src/components/HomePageFeed.tsx | 1 + src/components/goals/EditComment.tsx | 125 +++++++++++++++ src/components/goals/UpdateComment.tsx | 182 ++++++++++++++-------- src/components/goals/index.tsx | 1 + src/pages/api/fauna/goals/edit-comment.ts | 49 ++++++ 5 files changed, 294 insertions(+), 64 deletions(-) create mode 100644 src/components/goals/EditComment.tsx create mode 100644 src/pages/api/fauna/goals/edit-comment.ts diff --git a/src/components/HomePageFeed.tsx b/src/components/HomePageFeed.tsx index b243022..eaeec33 100644 --- a/src/components/HomePageFeed.tsx +++ b/src/components/HomePageFeed.tsx @@ -265,6 +265,7 @@ export function HomePageFeedUpdate({ {update.comments.data.map((comment, index) => ( void +}) { + const [descriptionStorage, setDescriptionStorage] = useState( + comment.description + ) + const queryClient = useQueryClient() + const [session, loading] = useSession() + const { handleSubmit, register, errors, reset } = useForm() + const toastId = useRef('') + const { mutate } = useMutation( + (data: Inputs) => + fetch(`/api/fauna/goals/edit-comment`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + id: comment.id, + description: data.description, + }), + }).then((res) => { + if (!res.ok) { + throw new Error('Something went wrong!!') + } + return res.json() + }), + { + onSuccess: () => { + toast.success('You have successfully updated your comment.', { + id: toastId.current, + }) + queryClient.refetchQueries('/api/fauna/all-updates') + cancelEditMode() + reset() + }, + onError: () => { + toast.error('Something went wrong!!!', { id: toastId.current }) + }, + } + ) + const onSubmit = (data: Inputs) => { + const id = toast.loading('Saving your comment...') + toastId.current = id + mutate(data) + setDescriptionStorage('') + } + if (loading) { + return

    loading...

    + } + return ( + <> + +
    +
    +
    +
    + + + +
    +
    +
    +
    + + {descriptionStorage && ( +
    + {descriptionStorage} +
    + )} + +
    + + +
    +
    +
    +
    +
    + + ) +} diff --git a/src/components/goals/UpdateComment.tsx b/src/components/goals/UpdateComment.tsx index d2ea689..cf9bcec 100644 --- a/src/components/goals/UpdateComment.tsx +++ b/src/components/goals/UpdateComment.tsx @@ -1,11 +1,17 @@ -import { Avatar } from '@/ui' +import { Avatar, Menu } from '@/ui' import React, { useState } from 'react' -import { Markdown, A, LikeModal, useLikes } from '@/components' +import { Markdown, A, LikeModal, useLikes, EditComment } from '@/components' import { DateTime } from 'luxon' import { UpdateCommentType } from 'src/pages' import { useSession } from 'next-auth/client' import classNames from 'classnames' -import { ThumbsUp } from 'phosphor-react' +import { + DotsThreeOutlineVertical, + Pencil, + ThumbsUp, + Trash, +} from 'phosphor-react' +import { User } from 'src/pages/members' export type GoalUpdateType = { id: string @@ -14,14 +20,17 @@ export type GoalUpdateType = { } export default function UpdateComment({ + updateId, comment, children, isLastComment = false, }: { + updateId: string children: string comment: UpdateCommentType isLastComment?: boolean }) { + const [isInEditMode, setIsInEditMode] = useState(false) const postedOn = DateTime.fromMillis(comment.createdAt) const [session] = useSession() const [isLikeModalOpen, setIsLikeModalOpen] = useState(false) @@ -43,75 +52,120 @@ export default function UpdateComment({ }) return (
  • -
    -
    -
    - - - -
    -
    -
    - -

    - Posted on{' '} - -

    + {isInEditMode ? ( + setIsInEditMode(false)} + /> + ) : ( +
    +
    + -
    -
    - {children} +
    +
    +
    + +

    + Posted on{' '} + +

    +
    + {session && (session.user as User).id === comment.postedBy.id && ( +
    +
    + + Open quick actions + + + } + > + setIsInEditMode(true)} + > + Edit + + { + // deleteUpdate() + // const id = toast.loading('Deleting your update...') + // toastId.current = id + }} + > + Delete + + +
    +
    + )} +
    +
    +
    + {children} +
    -
    -
    -
    - - + - - {likesCount} - - likes - - - + +
    -
    + )}
  • ) } diff --git a/src/components/goals/index.tsx b/src/components/goals/index.tsx index 2bfc196..c567cde 100644 --- a/src/components/goals/index.tsx +++ b/src/components/goals/index.tsx @@ -12,3 +12,4 @@ export { default as UpdateComment } from './UpdateComment' export { default as NewComment } from './NewComment' export { default as UpdateComments, UpdateCommentsList } from './UpdateComments' export { default as EditUpdate } from './EditUpdate' +export { default as EditComment } from './EditComment' diff --git a/src/pages/api/fauna/goals/edit-comment.ts b/src/pages/api/fauna/goals/edit-comment.ts new file mode 100644 index 0000000..bf11f14 --- /dev/null +++ b/src/pages/api/fauna/goals/edit-comment.ts @@ -0,0 +1,49 @@ +import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { getSession } from 'next-auth/client' + +import faunadb from 'faunadb' +import { User } from 'src/pages/members' +const q = faunadb.query +const isProduction = process.env.NODE_ENV === 'production' +const client = new faunadb.Client({ + secret: process.env.FAUNADB_SECRET ?? 'secret', + scheme: isProduction ? 'https' : 'http', + domain: isProduction ? 'db.fauna.com' : 'localhost', + ...(isProduction ? {} : { port: 8443 }), +}) + +const FaunaCreateHandler: NextApiHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + const session = await getSession({ req }) + + if (!session) { + return res.status(401).json({ message: 'Unauthorized' }) + } + const { id, description } = req.body + const userId = (session.user as User).id + try { + const commentDoc = q.Get(q.Ref(q.Collection('update_comments'), id)) + const commentPostedById = q.Select(['data', 'postedBy', 'id'], commentDoc) + const response = await client.query( + q.If( + q.Equals(commentPostedById, userId), + q.Update(q.Ref(q.Collection('update_comments'), id), { + data: { + description, + }, + }), + q.Abort('You are not authorized to edit this!!!') + ) + ) + + res.status(200).json({ response }) + } catch (error) { + console.error(error) + console.error({ msg: error.message }) + res.status(500).json({ message: error.description }) + } +} + +export default FaunaCreateHandler From 8012cb4e0dc04a5daec332106ee9a630f02722dd Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Thu, 25 Feb 2021 13:36:56 +0530 Subject: [PATCH 067/115] Add a way to delete comment --- src/components/goals/UpdateComment.tsx | 44 ++++++++++++++++++-- src/pages/api/fauna/goals/delete-comment.ts | 45 +++++++++++++++++++++ 2 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 src/pages/api/fauna/goals/delete-comment.ts diff --git a/src/components/goals/UpdateComment.tsx b/src/components/goals/UpdateComment.tsx index cf9bcec..4c7f1e0 100644 --- a/src/components/goals/UpdateComment.tsx +++ b/src/components/goals/UpdateComment.tsx @@ -1,5 +1,5 @@ import { Avatar, Menu } from '@/ui' -import React, { useState } from 'react' +import React, { useRef, useState } from 'react' import { Markdown, A, LikeModal, useLikes, EditComment } from '@/components' import { DateTime } from 'luxon' import { UpdateCommentType } from 'src/pages' @@ -12,6 +12,8 @@ import { Trash, } from 'phosphor-react' import { User } from 'src/pages/members' +import { useMutation, useQueryClient } from 'react-query' +import toast from 'react-hot-toast' export type GoalUpdateType = { id: string @@ -30,9 +32,11 @@ export default function UpdateComment({ comment: UpdateCommentType isLastComment?: boolean }) { + const queryClient = useQueryClient() const [isInEditMode, setIsInEditMode] = useState(false) const postedOn = DateTime.fromMillis(comment.createdAt) const [session] = useSession() + const toastId = useRef('') const [isLikeModalOpen, setIsLikeModalOpen] = useState(false) const { count: likesCount, hasLiked, toggleLike } = useLikes({ initialCount: comment.likes.data, @@ -50,6 +54,38 @@ export default function UpdateComment({ }, }, }) + const { mutate: deleteComment } = useMutation( + () => { + return fetch(`/api/fauna/goals/delete-comment`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + id: comment.id, + }), + }).then((res) => { + if (!res.ok) { + throw new Error('something went wrong!!!') + } + return res.json() + }) + }, + { + onSuccess: () => { + toast.success('Deleted your comment!!', { + id: toastId.current, + icon: , + }) + queryClient.refetchQueries('/api/fauna/all-updates') + }, + onError: () => { + toast.error('Something went wrong!!!', { + id: toastId.current, + }) + }, + } + ) return (
  • {isInEditMode ? ( @@ -111,9 +147,9 @@ export default function UpdateComment({ { - // deleteUpdate() - // const id = toast.loading('Deleting your update...') - // toastId.current = id + deleteComment() + const id = toast.loading('Deleting your comment...') + toastId.current = id }} > Delete diff --git a/src/pages/api/fauna/goals/delete-comment.ts b/src/pages/api/fauna/goals/delete-comment.ts new file mode 100644 index 0000000..8ab3c7a --- /dev/null +++ b/src/pages/api/fauna/goals/delete-comment.ts @@ -0,0 +1,45 @@ +import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { getSession } from 'next-auth/client' + +import faunadb from 'faunadb' +import { User } from 'src/pages/members' +const q = faunadb.query +const isProduction = process.env.NODE_ENV === 'production' +const client = new faunadb.Client({ + secret: process.env.FAUNADB_SECRET ?? 'secret', + scheme: isProduction ? 'https' : 'http', + domain: isProduction ? 'db.fauna.com' : 'localhost', + ...(isProduction ? {} : { port: 8443 }), +}) + +const FaunaCreateHandler: NextApiHandler = async ( + req: NextApiRequest, + res: NextApiResponse +) => { + const session = await getSession({ req }) + + if (!session) { + return res.status(401).json({ message: 'Unauthorized' }) + } + const { id } = req.body + const userId = (session.user as User).id + try { + const commentDoc = q.Get(q.Ref(q.Collection('update_comments'), id)) + const commentPostedById = q.Select(['data', 'postedBy', 'id'], commentDoc) + const response = await client.query( + q.If( + q.Equals(commentPostedById, userId), + q.Delete(q.Ref(q.Collection('update_comments'), id)), + q.Abort('You are not authorized to delete this!!!') + ) + ) + + res.status(200).json({ response }) + } catch (error) { + console.error(error) + console.error({ msg: error.message }) + res.status(500).json({ message: error.description }) + } +} + +export default FaunaCreateHandler From 85eddba340abf7558cbb8651b79087e102468874 Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Fri, 26 Feb 2021 12:42:54 +0530 Subject: [PATCH 068/115] Show members count in the members page --- src/components/members/Members.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/members/Members.tsx b/src/components/members/Members.tsx index e4d49c1..d487ae6 100644 --- a/src/components/members/Members.tsx +++ b/src/components/members/Members.tsx @@ -3,7 +3,16 @@ import Member from './Member' export default function Members({ users }: { users: User[] }) { return ( -
    +
    +
    +

    + Coderplex Community +

    +

    + {users.length}{' '} + people are a part of this amazing community. +

    +
      {users.map((user) => ( From 3915fa8d96a62add53d79759889b131631104e80 Mon Sep 17 00:00:00 2001 From: Bhanu Teja Pachipulusu Date: Fri, 26 Feb 2021 13:54:48 +0530 Subject: [PATCH 069/115] Add a deadline to goals --- src/components/goals/EditGoal.tsx | 17 +++++++++---- src/components/goals/GoalFeed.tsx | 3 +++ src/components/goals/GoalMeta.tsx | 24 +++++++++++++++++++ src/components/goals/NewGoal.tsx | 13 ++++++++-- src/pages/[username]/index.tsx | 2 ++ .../api/fauna/goals/all-goals-by-user.ts | 5 ++++ src/pages/api/fauna/goals/update-goal.ts | 3 ++- 7 files changed, 60 insertions(+), 7 deletions(-) diff --git a/src/components/goals/EditGoal.tsx b/src/components/goals/EditGoal.tsx index ec5d6ae..249cb7f 100644 --- a/src/components/goals/EditGoal.tsx +++ b/src/components/goals/EditGoal.tsx @@ -3,13 +3,12 @@ import { useForm } from 'react-hook-form' import { useMutation, useQueryClient } from 'react-query' import toast, { Toaster } from 'react-hot-toast' import { useEffect, useRef, useState } from 'react' -import { useSession } from 'next-auth/client' -import { User } from 'src/pages/members' import { Markdown, GoalType } from '@/components' type Inputs = { title: string description: string + deadline: Date } export default function EditGoal({ @@ -26,7 +25,6 @@ export default function EditGoal({ const queryClient = useQueryClient() const { register, handleSubmit, errors, trigger } = useForm() const toastId = useRef('') - const [session] = useSession() const { mutate } = useMutation( (data: Inputs) => fetch(`/api/fauna/goals/update-goal`, { @@ -39,6 +37,7 @@ export default function EditGoal({ title: data.title, description: data.description, creatorId: goal.creatorId, + deadline: data.deadline, }), }).then((res) => { if (!res.ok) { @@ -71,7 +70,7 @@ export default function EditGoal({
      -
      + + +