diff --git a/.circleci/config.yml b/.circleci/config.yml index fabcb0254c..3cd7879dfb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -275,14 +275,14 @@ workflows: filters: branches: only: - - feature/poc-recommender-sub-2 + - develop # This is alternate dev env for parallel testing - "build-test": context : org-global filters: branches: only: - - feature/poc-recommender-sub-2 + - free # This is alternate dev env for parallel testing - "build-qa": context : org-global @@ -296,7 +296,7 @@ workflows: filters: branches: only: - - feature/poc-recommender-sub-2 + - free # This is stage env for production QA releases - "build-prod-staging": context : org-global @@ -304,6 +304,7 @@ workflows: branches: only: - develop + - nav-vanilla-forum - "approve-smoke-test-on-staging": type: approval requires: diff --git a/Dockerfile b/Dockerfile index 59d39c94bc..343cd978b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -65,6 +65,7 @@ ARG TC_M2M_AUTH0_URL ARG AUTH_SECRET ARG COMMUNITY_APP_URL +ARG GSHEETS_API_KEY ################################################################################ # Setting of environment variables in the Docker image. @@ -120,6 +121,7 @@ ENV CONTENTFUL_EDU_CDN_API_KEY=$CONTENTFUL_EDU_CDN_API_KEY ENV CONTENTFUL_EDU_PREVIEW_API_KEY=$CONTENTFUL_EDU_PREVIEW_API_KEY ENV RECRUITCRM_API_KEY=$RECRUITCRM_API_KEY ENV COMMUNITY_APP_URL=$COMMUNITY_APP_URL +ENV GSHEETS_API_KEY=$GSHEETS_API_KEY ################################################################################ # Testing and build of the application inside the container. diff --git a/__tests__/shared/components/Header/__snapshots__/index.jsx.snap b/__tests__/shared/components/Header/__snapshots__/index.jsx.snap index 06761c8d88..323a4e16e7 100644 --- a/__tests__/shared/components/Header/__snapshots__/index.jsx.snap +++ b/__tests__/shared/components/Header/__snapshots__/index.jsx.snap @@ -110,8 +110,7 @@ exports[`Default render 1`] = ` "title": "Programs", }, Object { - "href": "https://apps.topcoder-dev.com/forums", - "openNewTab": true, + "href": "https://vanilla.topcoder-dev.com", "title": "Forums", }, Object { diff --git a/__tests__/shared/components/Settings/Preferences/Email/__snapshots__/index.jsx.snap b/__tests__/shared/components/Settings/Preferences/Email/__snapshots__/index.jsx.snap index ab117b50c9..445b116422 100644 --- a/__tests__/shared/components/Settings/Preferences/Email/__snapshots__/index.jsx.snap +++ b/__tests__/shared/components/Settings/Preferences/Email/__snapshots__/index.jsx.snap @@ -10,69 +10,48 @@ exports[`renders email preferences setting page correctly 1`] = ` E-Mail Preferences
- Your preferences -
-
- Challenge Pipeline page." - value="Pipeline" - /> - Gig Work page." - value="Gig Work" - /> - - - - Topcoder Open you should definitely be subscribing to this one. Expect an update in your mailbox every Tuesday!" - value="TCO Tuesdays" - /> - +

+ You are not subscribed to receive Topcoder emails +

+

+ If this was a mistake or if you would like to resubscribe, please click the button below. +

+
+ + + + +
`; diff --git a/__tests__/shared/components/__snapshots__/TopcoderFooter.jsx.snap b/__tests__/shared/components/__snapshots__/TopcoderFooter.jsx.snap index 512f201fb3..bc62da49cb 100644 --- a/__tests__/shared/components/__snapshots__/TopcoderFooter.jsx.snap +++ b/__tests__/shared/components/__snapshots__/TopcoderFooter.jsx.snap @@ -185,7 +185,7 @@ exports[`Matches shallow shapshot 1`] = ` className="src-shared-components-TopcoderFooter-___style__link___3-nzm" > Forums diff --git a/__tests__/shared/components/challenge-listing/__snapshots__/index.jsx.snap b/__tests__/shared/components/challenge-listing/__snapshots__/index.jsx.snap index f3b861cd91..351bba4c01 100644 --- a/__tests__/shared/components/challenge-listing/__snapshots__/index.jsx.snap +++ b/__tests__/shared/components/challenge-listing/__snapshots__/index.jsx.snap @@ -5,6 +5,9 @@ exports[`Matches shallow shapshot 1 shapshot 1 1`] = ` className="src-shared-components-challenge-listing-___style__ChallengeFiltersExample___3IjeI" id="challengeFilterContainer" > +
@@ -21,41 +24,34 @@ exports[`Matches shallow shapshot 1 shapshot 1 1`] = ` setFilterState={[MockFunction]} />
-
- - -
+ `; @@ -65,6 +61,9 @@ exports[`Matches shallow shapshot 2 shapshot 2 1`] = ` className="src-shared-components-challenge-listing-___style__ChallengeFiltersExample___3IjeI" id="challengeFilterContainer" > +
@@ -81,41 +80,34 @@ exports[`Matches shallow shapshot 2 shapshot 2 1`] = ` setFilterState={[MockFunction]} />
-
- - -
+ `; diff --git a/build.sh b/build.sh index 8c4660937b..865bd28537 100755 --- a/build.sh +++ b/build.sh @@ -44,6 +44,7 @@ docker build -t $TAG \ --build-arg CONTENTFUL_COMCAST_CDN_API_KEY=$CONTENTFUL_COMCAST_CDN_API_KEY \ --build-arg CONTENTFUL_COMCAST_PREVIEW_API_KEY=$CONTENTFUL_COMCAST_PREVIEW_API_KEY \ --build-arg RECRUITCRM_API_KEY=$RECRUITCRM_API_KEY \ + --build-arg GSHEETS_API_KEY=$GSHEETS_API_KEY \ --build-arg COMMUNITY_APP_URL=$COMMUNITY_APP_URL . # Copies "node_modules" from the created image, if necessary for caching. diff --git a/config/custom-environment-variables.js b/config/custom-environment-variables.js index 51264f7d73..ffb0182dda 100644 --- a/config/custom-environment-variables.js +++ b/config/custom-environment-variables.js @@ -104,4 +104,5 @@ module.exports = { AUTH0_PROXY_SERVER_URL: 'TC_M2M_AUTH0_PROXY_SERVER_URL', TOKEN_CACHE_TIME: 'TOKEN_CACHE_TIME', }, + GSHEETS_API_KEY: 'GSHEETS_API_KEY', }; diff --git a/config/default.js b/config/default.js index 9f7fed509e..ddba003d31 100644 --- a/config/default.js +++ b/config/default.js @@ -111,6 +111,7 @@ module.exports = { BLOG_FEED: 'https://www.topcoder.com/blog/feed/', COMMUNITY: 'https://community.topcoder-dev.com', FORUMS: 'https://apps.topcoder-dev.com/forums', + FORUMS_VANILLA: 'https://vanilla.topcoder-dev.com', HELP: 'https://www.topcoder.com/thrive/tracks?track=Topcoder&tax=Help%20Articles', SUBMISSION_REVIEW: 'https://submission-review.topcoder-dev.com', @@ -249,6 +250,8 @@ module.exports = { RECRUITCRM_API_KEY: '', }, + GSHEETS_API_KEY: 'AIzaSyBRdKySN5JNCb2H6ZxJdTTvp3cWU51jiOQ', + AUTH_CONFIG: { AUTH0_URL: 'TC_M2M_AUTH0_URL', AUTH0_AUDIENCE: 'TC_M2M_AUDIENCE', @@ -358,8 +361,7 @@ module.exports = { }, { title: 'Forums', - href: 'https://apps.topcoder-dev.com/forums', - openNewTab: true, + href: 'https://vanilla.topcoder-dev.com', }, { title: 'Statistics', @@ -412,4 +414,5 @@ module.exports = { GUIKIT: { DEBOUNCE_ON_CHANGE_TIME: 150, }, + ENABLE_RECOMMENDER: true, }; diff --git a/config/production.js b/config/production.js index 1ab2d4fb87..f83da0fbc1 100644 --- a/config/production.js +++ b/config/production.js @@ -31,6 +31,7 @@ module.exports = { HOME: '/my-dashboard', COMMUNITY: 'https://community.topcoder.com', FORUMS: 'https://apps.topcoder.com/forums', + FORUMS_VANILLA: 'https://discussions.topcoder.com', HELP: 'https://www.topcoder.com/thrive/tracks?track=Topcoder&tax=Help%20Articles', SUBMISSION_REVIEW: 'https://submission-review.topcoder.com', MEMBER: 'https://member.topcoder.com', @@ -165,8 +166,7 @@ module.exports = { }, { title: 'Forums', - href: 'https://apps.topcoder.com/forums', - openNewTab: true, + href: 'https://discussions.topcoder.com', }, { title: 'Statistics', @@ -213,4 +213,5 @@ module.exports = { TC_EDU_ARTICLES_PATH: '/articles', TC_EDU_SEARCH_PATH: '/search', TC_EDU_SEARCH_BAR_MAX_RESULTS_EACH_GROUP: 3, + ENABLE_RECOMMENDER: true, }; diff --git a/package-lock.json b/package-lock.json index 1e5adfca69..d0f67f50af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -703,17 +703,22 @@ "dev": true }, "@babel/register": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.9.0.tgz", - "integrity": "sha512-Tv8Zyi2J2VRR8g7pC5gTeIN8Ihultbmk0ocyNz8H2nEZbmhp1N6q0A1UGsQbDvGP/sNinQKUHf3SqXwqjtFv4Q==", + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.12.13.tgz", + "integrity": "sha512-fnCeRXj970S9seY+973oPALQg61TRvAaW0nRDe1f4ytKqM3fZgsNXewTZWmqZedg74LFIRpg/11dsrPZZvYs2g==", "requires": { "find-cache-dir": "2.1.0", - "lodash": "4.17.15", + "lodash": "4.17.20", "make-dir": "2.1.0", "pirates": "4.0.1", "source-map-support": "0.5.19" }, "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -724,8 +729,8 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "requires": { - "buffer-from": "1.1.1", - "source-map": "0.6.1" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } } } @@ -1333,16 +1338,21 @@ "resolved": "https://registry.npmjs.org/@tanem/svg-injector/-/svg-injector-1.2.1.tgz", "integrity": "sha512-mA5Q5ulPoGQ+e08Vts1R6xw2QU0BKEnMH/KcqoYoS7Gk6imvMTpyFPeu1g+NOZObSIoAzA3/kRzY8m96cEBA2A==" }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + }, "@topcoder-platform/tc-auth-lib": { "version": "github:topcoder-platform/tc-auth-lib#68fdc22464810c51b703a33e529cdbd6d09437de", "requires": { - "lodash": "4.17.20" + "lodash": "4.17.21" }, "dependencies": { "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" } } }, @@ -1351,7 +1361,7 @@ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", "requires": { - "@types/connect": "3.4.33", + "@types/connect": "3.4.34", "@types/node": "14.0.1" } }, @@ -1362,9 +1372,9 @@ "dev": true }, "@types/connect": { - "version": "3.4.33", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", - "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", + "version": "3.4.34", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz", + "integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==", "requires": { "@types/node": "14.0.1" } @@ -1376,14 +1386,14 @@ "dev": true }, "@types/express": { - "version": "4.17.6", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.6.tgz", - "integrity": "sha512-n/mr9tZI83kd4azlPG5y997C/M4DNABK9yErhFM6hKdym4kkmd9j0vtsJyjFIwfRBxtrxZtAfGZCNRIBMFLK5w==", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.11.tgz", + "integrity": "sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg==", "requires": { "@types/body-parser": "1.19.0", - "@types/express-serve-static-core": "4.17.7", - "@types/qs": "6.9.2", - "@types/serve-static": "1.13.3" + "@types/express-serve-static-core": "4.17.18", + "@types/qs": "6.9.5", + "@types/serve-static": "1.13.9" } }, "@types/express-jwt": { @@ -1391,17 +1401,17 @@ "resolved": "https://registry.npmjs.org/@types/express-jwt/-/express-jwt-0.0.42.tgz", "integrity": "sha512-WszgUddvM1t5dPpJ3LhWNH8kfNN8GPIBrAGxgIYXVCEGx6Bx4A036aAuf/r5WH9DIEdlmp7gHOYvSM6U87B0ag==", "requires": { - "@types/express": "4.17.6", + "@types/express": "4.17.11", "@types/express-unless": "0.5.1" } }, "@types/express-serve-static-core": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.7.tgz", - "integrity": "sha512-EMgTj/DF9qpgLXyc+Btimg+XoH7A2liE8uKul8qSmMTHCeNYzydDKFdsJskDvw42UsesCnhO63dO0Grbj8J4Dw==", + "version": "4.17.18", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz", + "integrity": "sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA==", "requires": { "@types/node": "14.0.1", - "@types/qs": "6.9.2", + "@types/qs": "6.9.5", "@types/range-parser": "1.2.3" } }, @@ -1410,7 +1420,7 @@ "resolved": "https://registry.npmjs.org/@types/express-unless/-/express-unless-0.5.1.tgz", "integrity": "sha512-5fuvg7C69lemNgl0+v+CUxDYWVPSfXHhJPst4yTLcqi4zKJpORCxnDrnnilk3k0DTq/WrAUdvXFs01+vUqUZHw==", "requires": { - "@types/express": "4.17.6" + "@types/express": "4.17.11" } }, "@types/glob": { @@ -1425,9 +1435,9 @@ } }, "@types/mime": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz", - "integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==" + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, "@types/minimatch": { "version": "3.0.3", @@ -1459,9 +1469,9 @@ "dev": true }, "@types/qs": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.2.tgz", - "integrity": "sha512-a9bDi4Z3zCZf4Lv1X/vwnvbbDYSNz59h3i3KdyuYYN+YrLjSeJD0dnphdULDfySvUv6Exy/O0K6wX/kQpnPQ+A==" + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", + "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==" }, "@types/range-parser": { "version": "1.2.3", @@ -1469,12 +1479,12 @@ "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" }, "@types/serve-static": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz", - "integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==", + "version": "1.13.9", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz", + "integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==", "requires": { - "@types/express-serve-static-core": "4.17.7", - "@types/mime": "2.0.2" + "@types/mime": "1.3.2", + "@types/node": "14.0.1" } }, "@types/unist": { @@ -1712,6 +1722,14 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "5.0.1" + } + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -1838,6 +1856,29 @@ } } }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "airbnb-prop-types": { "version": "2.15.0", "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.15.0.tgz", @@ -2100,8 +2141,7 @@ "arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" }, "asap": { "version": "2.0.6", @@ -2258,17 +2298,86 @@ "integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==" }, "auth0-js": { - "version": "9.13.2", - "resolved": "https://registry.npmjs.org/auth0-js/-/auth0-js-9.13.2.tgz", - "integrity": "sha512-gWlf+X3XhCT9JboYpGviflv0pHcaHFPGtkLXiebyJohHDKddiu2rZkezp9kZHEoXqxhtNqgWuuaXkcla5JtnXg==", + "version": "9.14.3", + "resolved": "https://registry.npmjs.org/auth0-js/-/auth0-js-9.14.3.tgz", + "integrity": "sha512-UO/fGv9641PUpYjz2nkPaUHzzrhNaJKupJOqt8blj1pD6wBgpZtxUSXBox6Y8md3eTBzpxeWxV+6RKzzERvr1g==", "requires": { "base64-js": "1.3.1", - "idtoken-verifier": "2.0.3", + "idtoken-verifier": "2.1.0", "js-cookie": "2.2.1", "qs": "6.9.4", - "superagent": "3.8.3", + "superagent": "5.3.1", "url-join": "4.0.1", "winchan": "0.2.2" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "4.0.0" + } + }, + "mime": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz", + "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "2.0.3", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "requires": { + "lru-cache": "6.0.0" + } + }, + "superagent": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz", + "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==", + "requires": { + "component-emitter": "1.3.0", + "cookiejar": "2.1.2", + "debug": "4.3.1", + "fast-safe-stringify": "2.0.7", + "form-data": "3.0.0", + "formidable": "1.2.2", + "methods": "1.1.2", + "mime": "2.5.0", + "qs": "6.9.4", + "readable-stream": "3.6.0", + "semver": "7.3.4" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } } }, "autoprefixer": { @@ -3916,9 +4025,9 @@ "dev": true }, "bunyan": { - "version": "1.8.12", - "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz", - "integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=", + "version": "1.8.15", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz", + "integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==", "requires": { "dtrace-provider": "0.8.8", "moment": "2.25.3", @@ -7833,6 +7942,11 @@ "resolved": "https://registry.npmjs.org/event-lite/-/event-lite-0.1.2.tgz", "integrity": "sha512-HnSYx1BsJ87/p6swwzv+2v6B4X+uxUteoDfRxsAb1S1BePzQqOLevVmkdA15GHJVd9A9Ok6wygUR18Hu0YeV9g==" }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, "eventemitter3": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", @@ -8400,6 +8514,11 @@ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" }, + "fast-text-encoding": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", + "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" + }, "fastparse": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", @@ -9277,6 +9396,30 @@ "wide-align": "1.1.3" } }, + "gaxios": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.1.0.tgz", + "integrity": "sha512-vb0to8xzGnA2qcgywAjtshOKKVDf2eQhJoiL6fHhgW5tVN7wNk7egnYIO9zotfn3lQ3De1VPdf7V5/BWfCtCmg==", + "requires": { + "abort-controller": "3.0.0", + "extend": "3.0.2", + "https-proxy-agent": "5.0.0", + "is-stream": "2.0.0", + "node-fetch": "2.6.1" + }, + "dependencies": { + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + } + } + }, "gaze": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", @@ -9286,6 +9429,15 @@ "globule": "1.3.1" } }, + "gcp-metadata": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.2.1.tgz", + "integrity": "sha512-tSk+REe5iq/N+K+SK1XjZJUrFPuDqGZVzCy2vocIHIGmPlTGsa8owXMJwGkrXr73NO0AzhPW4MF2DEHz7P2AVw==", + "requires": { + "gaxios": "4.1.0", + "json-bigint": "1.0.0" + } + }, "generic-names": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-1.0.3.tgz", @@ -10067,6 +10219,101 @@ "delegate": "3.2.0" } }, + "google-auth-library": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz", + "integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==", + "requires": { + "arrify": "2.0.1", + "base64-js": "1.3.1", + "ecdsa-sig-formatter": "1.0.11", + "fast-text-encoding": "1.0.3", + "gaxios": "4.1.0", + "gcp-metadata": "4.2.1", + "gtoken": "5.2.1", + "jws": "4.0.0", + "lru-cache": "6.0.0" + }, + "dependencies": { + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "5.1.2" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "requires": { + "jwa": "2.0.0", + "safe-buffer": "5.1.2" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "google-p12-pem": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz", + "integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==", + "requires": { + "node-forge": "0.10.0" + }, + "dependencies": { + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" + } + } + }, + "google-spreadsheet": { + "version": "3.1.15", + "resolved": "https://registry.npmjs.org/google-spreadsheet/-/google-spreadsheet-3.1.15.tgz", + "integrity": "sha512-S5477f3Gf3Mz6AXgCw7dbaYnzu5aHou1AX4sDqrGboQWnAytkxqJGKQiXN+zzRTTcYzSTJCe0g7KqCPZO9xiOw==", + "requires": { + "axios": "0.21.1", + "google-auth-library": "6.1.6", + "lodash": "4.17.20" + }, + "dependencies": { + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "requires": { + "follow-redirects": "1.13.2" + } + }, + "follow-redirects": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz", + "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==" + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + } + } + }, "graceful-fs": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", @@ -10078,6 +10325,37 @@ "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", "dev": true }, + "gtoken": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.2.1.tgz", + "integrity": "sha512-OY0BfPKe3QnMsY9MzTHTSKn+Vl2l1CcLe6BwDEQj00mbbkl5nyQ/7EUREstg4fQNZ8iYE7br4JJ7TdKeDOPWmw==", + "requires": { + "gaxios": "4.1.0", + "google-p12-pem": "3.0.3", + "jws": "4.0.0" + }, + "dependencies": { + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "5.1.2" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "requires": { + "jwa": "2.0.0", + "safe-buffer": "5.1.2" + } + } + } + }, "handlebars": { "version": "4.7.6", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", @@ -10583,6 +10861,31 @@ "toidentifier": "1.0.0" } }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "requires": { + "@tootallnate/once": "1.1.2", + "agent-base": "6.0.2", + "debug": "4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -10621,6 +10924,30 @@ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "requires": { + "agent-base": "6.0.2", + "debug": "4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "husky": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/husky/-/husky-4.2.5.tgz", @@ -10829,15 +11156,15 @@ } }, "idtoken-verifier": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/idtoken-verifier/-/idtoken-verifier-2.0.3.tgz", - "integrity": "sha512-X1izD2ZTMoo+2tw2RKVUvvCSw2B6UOCNMJ0bgHRH758LFTMwBf4JZfCZm61MPBaBW2CIuhkcSnKCZP6jXpSDmw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/idtoken-verifier/-/idtoken-verifier-2.1.0.tgz", + "integrity": "sha512-X0423UM4Rc5bFb39Ai0YHr35rcexlu4oakKdYzSGZxtoPy84P86hhAbzlpgbgomcLOFRgzgKRvhY7YjO5g8OPA==", "requires": { "base64-js": "1.3.1", "crypto-js": "3.3.0", "es6-promise": "4.2.8", "jsbn": "1.1.0", - "unfetch": "4.1.0", + "unfetch": "4.2.0", "url-join": "4.0.1" } }, @@ -13094,6 +13421,21 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "requires": { + "bignumber.js": "9.0.1" + }, + "dependencies": { + "bignumber.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" + } + } + }, "json-fallback": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/json-fallback/-/json-fallback-0.0.1.tgz", @@ -13194,14 +13536,14 @@ "lodash.isplainobject": "4.0.6", "lodash.isstring": "4.0.1", "lodash.once": "4.1.1", - "ms": "2.1.2", + "ms": "2.1.3", "semver": "5.7.1" }, "dependencies": { "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, @@ -13269,31 +13611,54 @@ } }, "jwks-rsa": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.8.0.tgz", - "integrity": "sha512-+HYROHD5fsYQCNrJ37RSr2NjbN2/V9YT+yVF3oJxLmPIZWrmp1SOl1hMw2RcuNh+LGA2bGZIhRKGiMjhQa/b7Q==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.12.2.tgz", + "integrity": "sha512-6gPo/mQUxXJt75oPtjhM3Jm3FSXnmwg73QDA8dpgP7YmIKlIY+2StngFxt4w4Y1podtSbtV3jttNOdctuxAX1Q==", "requires": { "@types/express-jwt": "0.0.42", - "axios": "0.19.2", - "debug": "4.1.1", + "axios": "0.21.1", + "debug": "4.3.1", + "http-proxy-agent": "4.0.1", + "https-proxy-agent": "5.0.0", "jsonwebtoken": "8.5.1", "limiter": "1.1.5", - "lru-memoizer": "2.1.2", - "ms": "2.1.2" + "lru-memoizer": "2.1.4", + "ms": "2.1.3", + "proxy-from-env": "1.1.0" }, "dependencies": { + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "requires": { + "follow-redirects": "1.13.2" + } + }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "requires": { "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } } }, + "follow-redirects": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz", + "integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA==" + }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, @@ -13878,9 +14243,9 @@ } }, "lru-memoizer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.1.2.tgz", - "integrity": "sha512-N5L5xlnVcbIinNn/TJ17vHBZwBMt9t7aJDz2n97moWubjNl6VO9Ao2XuAGBBddkYdjrwR9HfzXbT6NfMZXAZ/A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-2.1.4.tgz", + "integrity": "sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ==", "requires": { "lodash.clonedeep": "4.5.0", "lru-cache": "4.0.2" @@ -13891,8 +14256,8 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.2.tgz", "integrity": "sha1-HRdnnAac2l0ECZGgnbwsDbN35V4=", "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.1", + "yallist": "^2.0.0" } } } @@ -14706,7 +15071,7 @@ "resolved": "https://registry.npmjs.org/config/-/config-3.3.3.tgz", "integrity": "sha512-T3RmZQEAji5KYqUQpziWtyGJFli6Khz7h0rpxDwYNjSkr5ynyTWwO7WpfjHzTXclNCDfSWQRcwMb+NwxJesCKw==", "requires": { - "json5": "2.1.3" + "json5": "2.2.0" } }, "hoist-non-react-statics": { @@ -14718,9 +15083,9 @@ } }, "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "requires": { "minimist": "1.2.5" } @@ -14757,7 +15122,7 @@ "resolved": "https://registry.npmjs.org/topcoder-react-utils/-/topcoder-react-utils-0.7.9.tgz", "integrity": "sha512-bH5t7lVTezl3rh2S1pguMWhUlJb39gOLLkCG9jwLCsMKTzri+LsOvpRJ6dOvYZPzA7GdmCgQNeGAoctiqAGb4g==", "requires": { - "@babel/register": "7.9.0", + "@babel/register": "7.12.13", "@babel/runtime": "7.9.6", "body-parser": "1.19.0", "command-line-args": "5.1.1", @@ -17780,6 +18145,11 @@ "ipaddr.js": "1.9.1" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -22540,11 +22910,11 @@ "tc-core-library-js": { "version": "github:appirio-tech/tc-core-library-js#f45352974dafe5a10c86fc50bdd59ef399b50c65", "requires": { - "auth0-js": "9.13.2", + "auth0-js": "9.14.3", "axios": "0.19.2", - "bunyan": "1.8.12", + "bunyan": "1.8.15", "jsonwebtoken": "8.5.1", - "jwks-rsa": "1.8.0", + "jwks-rsa": "1.12.2", "le_node": "1.8.0", "lodash": "4.17.15", "millisecond": "0.1.2", @@ -23244,9 +23614,9 @@ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, "topcoder-react-lib": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/topcoder-react-lib/-/topcoder-react-lib-1.1.5.tgz", - "integrity": "sha512-XD1QPxuaD4w6plhYhU/q4bnwAd498HYCHAANkXt6bztrm0hmmwZFHIJGOtVEozwz1B8EnOsHfVlyn12j5EtEXQ==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/topcoder-react-lib/-/topcoder-react-lib-1.1.6.tgz", + "integrity": "sha512-i9Btnbd9k6dq569avQA4vz0fIxz/nIUxJ9hMldN+n71JY3Qv9rNL6nVCk3ou/j7mMLwTY3zNajJsUAogjD4uIA==", "requires": { "@topcoder-platform/tc-auth-lib": "git+https://github.com/topcoder-platform/tc-auth-lib.git#68fdc22464810c51b703a33e529cdbd6d09437de", "auth0-js": "6.8.4", @@ -23286,18 +23656,19 @@ "resolved": "https://registry.npmjs.org/auth0-js/-/auth0-js-6.8.4.tgz", "integrity": "sha1-Qw3Uystk2NFdabHmIRhPmipkCmE=", "requires": { - "Base64": "0.1.4", + "Base64": "~0.1.3", "json-fallback": "0.0.1", - "jsonp": "0.0.4", - "qs": "git+https://github.com/jfromaniello/node-querystring.git#5d96513991635e3e22d7aa54a8584d6ce97cace8", - "reqwest": "1.1.6", - "trim": "0.0.1", - "winchan": "0.1.4", - "xtend": "2.1.2" + "jsonp": "~0.0.4", + "qs": "git+https://github.com/jfromaniello/node-querystring.git#fix_ie7_bug_with_arrays", + "reqwest": "^1.1.4", + "trim": "~0.0.1", + "winchan": "^0.1.1", + "xtend": "~2.1.1" }, "dependencies": { "qs": { - "version": "git+https://github.com/jfromaniello/node-querystring.git#5d96513991635e3e22d7aa54a8584d6ce97cace8" + "version": "git+https://github.com/jfromaniello/node-querystring.git#5d96513991635e3e22d7aa54a8584d6ce97cace8", + "from": "git+https://github.com/jfromaniello/node-querystring.git#fix_ie7_bug_with_arrays" } } }, @@ -23314,7 +23685,7 @@ "resolved": "https://registry.npmjs.org/config/-/config-3.3.3.tgz", "integrity": "sha512-T3RmZQEAji5KYqUQpziWtyGJFli6Khz7h0rpxDwYNjSkr5ynyTWwO7WpfjHzTXclNCDfSWQRcwMb+NwxJesCKw==", "requires": { - "json5": "2.1.3" + "json5": "2.2.0" } }, "debug": { @@ -23330,8 +23701,8 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-0.0.7.tgz", "integrity": "sha1-NLkLqyqRGqNHVx2pDyK9NuzYqRk=", "requires": { - "debug": "2.6.9", - "stream-consume": "0.1.1" + "debug": "^2.2.0", + "stream-consume": "^0.1.0" }, "dependencies": { "debug": { @@ -23354,13 +23725,13 @@ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "requires": { - "react-is": "16.13.1" + "react-is": "^16.7.0" } }, "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", "requires": { "minimist": "1.2.5" } @@ -23374,9 +23745,9 @@ } }, "mime": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.7.tgz", - "integrity": "sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz", + "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==" }, "ms": { "version": "2.1.2", @@ -23393,12 +23764,12 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-6.0.1.tgz", "integrity": "sha512-T52I52Kxhbqy/6TEfBv85rQSDz6+Y28V/pf52vDWs1YRXG19mcFOGfHnY2HsNFHyhP+ST34Aih98fvt6tqwVcQ==", "requires": { - "@babel/runtime": "7.9.6", - "hoist-non-react-statics": "3.3.2", - "invariant": "2.2.4", - "loose-envify": "1.4.0", - "prop-types": "15.7.2", - "react-is": "16.13.1" + "@babel/runtime": "^7.3.1", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^16.8.2" } }, "readable-stream": { @@ -23429,27 +23800,27 @@ "resolved": "https://registry.npmjs.org/superagent/-/superagent-5.3.1.tgz", "integrity": "sha512-wjJ/MoTid2/RuGCOFtlacyGNxN9QLMgcpYLDQlWFIhhdJ93kNscFonGvrpAHSCVjRVj++DGCglocF7Aej1KHvQ==", "requires": { - "component-emitter": "1.3.0", - "cookiejar": "2.1.2", - "debug": "4.3.1", - "fast-safe-stringify": "2.0.7", - "form-data": "3.0.0", - "formidable": "1.2.2", - "methods": "1.1.2", - "mime": "2.4.7", - "qs": "6.9.4", - "readable-stream": "3.6.0", - "semver": "7.3.4" + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.2", + "debug": "^4.1.1", + "fast-safe-stringify": "^2.0.7", + "form-data": "^3.0.0", + "formidable": "^1.2.2", + "methods": "^1.1.2", + "mime": "^2.4.6", + "qs": "^6.9.4", + "readable-stream": "^3.6.0", + "semver": "^7.3.2" } }, "tc-core-library-js": { "version": "github:appirio-tech/tc-core-library-js#d16413db30b1eed21c0cf426e185bedb2329ddab", "requires": { - "auth0-js": "9.14.0", + "auth0-js": "9.14.3", "axios": "0.12.0", - "bunyan": "1.8.12", + "bunyan": "1.8.15", "jsonwebtoken": "8.5.1", - "jwks-rsa": "1.8.0", + "jwks-rsa": "1.12.2", "le_node": "1.8.0", "lodash": "4.17.15", "millisecond": "0.1.2", @@ -23457,17 +23828,17 @@ }, "dependencies": { "auth0-js": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/auth0-js/-/auth0-js-9.14.0.tgz", - "integrity": "sha512-40gIBUejmYAYse06ck6sxdNO0KU0pX+KDIQsWAkcyFtI0HU6dY5aeHxZfVYkYjtbArKr5s13LuZFdKrUiGyCqQ==", + "version": "9.14.3", + "resolved": "https://registry.npmjs.org/auth0-js/-/auth0-js-9.14.3.tgz", + "integrity": "sha512-UO/fGv9641PUpYjz2nkPaUHzzrhNaJKupJOqt8blj1pD6wBgpZtxUSXBox6Y8md3eTBzpxeWxV+6RKzzERvr1g==", "requires": { - "base64-js": "1.3.1", - "idtoken-verifier": "2.0.3", - "js-cookie": "2.2.1", - "qs": "6.9.4", - "superagent": "5.3.1", - "url-join": "4.0.1", - "winchan": "0.2.2" + "base64-js": "^1.3.0", + "idtoken-verifier": "^2.0.3", + "js-cookie": "^2.2.0", + "qs": "^6.7.0", + "superagent": "^5.3.1", + "url-join": "^4.0.1", + "winchan": "^0.2.2" } }, "winchan": { @@ -23482,38 +23853,38 @@ "resolved": "https://registry.npmjs.org/topcoder-react-utils/-/topcoder-react-utils-0.7.5.tgz", "integrity": "sha512-/jolO/UUCC/FL/MniBMFi9d7Wc1KbzwvgT5STGs4T+7u7R26bQugGPpGVISEPuglsmW0Xybh6iRi+pT/muOkbg==", "requires": { - "babel-runtime": "6.26.0", - "body-parser": "1.19.0", - "command-line-args": "5.1.1", - "command-line-usage": "5.0.5", - "compression": "1.7.4", - "config": "1.31.0", - "cookie-parser": "1.4.5", - "express": "4.17.1", - "helmet": "3.22.0", - "lodash": "4.17.15", - "moment": "2.25.3", - "morgan": "1.10.0", - "node-forge": "0.7.6", - "prop-types": "15.7.2", - "raf": "3.4.1", - "react": "16.13.1", - "react-css-super-themr": "2.3.0", - "react-dom": "16.13.1", - "react-helmet": "5.2.1", - "react-redux": "5.1.2", - "react-router-dom": "4.3.1", - "redux": "3.7.2", - "redux-actions": "2.6.5", - "redux-devtools": "3.5.0", - "redux-devtools-dock-monitor": "1.1.3", - "redux-devtools-log-monitor": "1.4.0", - "redux-promise": "0.6.0", - "request-ip": "2.1.3", - "serialize-javascript": "1.9.1", - "serve-favicon": "2.5.0", - "shortid": "2.2.15", - "url-parse": "1.4.7" + "babel-runtime": "^6.26.0", + "body-parser": "^1.18.3", + "command-line-args": "^5.0.2", + "command-line-usage": "^5.0.5", + "compression": "^1.7.2", + "config": "^1.30.0", + "cookie-parser": "^1.4.3", + "express": "^4.16.3", + "helmet": "^3.12.1", + "lodash": "^4.17.10", + "moment": "^2.22.2", + "morgan": "^1.9.0", + "node-forge": "^0.7.5", + "prop-types": "^15.6.2", + "raf": "^3.4.0", + "react": "^16.4.1", + "react-css-super-themr": "^2.2.0", + "react-dom": "^16.4.1", + "react-helmet": "^5.2.0", + "react-redux": "^5.0.7", + "react-router-dom": "^4.3.1", + "redux": "^3.7.2", + "redux-actions": "^2.4.0", + "redux-devtools": "^3.4.1", + "redux-devtools-dock-monitor": "^1.1.3", + "redux-devtools-log-monitor": "^1.4.0", + "redux-promise": "^0.6.0", + "request-ip": "^2.0.2", + "serialize-javascript": "^1.5.0", + "serve-favicon": "^2.5.0", + "shortid": "^2.2.8", + "url-parse": "^1.4.1" }, "dependencies": { "config": { @@ -23521,7 +23892,7 @@ "resolved": "https://registry.npmjs.org/config/-/config-1.31.0.tgz", "integrity": "sha512-Ep/l9Rd1J9IPueztJfpbOqVzuKHQh4ZODMNt9xqTYdBBNRXbV4oTu34kCkkfdRVcDq0ohtpaeXGgb+c0LQxFRA==", "requires": { - "json5": "1.0.1" + "json5": "^1.0.1" } }, "json5": { @@ -23529,7 +23900,7 @@ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "requires": { - "minimist": "1.2.5" + "minimist": "^1.2.0" } }, "react-redux": { @@ -23537,13 +23908,13 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.1.2.tgz", "integrity": "sha512-Ns1G0XXc8hDyH/OcBHOxNgQx9ayH3SPxBnFCOidGKSle8pKihysQw2rG/PmciUQRoclhVBO8HMhiRmGXnDja9Q==", "requires": { - "@babel/runtime": "7.9.6", - "hoist-non-react-statics": "3.3.2", - "invariant": "2.2.4", - "loose-envify": "1.4.0", - "prop-types": "15.7.2", - "react-is": "16.13.1", - "react-lifecycles-compat": "3.0.4" + "@babel/runtime": "^7.1.2", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "loose-envify": "^1.1.0", + "prop-types": "^15.6.1", + "react-is": "^16.6.0", + "react-lifecycles-compat": "^3.0.0" } } } @@ -23558,7 +23929,7 @@ "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", "requires": { - "object-keys": "0.4.0" + "object-keys": "~0.4.0" } }, "yallist": { @@ -23791,9 +24162,9 @@ "dev": true }, "unfetch": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.1.0.tgz", - "integrity": "sha512-crP/n3eAPUJxZXM9T80/yv0YhkTEx2K1D3h7D1AJM6fzsWZrxdyRuLN0JH/dkZh1LNH8LxCnBzoPFCPbb2iGpg==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==" }, "unherit": { "version": "1.1.3", diff --git a/package.json b/package.json index 60589e2bb7..246554d141 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "flag-icon-css": "^3.3.0", "focus-trap-react": "^6.0.0", "form-data": "^3.0.0", + "google-spreadsheet": "^3.1.15", "helmet": "^3.12.1", "highlight.js": "^9.18.1", "html-to-text": "^5.1.1", @@ -143,7 +144,7 @@ "supertest": "^3.1.0", "tc-core-library-js": "github:appirio-tech/tc-core-library-js#v2.6.3", "tc-ui": "^1.0.12", - "topcoder-react-lib": "1000.27.5", + "topcoder-react-lib": "1.1.6", "topcoder-react-ui-kit": "2.0.1", "topcoder-react-utils": "0.7.8", "turndown": "^4.0.2", diff --git a/src/server/index.js b/src/server/index.js index b4892eb12f..1338e6c447 100644 --- a/src/server/index.js +++ b/src/server/index.js @@ -28,6 +28,7 @@ import mailChimpRouter from './routes/mailchimp'; import mockDocuSignFactory from './__mocks__/docu-sign-mock'; import recruitCRMRouter from './routes/recruitCRM'; import mmLeaderboardRouter from './routes/mmLeaderboard'; +import gSheetsRouter from './routes/gSheet'; /* Dome API for topcoder communities */ import tcCommunitiesDemoApi from './tc-communities'; @@ -137,6 +138,7 @@ async function onExpressJsSetup(server) { server.use('/api/mailchimp', mailChimpRouter); server.use('/api/recruit', recruitCRMRouter); server.use('/api/mml', mmLeaderboardRouter); + server.use('/api/gsheets', gSheetsRouter); // serve demo api server.use( diff --git a/src/server/routes/gSheet.js b/src/server/routes/gSheet.js new file mode 100644 index 0000000000..432dbcfb7b --- /dev/null +++ b/src/server/routes/gSheet.js @@ -0,0 +1,19 @@ +/** + * The routes related to GSheets integration + */ + +import express from 'express'; +import GSheetService from '../services/gSheet'; + +const cors = require('cors'); + +const routes = express.Router(); + +// Enables CORS on those routes according config above +// ToDo configure CORS for set of our trusted domains +routes.use(cors()); +routes.options('*', cors()); + +routes.get('/:id', (req, res) => new GSheetService().getSheet(req, res)); + +export default routes; diff --git a/src/server/routes/mailchimp.js b/src/server/routes/mailchimp.js index 0b8b2a98fe..2ebe70056c 100644 --- a/src/server/routes/mailchimp.js +++ b/src/server/routes/mailchimp.js @@ -20,7 +20,7 @@ routes.post('/:listId/members', (req, res, next) => new MailchimpService().doReg routes.get('/:listId/members/:emailHash', (req, res) => new MailchimpService().checkSubscription(req).then(res.send.bind(res))); -routes.put('/:listId/members/:emailHash', (req, res) => new MailchimpService().subscribeInterests(req).then(res.send.bind(res))); +routes.put('/:listId/members/:emailHash', (req, res) => new MailchimpService().updateMember(req).then(res.send.bind(res))); routes.post('/:listId/members/:emailHash/tags', (req, res) => new MailchimpService().subscribeTags(req).then(res.send.bind(res))); diff --git a/src/server/services/gSheet.js b/src/server/services/gSheet.js new file mode 100644 index 0000000000..a54d6428c4 --- /dev/null +++ b/src/server/services/gSheet.js @@ -0,0 +1,52 @@ +/* eslint-disable consistent-return */ +/* eslint-disable class-methods-use-this */ +/** + * Server-side functions necessary for effective integration with gsheets + */ +import config from 'config'; + +const { GoogleSpreadsheet } = require('google-spreadsheet'); + +const getCircularReplacer = () => { + const seen = new WeakSet(); + return (key, value) => { + if (typeof value === 'object' && value !== null) { + if (seen.has(value)) { + return; + } + seen.add(value); + } + return value; + }; +}; + +/** + * Auxiliary class that handles communication with mailchimp + * APIs in the same uniform manner. + */ +export default class GSheetService { + /** + * getSheet + * @param {Object} req the request + * @param {Object} res the response + */ + async getSheet(req, res) { + const { index } = req.query; + const { id } = req.params; + const doc = new GoogleSpreadsheet(id); + doc.useApiKey(config.GSHEETS_API_KEY); + try { + await doc.loadInfo(); + // the first sheet if not selected via query + const sheet = doc.sheetsByIndex[index || 0]; + const rows = await sheet.getRows(); + const rowsJson = JSON.stringify(rows, getCircularReplacer()); + return res.send({ + rows: JSON.parse(rowsJson), + }); + } catch (e) { + res.status((e.response && e.response.status) || 500); + return res.send((e.response && e.response.data) || { ...e, message: e.message }); + } + } +} diff --git a/src/server/services/mailchimp.js b/src/server/services/mailchimp.js index 1a22665a24..1e06769f23 100644 --- a/src/server/services/mailchimp.js +++ b/src/server/services/mailchimp.js @@ -51,7 +51,7 @@ export default class MailchimpService { return res.json(); } - async subscribeInterests(req) { + async updateMember(req) { const formData = JSON.stringify(req.body); const res = await fetch(`${this.mailchimpBaseUrl}/lists/${req.params.listId}/members/${req.params.emailHash}`, { method: 'PUT', diff --git a/src/server/tc-communities/wipro/metadata.json b/src/server/tc-communities/wipro/metadata.json index fed156fca6..40cd8f5975 100644 --- a/src/server/tc-communities/wipro/metadata.json +++ b/src/server/tc-communities/wipro/metadata.json @@ -31,7 +31,7 @@ "title": "Home", "url": "/" }, { - "title": "Learn", + "title": "TopGear Operations", "openNewTab": true, "url": "https://topgear-app.wipro.com" }, { diff --git a/src/shared/actions/gSheet.js b/src/shared/actions/gSheet.js new file mode 100644 index 0000000000..bd09ca5132 --- /dev/null +++ b/src/shared/actions/gSheet.js @@ -0,0 +1,33 @@ +/** + * Actions related to gsheets + */ +/* global fetch */ +import { redux } from 'topcoder-react-utils'; +import Service from 'services/gSheet'; + +/** + * Fetch init + */ +function getGsheetInit(id, index) { + return { id, index }; +} + +/** + * Fetch done + */ +async function getGsheetDone(id, index) { + const ss = new Service(); + const res = await ss.getSheet(id, index); + return { + id, + index, + data: res, + }; +} + +export default redux.createActions({ + GSHEETS: { + GET_GSHEET_INIT: getGsheetInit, + GET_GSHEET_DONE: getGsheetDone, + }, +}); diff --git a/src/shared/actions/newsletterPreferences.js b/src/shared/actions/newsletterPreferences.js index 40a415c34a..4e1d948896 100644 --- a/src/shared/actions/newsletterPreferences.js +++ b/src/shared/actions/newsletterPreferences.js @@ -35,7 +35,8 @@ async function fetchDataDone(emailHash, listId = config.NEWSLETTER_SIGNUP.DEFAUL return { email: emailHash, - preferences: subs.tags, + preferences: subs.interests, + status: subs.status, error, }; } catch (error) { @@ -48,7 +49,7 @@ async function fetchDataDone(emailHash, listId = config.NEWSLETTER_SIGNUP.DEFAUL // Updates member newsletter subscription async function updateSubscriptionsDone( - emailHash, tagId, status, listId = config.NEWSLETTER_SIGNUP.DEFAUL_LIST_ID, + emailHash, groupId, status, listId = config.NEWSLETTER_SIGNUP.DEFAUL_LIST_ID, ) { /* NOTE: In the real life in most cases you don't want to use fetch() directly * in an action. You want to create a service for your calls and use it here. @@ -56,18 +57,16 @@ async function updateSubscriptionsDone( * directly here. */ try { let error = false; - const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${emailHash}/tags`; + const fetchUrl = `${PROXY_ENDPOINT}/${listId}/members/${emailHash}`; const data = { - tags: [ - { name: tagId, status: status ? 'active' : 'inactive' }, - ], + interests: { [groupId]: !!status }, }; const formData = JSON.stringify(data); // use proxy for avoid 'Access-Control-Allow-Origin' bug await fetch(fetchUrl, { - method: 'POST', + method: 'PUT', headers: { 'Content-Type': 'application/json', }, @@ -79,14 +78,14 @@ async function updateSubscriptionsDone( }); return { - id: tagId, + id: groupId, checked: status, email: emailHash, error, }; } catch (error) { return { - id: tagId, + id: groupId, checked: status, email: emailHash, error, diff --git a/src/shared/components/Contentful/AppComponent/index.jsx b/src/shared/components/Contentful/AppComponent/index.jsx index 47251bfcfc..5d19f81fee 100644 --- a/src/shared/components/Contentful/AppComponent/index.jsx +++ b/src/shared/components/Contentful/AppComponent/index.jsx @@ -11,6 +11,7 @@ import { errors } from 'topcoder-react-lib'; import Leaderboard from 'containers/tco/Leaderboard'; import RecruitCRMJobs from 'containers/Gigs/RecruitCRMJobs'; import EmailSubscribeForm from 'containers/EmailSubscribeForm'; +import GSheet from 'containers/GSheet'; const { fireErrorMessage } = errors; @@ -39,7 +40,10 @@ export function AppComponentSwitch(appComponent) { if (appComponent.fields.type === 'EmailSubscribeForm') { return ; } - fireErrorMessage('Unsupported app component type from contentful', ''); + if (appComponent.fields.type === 'GSheet') { + return ; + } + fireErrorMessage(`Unsupported app component type ${appComponent.fields.type}`, ''); return null; } diff --git a/src/shared/components/GSheet/index.jsx b/src/shared/components/GSheet/index.jsx new file mode 100644 index 0000000000..c09a00fa4f --- /dev/null +++ b/src/shared/components/GSheet/index.jsx @@ -0,0 +1,118 @@ +/* eslint-disable no-underscore-dangle */ +/** + * GSheet component + * renders a table with data from google sheets + */ + +import PT from 'prop-types'; +import _ from 'lodash'; +import React, { Component } from 'react'; +import { Scrollbars } from 'react-custom-scrollbars'; +import cn from 'classnames'; +import './style.scss'; + +export default class GSheet extends Component { + constructor(props) { + super(props); + + this.state = { + sortParam: { + order: '', + field: '', + }, + }; + } + + render() { + const { + sheet, config, + } = this.props; + + const { sortParam } = this.state; + let data = sheet.rows; + + if (sortParam.field) { + // Use Lodash to sort array + data = _.orderBy( + sheet.rows, + [d => Number(d[sortParam.field]) || String(d[sortParam.field]).toLowerCase()], + [sortParam.order], + ); + } + + const renderData = () => ( + + + + + { + (config.pick || sheet.rows[0]._sheet.headerValues).map(c => ( + + )) + } + + + + { + data.map(record => ( + + { + (config.pick || sheet.rows[0]._sheet.headerValues).map(c => ( + + )) + } + + )) + } + +
+
+ {c} + +
+
+ {c.toLowerCase() === 'handle' ? ({record[c]}) : record[c]} +
+
+ ); + + return ( + + { sheet.rows && sheet.rows.length ? renderData() :

No data available yet.

} +
+ ); + } +} + +GSheet.defaultProps = { + +}; + +GSheet.propTypes = { + sheet: PT.shape().isRequired, + config: PT.shape().isRequired, +}; diff --git a/src/shared/components/GSheet/style.scss b/src/shared/components/GSheet/style.scss new file mode 100644 index 0000000000..435f9e456a --- /dev/null +++ b/src/shared/components/GSheet/style.scss @@ -0,0 +1,127 @@ +@import '~styles/mixins'; + +$light-gray: #d4d4d4; + +.no-data-title { + text-align: center; +} + +.body-row, +.header-cell { + border-bottom: 1px solid $light-gray; + font-family: Roboto, sans-serif; +} + +.header-cell { + text-transform: uppercase; +} + +.sort-container > div { + width: 0; + height: 0; + border-left: 4px solid transparent; + border-right: 4px solid transparent; +} + +.component-container { + min-height: 300px; + + > div:last-child { + width: 7px !important; + border-radius: 4.5px !important; + } + + > div:last-child > div { + background-color: rgba(#2a2a2a, 0.3) !important; + border-radius: 4.5px !important; + } + + /* width */ + > div:first-child::-webkit-scrollbar { + width: 7px; + } + + /* Track */ + > div:first-child::-webkit-scrollbar-track { + box-shadow: none; + } + + /* Handle */ + > div:first-child::-webkit-scrollbar-thumb { + background: rgba(#2a2a2a, 0.3); + border-radius: 4.5px; + width: 7px; + } + + /* Handle on hover */ + > div:first-child::-webkit-scrollbar-thumb:hover { + background: rgba(#2a2a2a, 0.5); + } + + .table-container { + width: 100%; + + th { + @include roboto-medium; + } + + td, + th { + padding: 0 5px; + font-size: 14px; + text-align: left; + color: #2a2a2a; + line-height: 51px; + letter-spacing: 0.5px; + + &:last-child { + padding-right: 20px; + } + } + } +} + +.header-table-content { + display: flex; + align-items: center; +} + +.sort-container { + display: flex; + flex-direction: column; + margin-left: 5px; + padding: 0; + border: none; + outline: none; + background: transparent; +} + +.sort-up { + border-bottom: 4px solid $light-gray; + margin-bottom: 2px; + + &.active { + border-bottom: 4px solid $tc-black; + } +} + +.sort-down { + border-top: 4px solid $light-gray; + + &.active { + border-top: 4px solid $tc-black; + } +} + +.handle-link { + @include roboto-medium; + + font-weight: 400; + color: #0d61bf !important; + text-decoration: underline; + font-size: 16px; + + &:hover { + text-decoration: none; + } +} diff --git a/src/shared/components/NewsletterSignupForMembers/ConfirmModal/style.scss b/src/shared/components/NewsletterSignupForMembers/ConfirmModal/style.scss index 7f44328bda..ea3f288646 100644 --- a/src/shared/components/NewsletterSignupForMembers/ConfirmModal/style.scss +++ b/src/shared/components/NewsletterSignupForMembers/ConfirmModal/style.scss @@ -33,5 +33,9 @@ button { margin: 24px 12px 0; + + &:first-child { + margin-right: 12px !important; + } } } diff --git a/src/shared/components/Settings/Preferences/Email/index.jsx b/src/shared/components/Settings/Preferences/Email/index.jsx index b8666c7a80..d8d80ecfa3 100644 --- a/src/shared/components/Settings/Preferences/Email/index.jsx +++ b/src/shared/components/Settings/Preferences/Email/index.jsx @@ -1,3 +1,4 @@ +/* eslint-disable max-len */ /** * Email Preferences component. */ @@ -26,41 +27,48 @@ const SAVE_DELAY = 1000; const newsletters = [ { - id: 'Pipeline', + id: '9f950b43a1', name: 'Challenge Pipeline', desc: 'Subscribe to this newsletter if you want to get updates on the types of challenges coming up in the future. To view these challenges at your leisure you can always visit the Challenge Pipeline page.', }, { - id: 'Gig Work', + id: 'd0c48e9da3', name: 'Gig Work', desc: 'This newsletter gets sent out at various times, specifically when we have an opportunity of mass appeal. For more information you can visit the Gig Work page.', }, { - id: 'Monthly Newsletter', + id: 'a8f858cdf1', name: 'Monthly Newsletter', desc: 'This newsletter gets sent out at the end of every month and contains a variety of important information across all of our tracks.', }, { - id: 'Marathon Match Reminders', + id: '5e67dba327', name: 'Marathon Match Reminders', desc: 'Receive updates whenever a new marathon match is scheduled.', }, { - id: 'Single Round Match Reminders', + id: '9091b438cc', name: 'Single Round Match (SRM) Reminders', desc: 'Attention Competitive Programmers! If there is any newsletter you are subscribing too, it better be this one. Receive updates when a new SRM event is scheduled.', }, { - id: 'TCO Tuesdays', + id: '603c900c32', name: 'TCO Newsletter', desc: 'For all the latest updates surrounding the Topcoder Open you should definitely be subscribing to this one. Expect an update in your mailbox every Tuesday!', }, { - id: 'RDM', + id: '3460574ddd', name: 'Rapid Development Match (RDM) Reminders', desc: 'Receive notifications of our brand new RDMs! These rated, development matches will be a fun new way to engage with us!', }, ]; +const programs = [ + { + id: 'cafe98d7a7', + name: 'Beta Testers', + desc: 'If you have applied and been approved as a Beta Tester, you may control the emails you receive here.', + }, +]; export default class EmailPreferences extends React.Component { saveEmailPreferences = debounce((id, checked) => { @@ -72,6 +80,7 @@ export default class EmailPreferences extends React.Component { super(props); this.state = { emailPreferences: { ...props.preferences }, + status: props.status, }; this.onChange = this.onChange.bind(this); } @@ -82,14 +91,14 @@ export default class EmailPreferences extends React.Component { if (updated.error) { toastrError('Error! ', 'Failed to update Your email preferences :-('); } - const { emailPreferences } = this.state; + const { emailPreferences, status } = this.state; const { id, checked } = updated; - if (!emailPreferences[id]) emailPreferences[id] = { id, checked }; - else emailPreferences[id].checked = checked; + emailPreferences[id] = checked; // eslint-disable-next-line react/no-did-update-set-state this.setState({ emailPreferences, + status: updated.resubscribe ? 'subscribed' : status, }); toastrSuccess('Success! ', 'Your email preferences were updated.'); } @@ -101,34 +110,70 @@ export default class EmailPreferences extends React.Component { } render() { - const { emailPreferences } = this.state; + const { emailPreferences, status } = this.state; + const { email } = this.props; return (

E-Mail Preferences

-
- Your preferences -
-
- { - map(newsletters, (newsletter) => { - const checked = emailPreferences[newsletter.id] - ? emailPreferences[newsletter.id].checked : false; - return ( - this.onChange(newsletter.id, e.target.checked)} - /> - ); - }) - } -
+ { + status !== 'subscribed' ? ( +
+

You are not subscribed to receive Topcoder emails

+

If this was a mistake or if you would like to resubscribe, please click the button below.

+
+ + + + +
+
+ ) : ( + +
Newsletters
+
+ { + map(newsletters, (newsletter) => { + const checked = emailPreferences[newsletter.id]; + return ( + this.onChange(newsletter.id, e.target.checked)} + disabled={status !== 'subscribed'} + /> + ); + }) + } +
+
Programs
+
+ { + map(programs, (program) => { + const checked = emailPreferences[program.id]; + return ( + this.onChange(program.id, e.target.checked)} + disabled={status !== 'subscribed'} + /> + ); + }) + } +
+
+ ) + }
); } @@ -136,6 +181,7 @@ export default class EmailPreferences extends React.Component { EmailPreferences.defaultProps = { updated: null, + status: null, }; EmailPreferences.propTypes = { @@ -143,4 +189,5 @@ EmailPreferences.propTypes = { preferences: PT.shape().isRequired, saveEmailPreferences: PT.func.isRequired, updated: PT.shape(), + status: PT.string, }; diff --git a/src/shared/components/Settings/Preferences/Email/styles.scss b/src/shared/components/Settings/Preferences/Email/styles.scss index e0b07a58f1..ff39f96171 100644 --- a/src/shared/components/Settings/Preferences/Email/styles.scss +++ b/src/shared/components/Settings/Preferences/Email/styles.scss @@ -13,7 +13,8 @@ } } - .sub-title { + .sub-title, + .sub-title-2 { @include roboto-light; color: #888894; @@ -28,7 +29,60 @@ } } + .sub-title-2 { + margin-top: 30px; + } + .preferences-container { border-top: 1px solid $tc-gray-neutral-dark; } + + .unsubscribed-msg { + @include sofia-pro-regular; + + display: flex; + flex-direction: column; + background-color: $tc-red-10; + border: 1px solid $tc-red-30; + color: $tc-red; + line-height: 20px; + margin-bottom: 25px; + padding: 10px; + text-align: left; + font-size: 13px; + align-items: flex-start; + + button { + margin: 20px 0 0 0; + } + } +} + +:global { + #mc-embedded-subscribe-form { + input { + display: none; + } + + #mc-embedded-subscribe { + @include roboto-medium; + + display: inline-block; + margin-top: 20px; + cursor: pointer; + height: 40px; + font-size: 15px; + font-weight: 500; + padding: 0; + width: 170px; + white-space: nowrap; + background-color: #006ad7; + color: white; + border-radius: 4px; + + &:hover { + background-image: linear-gradient(180deg, #3996ff, #127bf3); + } + } + } } diff --git a/src/shared/components/Settings/ToggleableItem/index.jsx b/src/shared/components/Settings/ToggleableItem/index.jsx index bbfe110863..d5d4552a71 100644 --- a/src/shared/components/Settings/ToggleableItem/index.jsx +++ b/src/shared/components/Settings/ToggleableItem/index.jsx @@ -18,6 +18,7 @@ export default function ToggleableItem({ primaryText, secondaryText, value, + disabled, }) { return (
@@ -38,6 +39,7 @@ export default function ToggleableItem({ checked={checked} onChange={onToggle} className="onoffswitch-checkbox" + disabled={disabled} />