From 6ec239f6dadcda7fbb26c0993730eafcec567366 Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Tue, 19 Nov 2024 09:17:50 +1100 Subject: [PATCH 01/40] Remove vanilla access token value --- .environments/.env.dev | 3 --- .environments/.env.prod | 3 --- .environments/.env.qa | 3 --- .../src/config/constants/work.constants.js | 1 - .../message-store/message.store.ts | 17 +++++++++++------ src/config/environments/default.env.ts | 1 - src/config/environments/prod.env.ts | 1 - 7 files changed, 11 insertions(+), 18 deletions(-) diff --git a/.environments/.env.dev b/.environments/.env.dev index d3f5fecf3..ab1b994f6 100644 --- a/.environments/.env.dev +++ b/.environments/.env.dev @@ -6,9 +6,6 @@ REACT_APP_ENABLE_TCA_CERT_MONETIZATION=false REACT_APP_STRIPE_API_KEY=pk_test_rfcS49MHRVUKomQ9JgSH7Xqz REACT_APP_STRIPE_API_VERSION=2020-08-27 -# Vanilla Forums -REACT_APP_VANILLA_ACCESS_TOKEN=va.JApNvUOx3549h20I6tnl1kOQDc75NDIp.0jG3dA.EE3gZgV - # DataDogLogging REACT_APP_DATADOG_PUBLIC_TOKEN=puba0825671e469d16f940c5a30dc738f11 diff --git a/.environments/.env.prod b/.environments/.env.prod index bac66716c..b4c21353f 100644 --- a/.environments/.env.prod +++ b/.environments/.env.prod @@ -6,9 +6,6 @@ REACT_APP_ENABLE_TCA_CERT_MONETIZATION=false REACT_APP_STRIPE_API_KEY=pk_live_m3bCBVSfkfMOEp3unZFRsHXi REACT_APP_STRIPE_API_VERSION=2020-08-27 -# Vanilla Forums -REACT_APP_VANILLA_ACCESS_TOKEN=va.JApNvUOx3549h20I6tnl1kOQDc75NDIp.0jG3dA.EE3gZgV - # DataDogLogging REACT_APP_DATADOG_PUBLIC_TOKEN=puba0825671e469d16f940c5a30dc738f11 diff --git a/.environments/.env.qa b/.environments/.env.qa index 1c0688542..96332984b 100644 --- a/.environments/.env.qa +++ b/.environments/.env.qa @@ -6,9 +6,6 @@ REACT_APP_ENABLE_TCA_CERT_MONETIZATION=false REACT_APP_STRIPE_API_KEY=pk_test_rfcS49MHRVUKomQ9JgSH7Xqz REACT_APP_STRIPE_API_VERSION=2020-08-27 -# Vanilla Forums -REACT_APP_VANILLA_ACCESS_TOKEN=va.JApNvUOx3549h20I6tnl1kOQDc75NDIp.0jG3dA.EE3gZgV - # DataDogLogging REACT_APP_DATADOG_PUBLIC_TOKEN=puba0825671e469d16f940c5a30dc738f11 diff --git a/src/apps/self-service/src/config/constants/work.constants.js b/src/apps/self-service/src/config/constants/work.constants.js index 238d5643d..4bf3efad1 100644 --- a/src/apps/self-service/src/config/constants/work.constants.js +++ b/src/apps/self-service/src/config/constants/work.constants.js @@ -42,7 +42,6 @@ export const VANILLA_EMBED_JS = EnvironmentConfig.ENV === 'prod' : 'https://vanilla.topcoder-dev.com/js/embed.js'; export const VANILLA_EMBED_TYPE = 'mfe'; export const VANILLA_FORUM_API = EnvironmentConfig.VANILLA_FORUM.V2_URL; -export const VANILLA_ACCESS_TOKEN = EnvironmentConfig.VANILLA_FORUM.ACCESS_TOKEN; /** * Expire time period of auto saved intake form: 24 hours diff --git a/src/apps/self-service/src/lib/work-provider/message-functions/message-store/message.store.ts b/src/apps/self-service/src/lib/work-provider/message-functions/message-store/message.store.ts index b82fbe04f..035456d95 100644 --- a/src/apps/self-service/src/lib/work-provider/message-functions/message-store/message.store.ts +++ b/src/apps/self-service/src/lib/work-provider/message-functions/message-store/message.store.ts @@ -5,15 +5,20 @@ import { GetUnreadMessageCountResponse } from './get-unread-message-count-respon export async function getUnreadCountAsync(workId: string, handle: string): Promise { - const url: string = [ - `${EnvironmentConfig.VANILLA_FORUM.V2_URL}/groups/${workId}/member/${handle}`, - `access_token=${EnvironmentConfig.VANILLA_FORUM.ACCESS_TOKEN}`, - ].join('?') + // Removing this because it's no longer needed and showed up in a pen test failure (PM-324) + // const url: string = [ + // `${EnvironmentConfig.VANILLA_FORUM.V2_URL}/groups/${workId}/member/${handle}`, + // `access_token=${EnvironmentConfig.VANILLA_FORUM.ACCESS_TOKEN}`, + // ].join('?') - const response: { unreadNotifications: number } = await xhrGetAsync(url) + // const response: { unreadNotifications: number } = await xhrGetAsync(url) + // return { + // messageCount: response.unreadNotifications, + // workId, + // } return { - messageCount: response.unreadNotifications, + messageCount: 0, workId, } } diff --git a/src/config/environments/default.env.ts b/src/config/environments/default.env.ts index 1b9be7af6..40007d85a 100644 --- a/src/config/environments/default.env.ts +++ b/src/config/environments/default.env.ts @@ -39,7 +39,6 @@ export const REAUTH_OFFSET = 55 export const SPRIG = { ENVIRONMENT_ID: getReactEnv('SPRIG_ENV_ID', undefined) } export const VANILLA_FORUM = { - ACCESS_TOKEN: getReactEnv('VANILLA_ACCESS_TOKEN', ''), V2_URL: 'https://vanilla.topcoder-dev.com/api/v2', } diff --git a/src/config/environments/prod.env.ts b/src/config/environments/prod.env.ts index b740bc58c..eaf6dff32 100644 --- a/src/config/environments/prod.env.ts +++ b/src/config/environments/prod.env.ts @@ -6,6 +6,5 @@ export * from './default.env' export const TERMS_URL = 'https://www.topcoder.com/challenges/terms/detail/564a981e-6840-4a5c-894e-d5ad22e9cd6f' export const VANILLA_FORUM = { - ACCESS_TOKEN: getReactEnv('VANILLA_ACCESS_TOKEN', ''), V2_URL: 'https://vanilla.topcoder.com/api/v2', } From e0b21f02594c27e77c5725421d2773650b216881 Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Tue, 19 Nov 2024 09:22:04 +1100 Subject: [PATCH 02/40] Remove vanilla access token value --- src/config/environments/global-config.model.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/config/environments/global-config.model.ts b/src/config/environments/global-config.model.ts index 63ba75026..beb36f385 100644 --- a/src/config/environments/global-config.model.ts +++ b/src/config/environments/global-config.model.ts @@ -32,7 +32,6 @@ export interface GlobalConfig { MEMBER_VERIFY_LOOKER: number ENABLE_TCA_CERT_MONETIZATION: boolean VANILLA_FORUM: { - ACCESS_TOKEN: string V2_URL: string }, SUBDOMAIN: string, From a9a8769672346d00162b8231eb0c4c0f1718c707 Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Tue, 19 Nov 2024 09:25:26 +1100 Subject: [PATCH 03/40] Remove segment analytics --- package.json | 1 - src/apps/platform/src/PlatformApp.tsx | 5 ----- src/config/environments/default.env.ts | 1 - src/config/environments/global-config.model.ts | 1 - .../core/lib/auth/token-functions/token.functions.ts | 10 ---------- src/types/index.d.ts | 9 --------- 6 files changed, 27 deletions(-) delete mode 100644 src/types/index.d.ts diff --git a/package.json b/package.json index 05c805a94..97137440a 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "@datadog/browser-logs": "^4.21.2", "@heroicons/react": "^1.0.6", "@popperjs/core": "^2.11.8", - "@segment/analytics-next": "^1.53.3", "@sprig-technologies/sprig-browser": "^2.20.1", "@storybook/addon-actions": "^7.0.5", "@storybook/react": "^7.0.5", diff --git a/src/apps/platform/src/PlatformApp.tsx b/src/apps/platform/src/PlatformApp.tsx index ae62f3d5a..6c5683829 100644 --- a/src/apps/platform/src/PlatformApp.tsx +++ b/src/apps/platform/src/PlatformApp.tsx @@ -1,7 +1,6 @@ import { FC } from 'react' import { toast, ToastContainer } from 'react-toastify' -import { AnalyticsBrowser } from '@segment/analytics-next' import { useViewportUnitsFix } from '~/libs/shared' import { EnvironmentConfig } from '~/config' @@ -10,10 +9,6 @@ import { AppHeader } from './components/app-header' import { Providers } from './providers' import { PlatformRouter } from './platform-router' -if (EnvironmentConfig.SEGMENT_ANALYTICS_KEY) { - window.tcSegment = AnalyticsBrowser.load({ writeKey: EnvironmentConfig.SEGMENT_ANALYTICS_KEY }) as any -} - const PlatformApp: FC<{}> = () => { useViewportUnitsFix() diff --git a/src/config/environments/default.env.ts b/src/config/environments/default.env.ts index 40007d85a..b90bb2a20 100644 --- a/src/config/environments/default.env.ts +++ b/src/config/environments/default.env.ts @@ -68,7 +68,6 @@ export const GAMIFICATION_ORG_ID = getReactEnv('GAMIFICATION_ORG_ID', un // TODO: Revert this. This was done because prod was restricting this and no one was available to fix the config // export const RESTRICT_TALENT_SEARCH = getReactEnv('RESTRICT_TALENT_SEARCH', false) export const RESTRICT_TALENT_SEARCH = false -export const SEGMENT_ANALYTICS_KEY = getReactEnv('SEGMENT_ANALYTICS_KEY', undefined) export const USERFLOW_SURVEYS = { ACCOUNT_SETTINGS: getReactEnv('USERFLOW_SURVEY_ACCOUNT_SETTINGS', '3e704fe0-dff4-4af4-abee-383ed162729e'), diff --git a/src/config/environments/global-config.model.ts b/src/config/environments/global-config.model.ts index beb36f385..ce4dbd5f8 100644 --- a/src/config/environments/global-config.model.ts +++ b/src/config/environments/global-config.model.ts @@ -37,7 +37,6 @@ export interface GlobalConfig { SUBDOMAIN: string, GAMIFICATION_ORG_ID: string RESTRICT_TALENT_SEARCH: boolean - SEGMENT_ANALYTICS_KEY: string USERFLOW_SURVEYS: { ACCOUNT_SETTINGS: string PROFILES: string diff --git a/src/libs/core/lib/auth/token-functions/token.functions.ts b/src/libs/core/lib/auth/token-functions/token.functions.ts index e9b91bbf2..bcc9691a8 100644 --- a/src/libs/core/lib/auth/token-functions/token.functions.ts +++ b/src/libs/core/lib/auth/token-functions/token.functions.ts @@ -1,7 +1,5 @@ import { decodeToken } from 'tc-auth-lib' -import { ID } from '@segment/analytics-next' - import { authInitializeAsync } from '../authentication-functions' import { logError } from '../../logger' @@ -29,14 +27,6 @@ export async function getAsync(): Promise { return Promise.resolve({}) } - // segment identify user - if (window && window.tcSegment) { - window.tcSegment.identify(userId as ID, { - handle, - roles, - }) - } - return Promise.resolve({ handle, roles, token, userId }) // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/src/types/index.d.ts b/src/types/index.d.ts deleted file mode 100644 index e8adaebe9..000000000 --- a/src/types/index.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { AnalyticsSnippet } from '@segment/analytics-next' - -export { } - -declare global { - interface Window { - tcSegment: AnalyticsSnippet; - } -} From 5d891488ec006edacdca9390a2456e7c77574d95 Mon Sep 17 00:00:00 2001 From: Justin Gasper Date: Tue, 19 Nov 2024 09:31:58 +1100 Subject: [PATCH 04/40] Lint --- src/apps/platform/src/PlatformApp.tsx | 1 - .../message-store/message.store.ts | 4 +- src/config/environments/prod.env.ts | 3 - yarn.lock | 966 +----------------- 4 files changed, 3 insertions(+), 971 deletions(-) diff --git a/src/apps/platform/src/PlatformApp.tsx b/src/apps/platform/src/PlatformApp.tsx index 6c5683829..dd89390fb 100644 --- a/src/apps/platform/src/PlatformApp.tsx +++ b/src/apps/platform/src/PlatformApp.tsx @@ -2,7 +2,6 @@ import { FC } from 'react' import { toast, ToastContainer } from 'react-toastify' import { useViewportUnitsFix } from '~/libs/shared' -import { EnvironmentConfig } from '~/config' import { AppFooter } from './components/app-footer' import { AppHeader } from './components/app-header' diff --git a/src/apps/self-service/src/lib/work-provider/message-functions/message-store/message.store.ts b/src/apps/self-service/src/lib/work-provider/message-functions/message-store/message.store.ts index 035456d95..82f2bfdb4 100644 --- a/src/apps/self-service/src/lib/work-provider/message-functions/message-store/message.store.ts +++ b/src/apps/self-service/src/lib/work-provider/message-functions/message-store/message.store.ts @@ -1,8 +1,6 @@ -import { EnvironmentConfig } from '~/config' -import { xhrGetAsync } from '~/libs/core' - import { GetUnreadMessageCountResponse } from './get-unread-message-count-response.model' +/* eslint-disable @typescript-eslint/no-unused-vars */ export async function getUnreadCountAsync(workId: string, handle: string): Promise { // Removing this because it's no longer needed and showed up in a pen test failure (PM-324) diff --git a/src/config/environments/prod.env.ts b/src/config/environments/prod.env.ts index eaf6dff32..9d1baba34 100644 --- a/src/config/environments/prod.env.ts +++ b/src/config/environments/prod.env.ts @@ -1,6 +1,3 @@ -/* eslint-disable @typescript-eslint/typedef */ -import { getReactEnv } from './react-env' - export * from './default.env' export const TERMS_URL = 'https://www.topcoder.com/challenges/terms/detail/564a981e-6840-4a5c-894e-d5ad22e9cd6f' diff --git a/yarn.lock b/yarn.lock index 272b2eb1c..7c539a606 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2644,18 +2644,6 @@ resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== -"@lukeed/csprng@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@lukeed/csprng/-/csprng-1.1.0.tgz#1e3e4bd05c1cc7a0b2ddbd8a03f39f6e4b5e6cfe" - integrity sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA== - -"@lukeed/uuid@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@lukeed/uuid/-/uuid-2.0.1.tgz#4f6c34259ee0982a455e1797d56ac27bb040fd74" - integrity sha512-qC72D4+CDdjGqJvkFMMEAtancHUQ7/d/tAiHf64z8MopFDmcrtbcJuerDtFceuAfQJ2pDSfCKCtbqoGBNnwg0w== - dependencies: - "@lukeed/csprng" "^1.1.0" - "@mdx-js/react@^2.1.5": version "2.3.0" resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-2.3.0.tgz#4208bd6d70f0d0831def28ef28c26149b03180b3" @@ -2785,71 +2773,6 @@ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz#8be36a1f66f3265389e90b5f9c9962146758f728" integrity sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg== -"@segment/analytics-core@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@segment/analytics-core/-/analytics-core-1.3.0.tgz#677d1087af44d31266ddf60f72f93b5d5693c933" - integrity sha512-ujScWZH49NK1hYlp2/EMw45nOPEh+pmTydAnR6gSkRNucZD4fuinvpPL03rmFCw8ibaMuKLAdgPJfQ0gkLKZ5A== - dependencies: - "@lukeed/uuid" "^2.0.0" - dset "^3.1.2" - tslib "^2.4.1" - -"@segment/analytics-next@^1.53.3": - version "1.53.3" - resolved "https://registry.yarnpkg.com/@segment/analytics-next/-/analytics-next-1.53.3.tgz#d6ae5c96648d309efae51a02d34136b15ed06cd5" - integrity sha512-aAkVDm5HUaHtNrpQR0uXoGDkMKHbBK2ut+Quq0QGN4JNIpNX4j77vhCIZKkzNEResxH94d45Hm3uEFhQ0ycCBQ== - dependencies: - "@lukeed/uuid" "^2.0.0" - "@segment/analytics-core" "1.3.0" - "@segment/analytics.js-video-plugins" "^0.2.1" - "@segment/facade" "^3.4.9" - "@segment/tsub" "^2.0.0" - dset "^3.1.2" - js-cookie "3.0.1" - node-fetch "^2.6.7" - spark-md5 "^3.0.1" - tslib "^2.4.1" - unfetch "^4.1.0" - -"@segment/analytics.js-video-plugins@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@segment/analytics.js-video-plugins/-/analytics.js-video-plugins-0.2.1.tgz#3596fa3887dcd9df5978dc566edf4a0aea2a9b1e" - integrity sha512-lZwCyEXT4aaHBLNK433okEKdxGAuyrVmop4BpQqQSJuRz0DglPZgd9B/XjiiWs1UyOankg2aNYMN3VcS8t4eSQ== - dependencies: - unfetch "^3.1.1" - -"@segment/facade@^3.4.9": - version "3.4.10" - resolved "https://registry.yarnpkg.com/@segment/facade/-/facade-3.4.10.tgz#118fab29cf2250d3128f9b2a16d6ec76f86e3710" - integrity sha512-xVQBbB/lNvk/u8+ey0kC/+g8pT3l0gCT8O2y9Z+StMMn3KAFAQ9w8xfgef67tJybktOKKU7pQGRPolRM1i1pdA== - dependencies: - "@segment/isodate-traverse" "^1.1.1" - inherits "^2.0.4" - new-date "^1.0.3" - obj-case "0.2.1" - -"@segment/isodate-traverse@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@segment/isodate-traverse/-/isodate-traverse-1.1.1.tgz#37e1a68b5e48a841260145f1be86d342995dfc64" - integrity sha512-+G6e1SgAUkcq0EDMi+SRLfT48TNlLPF3QnSgFGVs0V9F3o3fq/woQ2rHFlW20W0yy5NnCUH0QGU3Am2rZy/E3w== - dependencies: - "@segment/isodate" "^1.0.3" - -"@segment/isodate@1.0.3", "@segment/isodate@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@segment/isodate/-/isodate-1.0.3.tgz#f44e8202d5edd277ce822785239474b2c9411d4a" - integrity sha512-BtanDuvJqnACFkeeYje7pWULVv8RgZaqKHWwGFnL/g/TH/CcZjkIVTfGDp/MAxmilYHUkrX70SqwnYSTNEaN7A== - -"@segment/tsub@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@segment/tsub/-/tsub-2.0.0.tgz#321e781a38fcd3720853f2da7574b523b447a296" - integrity sha512-NzkBK8GwPsyQ74AceLjENbUoaFrObnzEKOX4ko2wZDuIyK+DnDm3B//8xZYI2LCKt+wUD55l6ygfjCoVs8RMWw== - dependencies: - "@stdlib/math-base-special-ldexp" "^0.0.5" - dlv "^1.1.3" - dset "^3.1.1" - tiny-hashes "^1.0.1" - "@sideway/address@^4.1.3": version "4.1.4" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" @@ -2908,854 +2831,6 @@ resolved "https://registry.yarnpkg.com/@sprig-technologies/sprig-browser/-/sprig-browser-2.22.1.tgz#7e020a1edb477170c8e173f1551aeae25cc94d76" integrity sha512-0REMrzo+4Axoz79xNQI/vwQoxwPsRZfXL2FnBd+6NHltWpkcfr9DzAlnn6j4KA9lOI76cyROpqSpYBN7Pa1Plw== -"@stdlib/array-float32@^0.0.x": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@stdlib/array-float32/-/array-float32-0.0.6.tgz#7a1c89db3c911183ec249fa32455abd9328cfa27" - integrity sha512-QgKT5UaE92Rv7cxfn7wBKZAlwFFHPla8eXsMFsTGt5BiL4yUy36lwinPUh4hzybZ11rw1vifS3VAPuk6JP413Q== - dependencies: - "@stdlib/assert-has-float32array-support" "^0.0.x" - -"@stdlib/array-float64@^0.0.x": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@stdlib/array-float64/-/array-float64-0.0.6.tgz#02d1c80dd4c38a0f1ec150ddfefe706e148bfc10" - integrity sha512-oE8y4a84LyBF1goX5//sU1mOjet8gLI0/6wucZcjg+j/yMmNV1xFu84Az9GOGmFSE6Ze6lirGOhfBeEWNNNaJg== - dependencies: - "@stdlib/assert-has-float64array-support" "^0.0.x" - -"@stdlib/array-uint16@^0.0.x": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@stdlib/array-uint16/-/array-uint16-0.0.6.tgz#2545110f0b611a1d55b01e52bd9160aaa67d6973" - integrity sha512-/A8Tr0CqJ4XScIDRYQawosko8ha1Uy+50wsTgJhjUtXDpPRp7aUjmxvYkbe7Rm+ImYYbDQVix/uCiPAFQ8ed4Q== - dependencies: - "@stdlib/assert-has-uint16array-support" "^0.0.x" - -"@stdlib/array-uint32@^0.0.x": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@stdlib/array-uint32/-/array-uint32-0.0.6.tgz#5a923576475f539bfb2fda4721ea7bac6e993949" - integrity sha512-2hFPK1Fg7obYPZWlGDjW9keiIB6lXaM9dKmJubg/ergLQCsJQJZpYsG6mMAfTJi4NT1UF4jTmgvyKD+yf0D9cA== - dependencies: - "@stdlib/assert-has-uint32array-support" "^0.0.x" - -"@stdlib/array-uint8@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/array-uint8/-/array-uint8-0.0.7.tgz#56f82b361da6bd9caad0e1d05e7f6ef20af9c895" - integrity sha512-qYJQQfGKIcky6TzHFIGczZYTuVlut7oO+V8qUBs7BJC9TwikVnnOmb3hY3jToY4xaoi5p9OvgdJKPInhyIhzFg== - dependencies: - "@stdlib/assert-has-uint8array-support" "^0.0.x" - -"@stdlib/assert-has-float32array-support@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-has-float32array-support/-/assert-has-float32array-support-0.0.8.tgz#77371183726e26ca9e6f9db41d34543607074067" - integrity sha512-Yrg7K6rBqwCzDWZ5bN0VWLS5dNUWcoSfUeU49vTERdUmZID06J069CDc07UUl8vfQWhFgBWGocH3rrpKm1hi9w== - dependencies: - "@stdlib/assert-is-float32array" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/constants-float64-pinf" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - -"@stdlib/assert-has-float64array-support@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-has-float64array-support/-/assert-has-float64array-support-0.0.8.tgz#4d154994d348f5d894f63b3fbb9d7a6e2e4e5311" - integrity sha512-UVQcoeWqgMw9b8PnAmm/sgzFnuWkZcNhJoi7xyMjbiDV/SP1qLCrvi06mq86cqS3QOCma1fEayJdwgteoXyyuw== - dependencies: - "@stdlib/assert-is-float64array" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - -"@stdlib/assert-has-node-buffer-support@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-has-node-buffer-support/-/assert-has-node-buffer-support-0.0.8.tgz#5564d8e797c850f6ffc522b720eab1f6cba9c814" - integrity sha512-fgI+hW4Yg4ciiv4xVKH+1rzdV7e5+6UKgMnFbc1XDXHcxLub3vOr8+H6eDECdAIfgYNA7X0Dxa/DgvX9dwDTAQ== - dependencies: - "@stdlib/assert-is-buffer" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - -"@stdlib/assert-has-own-property@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/assert-has-own-property/-/assert-has-own-property-0.0.7.tgz#8b55b38e25db8366b028cb871905ac09c9c253fb" - integrity sha512-3YHwSWiUqGlTLSwxAWxrqaD1PkgcJniGyotJeIt5X0tSNmSW0/c9RWroCImTUUB3zBkyBJ79MyU9Nf4Qgm59fQ== - -"@stdlib/assert-has-symbol-support@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-has-symbol-support/-/assert-has-symbol-support-0.0.8.tgz#8606b247f0d023f2a7a6aa8a6fe5e346aa802a8f" - integrity sha512-PoQ9rk8DgDCuBEkOIzGGQmSnjtcdagnUIviaP5YskB45/TJHXseh4NASWME8FV77WFW9v/Wt1MzKFKMzpDFu4Q== - dependencies: - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - -"@stdlib/assert-has-tostringtag-support@^0.0.x": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@stdlib/assert-has-tostringtag-support/-/assert-has-tostringtag-support-0.0.9.tgz#1080ef0a4be576a72d19a819498719265456f170" - integrity sha512-UTsqdkrnQ7eufuH5BeyWOJL3ska3u5nvDWKqw3onNNZ2mvdgkfoFD7wHutVGzAA2rkTsSJAMBHVwWLsm5SbKgw== - dependencies: - "@stdlib/assert-has-symbol-support" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - -"@stdlib/assert-has-uint16array-support@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-has-uint16array-support/-/assert-has-uint16array-support-0.0.8.tgz#083828067d55e3cc896796bc63cbf5726f67eecf" - integrity sha512-vqFDn30YrtzD+BWnVqFhB130g3cUl2w5AdOxhIkRkXCDYAM5v7YwdNMJEON+D4jI8YB4D5pEYjqKweYaCq4nyg== - dependencies: - "@stdlib/assert-is-uint16array" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/constants-uint16-max" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - -"@stdlib/assert-has-uint32array-support@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-has-uint32array-support/-/assert-has-uint32array-support-0.0.8.tgz#a98c431fee45743088adb9602ef753c7552f9155" - integrity sha512-tJtKuiFKwFSQQUfRXEReOVGXtfdo6+xlshSfwwNWXL1WPP2LrceoiUoQk7zMCMT6VdbXgGH92LDjVcPmSbH4Xw== - dependencies: - "@stdlib/assert-is-uint32array" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/constants-uint32-max" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - -"@stdlib/assert-has-uint8array-support@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-has-uint8array-support/-/assert-has-uint8array-support-0.0.8.tgz#9bed19de9834c3ced633551ed630982f0f424724" - integrity sha512-ie4vGTbAS/5Py+LLjoSQi0nwtYBp+WKk20cMYCzilT0rCsBI/oez0RqHrkYYpmt4WaJL4eJqC+/vfQ5NsI7F5w== - dependencies: - "@stdlib/assert-is-uint8array" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/constants-uint8-max" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - -"@stdlib/assert-is-array@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-array/-/assert-is-array-0.0.7.tgz#7f30904f88a195d918c588540a6807d1ae639d79" - integrity sha512-/o6KclsGkNcZ5hiROarsD9XUs6xQMb4lTwF6O71UHbKWTtomEF/jD0rxLvlvj0BiCxfKrReddEYd2CnhUyskMA== - dependencies: - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/assert-is-big-endian@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-big-endian/-/assert-is-big-endian-0.0.7.tgz#25ca21fb1ae0ec8201a716731497a2a15f315a7f" - integrity sha512-BvutsX84F76YxaSIeS5ZQTl536lz+f+P7ew68T1jlFqxBhr4v7JVYFmuf24U040YuK1jwZ2sAq+bPh6T09apwQ== - dependencies: - "@stdlib/array-uint16" "^0.0.x" - "@stdlib/array-uint8" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - -"@stdlib/assert-is-boolean@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-boolean/-/assert-is-boolean-0.0.8.tgz#6b38c2e799e4475d7647fb0e44519510e67080ce" - integrity sha512-PRCpslMXSYqFMz1Yh4dG2K/WzqxTCtlKbgJQD2cIkAtXux4JbYiXCtepuoV7l4Wv1rm0a1eU8EqNPgnOmWajGw== - dependencies: - "@stdlib/assert-has-tostringtag-support" "^0.0.x" - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/assert-is-buffer@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-buffer/-/assert-is-buffer-0.0.8.tgz#633b98bc342979e9ed8ed71c3a0f1366782d1412" - integrity sha512-SYmGwOXkzZVidqUyY1IIx6V6QnSL36v3Lcwj8Rvne/fuW0bU2OomsEBzYCFMvcNgtY71vOvgZ9VfH3OppvV6eA== - dependencies: - "@stdlib/assert-is-object-like" "^0.0.x" - -"@stdlib/assert-is-float32array@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-float32array/-/assert-is-float32array-0.0.8.tgz#a43f6106a2ef8797496ab85aaf6570715394654a" - integrity sha512-Phk0Ze7Vj2/WLv5Wy8Oo7poZIDMSTiTrEnc1t4lBn3Svz2vfBXlvCufi/i5d93vc4IgpkdrOEwfry6nldABjNQ== - dependencies: - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/assert-is-float64array@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-float64array/-/assert-is-float64array-0.0.8.tgz#8c27204ae6cf309e16f0bbad1937f8aa06c2a812" - integrity sha512-UC0Av36EEYIgqBbCIz1lj9g7qXxL5MqU1UrWun+n91lmxgdJ+Z77fHy75efJbJlXBf6HXhcYXECIsc0u3SzyDQ== - dependencies: - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/assert-is-function@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-function/-/assert-is-function-0.0.8.tgz#e4925022b7dd8c4a67e86769691d1d29ab159db9" - integrity sha512-M55Dt2njp5tnY8oePdbkKBRIypny+LpCMFZhEjJIxjLE4rA6zSlHs1yRMqD4PmW+Wl9WTeEM1GYO4AQHl1HAjA== - dependencies: - "@stdlib/utils-type-of" "^0.0.x" - -"@stdlib/assert-is-little-endian@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-little-endian/-/assert-is-little-endian-0.0.7.tgz#f369fa3ec05c0e3a813738174b6821aacda6e323" - integrity sha512-SPObC73xXfDXY0dOewXR0LDGN3p18HGzm+4K8azTj6wug0vpRV12eB3hbT28ybzRCa6TAKUjwM/xY7Am5QzIlA== - dependencies: - "@stdlib/array-uint16" "^0.0.x" - "@stdlib/array-uint8" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - -"@stdlib/assert-is-number@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-number/-/assert-is-number-0.0.7.tgz#82b07cda4045bd0ecc846d3bc26d39dca7041c61" - integrity sha512-mNV4boY1cUOmoWWfA2CkdEJfXA6YvhcTvwKC0Fzq+HoFFOuTK/scpTd9HanUyN6AGBlWA8IW+cQ1ZwOT3XMqag== - dependencies: - "@stdlib/assert-has-tostringtag-support" "^0.0.x" - "@stdlib/number-ctor" "^0.0.x" - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/assert-is-object-like@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-object-like/-/assert-is-object-like-0.0.8.tgz#f6fc36eb7b612d650c6201d177214733426f0c56" - integrity sha512-pe9selDPYAu/lYTFV5Rj4BStepgbzQCr36b/eC8EGSJh6gMgRXgHVv0R+EbdJ69KNkHvKKRjnWj0A/EmCwW+OA== - dependencies: - "@stdlib/assert-tools-array-function" "^0.0.x" - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - -"@stdlib/assert-is-object@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-object/-/assert-is-object-0.0.8.tgz#0220dca73bc3df044fc43e73b02963d5ef7ae489" - integrity sha512-ooPfXDp9c7w+GSqD2NBaZ/Du1JRJlctv+Abj2vRJDcDPyrnRTb1jmw+AuPgcW7Ca7op39JTbArI+RVHm/FPK+Q== - dependencies: - "@stdlib/assert-is-array" "^0.0.x" - -"@stdlib/assert-is-plain-object@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-plain-object/-/assert-is-plain-object-0.0.7.tgz#0c3679faf61b03023363f1ce30f8d00f8ed1c37b" - integrity sha512-t/CEq2a083ajAgXgSa5tsH8l3kSoEqKRu1qUwniVLFYL4RGv3615CrpJUDQKVtEX5S/OKww5q0Byu3JidJ4C5w== - dependencies: - "@stdlib/assert-has-own-property" "^0.0.x" - "@stdlib/assert-is-function" "^0.0.x" - "@stdlib/assert-is-object" "^0.0.x" - "@stdlib/utils-get-prototype-of" "^0.0.x" - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/assert-is-regexp-string@^0.0.x": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-regexp-string/-/assert-is-regexp-string-0.0.9.tgz#424f77b4aaa46a19f4b60ba4b671893a2e5df066" - integrity sha512-FYRJJtH7XwXEf//X6UByUC0Eqd0ZYK5AC8or5g5m5efQrgr2lOaONHyDQ3Scj1A2D6QLIJKZc9XBM4uq5nOPXA== - dependencies: - "@stdlib/assert-is-string" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - "@stdlib/process-read-stdin" "^0.0.x" - "@stdlib/regexp-eol" "^0.0.x" - "@stdlib/regexp-regexp" "^0.0.x" - "@stdlib/streams-node-stdin" "^0.0.x" - -"@stdlib/assert-is-regexp@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-regexp/-/assert-is-regexp-0.0.7.tgz#430fe42417114e7ea01d21399a70ed9c4cbae867" - integrity sha512-ty5qvLiqkDq6AibHlNJe0ZxDJ9Mg896qolmcHb69mzp64vrsORnPPOTzVapAq0bEUZbXoypeijypLPs9sCGBSQ== - dependencies: - "@stdlib/assert-has-tostringtag-support" "^0.0.x" - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/assert-is-string@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-string/-/assert-is-string-0.0.8.tgz#b07e4a4cbd93b13d38fa5ebfaa281ccd6ae9e43f" - integrity sha512-Uk+bR4cglGBbY0q7O7HimEJiW/DWnO1tSzr4iAGMxYgf+VM2PMYgI5e0TLy9jOSOzWon3YS39lc63eR3a9KqeQ== - dependencies: - "@stdlib/assert-has-tostringtag-support" "^0.0.x" - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/assert-is-uint16array@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-uint16array/-/assert-is-uint16array-0.0.8.tgz#770cc5d86906393d30d387a291e81df0a984fdfb" - integrity sha512-M+qw7au+qglRXcXHjvoUZVLlGt1mPjuKudrVRto6KL4+tDsP2j+A89NDP3Fz8/XIUD+5jhj+65EOKHSMvDYnng== - dependencies: - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/assert-is-uint32array@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-uint32array/-/assert-is-uint32array-0.0.8.tgz#2a7f1265db25d728e3fc084f0f59be5f796efac5" - integrity sha512-cnZi2DicYcplMnkJ3dBxBVKsRNFjzoGpmG9A6jXq4KH5rFl52SezGAXSVY9o5ZV7bQGaF5JLyCLp6n9Y74hFGg== - dependencies: - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/assert-is-uint8array@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/assert-is-uint8array/-/assert-is-uint8array-0.0.8.tgz#4521054b5d3a2206b406cad7368e0a50eaee4dec" - integrity sha512-8cqpDQtjnJAuVtRkNAktn45ixq0JHaGJxVsSiK79k7GRggvMI6QsbzO6OvcLnZ/LimD42FmgbLd13Yc2esDmZw== - dependencies: - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/assert-tools-array-function@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/assert-tools-array-function/-/assert-tools-array-function-0.0.7.tgz#34e9e5a3fca62ea75da99fc9995ba845ba514988" - integrity sha512-3lqkaCIBMSJ/IBHHk4NcCnk2NYU52tmwTYbbqhAmv7vim8rZPNmGfj3oWkzrCsyCsyTF7ooD+In2x+qTmUbCtQ== - dependencies: - "@stdlib/assert-is-array" "^0.0.x" - -"@stdlib/buffer-ctor@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/buffer-ctor/-/buffer-ctor-0.0.7.tgz#d05b7f4a6ef26defe6cdd41ca244a927b96c55ec" - integrity sha512-4IyTSGijKUQ8+DYRaKnepf9spvKLZ+nrmZ+JrRcB3FrdTX/l9JDpggcUcC/Fe+A4KIZOnClfxLn6zfIlkCZHNA== - dependencies: - "@stdlib/assert-has-node-buffer-support" "^0.0.x" - -"@stdlib/buffer-from-string@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/buffer-from-string/-/buffer-from-string-0.0.8.tgz#0901a6e66c278db84836e483a7278502e2a33994" - integrity sha512-Dws5ZbK2M9l4Bkn/ODHFm3lNZ8tWko+NYXqGS/UH/RIQv3PGp+1tXFUSvjwjDneM6ppjQVExzVedUH1ftABs9A== - dependencies: - "@stdlib/assert-is-function" "^0.0.x" - "@stdlib/assert-is-string" "^0.0.x" - "@stdlib/buffer-ctor" "^0.0.x" - "@stdlib/string-format" "^0.0.x" - -"@stdlib/cli-ctor@^0.0.x": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@stdlib/cli-ctor/-/cli-ctor-0.0.3.tgz#5b0a6d253217556c778015eee6c14be903f82c2b" - integrity sha512-0zCuZnzFyxj66GoF8AyIOhTX5/mgGczFvr6T9h4mXwegMZp8jBC/ZkOGMwmp+ODLBTvlcnnDNpNFkDDyR6/c2g== - dependencies: - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - "@stdlib/utils-noop" "^0.0.x" - minimist "^1.2.0" - -"@stdlib/complex-float32@^0.0.7", "@stdlib/complex-float32@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/complex-float32/-/complex-float32-0.0.7.tgz#fb9a0c34254eaf3ed91c39983e19ef131fc18bc1" - integrity sha512-POCtQcBZnPm4IrFmTujSaprR1fcOFr/MRw2Mt7INF4oed6b1nzeG647K+2tk1m4mMrMPiuXCdvwJod4kJ0SXxQ== - dependencies: - "@stdlib/assert-is-number" "^0.0.x" - "@stdlib/number-float64-base-to-float32" "^0.0.x" - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - "@stdlib/utils-define-property" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/complex-float64@^0.0.8", "@stdlib/complex-float64@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/complex-float64/-/complex-float64-0.0.8.tgz#00ee3a0629d218a01b830a20406aea7d7aff6fb3" - integrity sha512-lUJwsXtGEziOWAqCcnKnZT4fcVoRsl6t6ECaCJX45Z7lAc70yJLiwUieLWS5UXmyoADHuZyUXkxtI4oClfpnaw== - dependencies: - "@stdlib/assert-is-number" "^0.0.x" - "@stdlib/complex-float32" "^0.0.x" - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - "@stdlib/utils-define-property" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/complex-reim@^0.0.6", "@stdlib/complex-reim@^0.0.x": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@stdlib/complex-reim/-/complex-reim-0.0.6.tgz#9657971e36f2a1f1930a21249c1934c8c5087efd" - integrity sha512-28WXfPSIFMtHb0YgdatkGS4yxX5sPYea5MiNgqPv3E78+tFcg8JJG52NQ/MviWP2wsN9aBQAoCPeu8kXxSPdzA== - dependencies: - "@stdlib/array-float64" "^0.0.x" - "@stdlib/complex-float64" "^0.0.x" - "@stdlib/types" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/complex-reimf@^0.0.1", "@stdlib/complex-reimf@^0.0.x": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@stdlib/complex-reimf/-/complex-reimf-0.0.1.tgz#6797bc1bfb668a30511611f2544d0cff4d297775" - integrity sha512-P9zu05ZW2i68Oppp3oHelP7Tk0D7tGBL0hGl1skJppr2vY9LltuNbeYI3C96tQe/7Enw/5GyAWgxoQI4cWccQA== - dependencies: - "@stdlib/array-float32" "^0.0.x" - "@stdlib/complex-float32" "^0.0.x" - "@stdlib/types" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/constants-float64-exponent-bias@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/constants-float64-exponent-bias/-/constants-float64-exponent-bias-0.0.8.tgz#f5069931a9a16d69e90a7c925739d7f64e4d725e" - integrity sha512-IzBJQw9hYgWCki7VoC/zJxEA76Nmf8hmY+VkOWnJ8IyfgTXClgY8tfDGS1cc4l/hCOEllxGp9FRvVdn24A5tKQ== - dependencies: - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/constants-float64-high-word-abs-mask@^0.0.x": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@stdlib/constants-float64-high-word-abs-mask/-/constants-float64-high-word-abs-mask-0.0.1.tgz#efb4cd3c13c301a3e9da83e8065dd2479e2c976e" - integrity sha512-1vy8SUyMHFBwqUUVaZFA7r4/E3cMMRKSwsaa/EZ15w7Kmc01W/ZmaaTLevRcIdACcNgK+8i8813c8H7LScXNcQ== - dependencies: - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/constants-float64-high-word-exponent-mask@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/constants-float64-high-word-exponent-mask/-/constants-float64-high-word-exponent-mask-0.0.8.tgz#c5671d462674ab09e48f25c2b3ca4d6d5cc4d875" - integrity sha512-z28/EQERc0VG7N36bqdvtrRWjFc8600PKkwvl/nqx6TpKAzMXNw55BS1xT4C28Sa9Z7uBWeUj3UbIFedbkoyMw== - dependencies: - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/constants-float64-high-word-sign-mask@^0.0.x": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@stdlib/constants-float64-high-word-sign-mask/-/constants-float64-high-word-sign-mask-0.0.1.tgz#d45bdec657199cdf522240d02ccd4b04040f58ca" - integrity sha512-hmTr5caK1lh1m0eyaQqt2Vt3y+eEdAx57ndbADEbXhxC9qSGd0b4bLSzt/Xp4MYBYdQkHAE/BlkgUiRThswhCg== - dependencies: - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/constants-float64-max-base2-exponent-subnormal@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/constants-float64-max-base2-exponent-subnormal/-/constants-float64-max-base2-exponent-subnormal-0.0.8.tgz#a24288c9c5e401eeb28d29f808c00a0bad481280" - integrity sha512-YGBZykSiXFebznnJfWFDwhho2Q9xhUWOL+X0lZJ4ItfTTo40W6VHAyNYz98tT/gJECFype0seNzzo1nUxCE7jQ== - dependencies: - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/constants-float64-max-base2-exponent@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/constants-float64-max-base2-exponent/-/constants-float64-max-base2-exponent-0.0.8.tgz#1d93dd829129a9e77133c5ad4f8c390c93f31bcb" - integrity sha512-xBAOtso1eiy27GnTut2difuSdpsGxI8dJhXupw0UukGgvy/3CSsyNm+a1Suz/dhqK4tPOTe5QboIdNMw5IgXKQ== - dependencies: - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/constants-float64-min-base2-exponent-subnormal@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/constants-float64-min-base2-exponent-subnormal/-/constants-float64-min-base2-exponent-subnormal-0.0.8.tgz#a5bd5a84ae2dec5694daccdaf2da54759185b727" - integrity sha512-bt81nBus/91aEqGRQBenEFCyWNsf8uaxn4LN1NjgkvY92S1yVxXFlC65fJHsj9FTqvyZ+uj690/gdMKUDV3NjQ== - dependencies: - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/constants-float64-ninf@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/constants-float64-ninf/-/constants-float64-ninf-0.0.8.tgz#4a83691d4d46503e2339fa3ec21d0440877b5bb7" - integrity sha512-bn/uuzCne35OSLsQZJlNrkvU1/40spGTm22g1+ZI1LL19J8XJi/o4iupIHRXuLSTLFDBqMoJlUNphZlWQ4l8zw== - dependencies: - "@stdlib/number-ctor" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/constants-float64-pinf@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/constants-float64-pinf/-/constants-float64-pinf-0.0.8.tgz#ad3d5b267b142b0927363f6eda74c94b8c4be8bf" - integrity sha512-I3R4rm2cemoMuiDph07eo5oWZ4ucUtpuK73qBJiJPDQKz8fSjSe4wJBAigq2AmWYdd7yJHsl5NJd8AgC6mP5Qw== - dependencies: - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/constants-float64-smallest-normal@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/constants-float64-smallest-normal/-/constants-float64-smallest-normal-0.0.8.tgz#ea1b2335175480f7e846fdf5bbe378a31b7409b6" - integrity sha512-Qwxpn5NA3RXf+mQcffCWRcsHSPTUQkalsz0+JDpblDszuz2XROcXkOdDr5LKgTAUPIXsjOgZzTsuRONENhsSEg== - dependencies: - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/constants-uint16-max@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/constants-uint16-max/-/constants-uint16-max-0.0.7.tgz#c20dbe90cf3825f03f5f44b9ee7e8cbada26f4f1" - integrity sha512-7TPoku7SlskA67mAm7mykIAjeEnkQJemw1cnKZur0mT5W4ryvDR6iFfL9xBiByVnWYq/+ei7DHbOv6/2b2jizw== - -"@stdlib/constants-uint32-max@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/constants-uint32-max/-/constants-uint32-max-0.0.7.tgz#60bda569b226120a5d2e01f3066da8e2d3b8e21a" - integrity sha512-8+NK0ewqc1vnEZNqzwFJgFSy3S543Eft7i8WyW/ygkofiqEiLAsujvYMHzPAB8/3D+PYvjTSe37StSwRwvQ6uw== - -"@stdlib/constants-uint8-max@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/constants-uint8-max/-/constants-uint8-max-0.0.7.tgz#d50affeaeb6e67a0f39059a8f5122f3fd5ff4447" - integrity sha512-fqV+xds4jgwFxwWu08b8xDuIoW6/D4/1dtEjZ1sXVeWR7nf0pjj1cHERq4kdkYxsvOGu+rjoR3MbjzpFc4fvSw== - -"@stdlib/fs-exists@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/fs-exists/-/fs-exists-0.0.8.tgz#391b2cee3e014a3b20266e5d047847f68ef82331" - integrity sha512-mZktcCxiLmycCJefm1+jbMTYkmhK6Jk1ShFmUVqJvs+Ps9/2EEQXfPbdEniLoVz4HeHLlcX90JWobUEghOOnAQ== - dependencies: - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - "@stdlib/process-cwd" "^0.0.x" - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - -"@stdlib/fs-read-file@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/fs-read-file/-/fs-read-file-0.0.8.tgz#2f12669fa6dd2d330fb5006a94dc8896f0aaa0e0" - integrity sha512-pIZID/G91+q7ep4x9ECNC45+JT2j0+jdz/ZQVjCHiEwXCwshZPEvxcPQWb9bXo6coOY+zJyX5TwBIpXBxomWFg== - dependencies: - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - -"@stdlib/fs-resolve-parent-path@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/fs-resolve-parent-path/-/fs-resolve-parent-path-0.0.8.tgz#628119952dfaae78afe3916dca856408a4f5c1eb" - integrity sha512-ok1bTWsAziChibQE3u7EoXwbCQUDkFjjRAHSxh7WWE5JEYVJQg1F0o3bbjRr4D/wfYYPWLAt8AFIKBUDmWghpg== - dependencies: - "@stdlib/assert-has-own-property" "^0.0.x" - "@stdlib/assert-is-function" "^0.0.x" - "@stdlib/assert-is-plain-object" "^0.0.x" - "@stdlib/assert-is-string" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-exists" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - "@stdlib/process-cwd" "^0.0.x" - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - -"@stdlib/math-base-assert-is-infinite@^0.0.x": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@stdlib/math-base-assert-is-infinite/-/math-base-assert-is-infinite-0.0.9.tgz#f9aa84e43a01ce4ccd976b20fbe7c508de884a90" - integrity sha512-JuPDdmxd+AtPWPHu9uaLvTsnEPaZODZk+zpagziNbDKy8DRiU1cy+t+QEjB5WizZt0A5MkuxDTjZ/8/sG5GaYQ== - dependencies: - "@stdlib/constants-float64-ninf" "^0.0.x" - "@stdlib/constants-float64-pinf" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/math-base-assert-is-nan@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/math-base-assert-is-nan/-/math-base-assert-is-nan-0.0.8.tgz#0cd6a546ca1e758251f04898fc906f6fce9e0f80" - integrity sha512-m+gCVBxLFW8ZdAfdkATetYMvM7sPFoMKboacHjb1pe21jHQqVb+/4bhRSDg6S7HGX7/8/bSzEUm9zuF7vqK5rQ== - dependencies: - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/math-base-napi-binary@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/math-base-napi-binary/-/math-base-napi-binary-0.0.8.tgz#b2754b021e40e3982c5f22b853ca50724b9eb8de" - integrity sha512-B8d0HBPhfXefbdl/h0h5c+lM2sE+/U7Fb7hY/huVeoQtBtEx0Jbx/qKvPSVxMjmWCKfWlbPpbgKpN5GbFgLiAg== - dependencies: - "@stdlib/complex-float32" "^0.0.x" - "@stdlib/complex-float64" "^0.0.x" - "@stdlib/complex-reim" "^0.0.x" - "@stdlib/complex-reimf" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/math-base-napi-unary@^0.0.x": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@stdlib/math-base-napi-unary/-/math-base-napi-unary-0.0.9.tgz#3a70fa64128aca7011c5a477110d2682d06c8ea8" - integrity sha512-2WNKhjCygkGMp0RgjaD7wAHJTqPZmuVW7yPOc62Tnz2U+Ad8q/tcOcN+uvq2dtKsAGr1HDMIQxZ/XrrThMePyA== - dependencies: - "@stdlib/complex-float32" "^0.0.7" - "@stdlib/complex-float64" "^0.0.8" - "@stdlib/complex-reim" "^0.0.6" - "@stdlib/complex-reimf" "^0.0.1" - "@stdlib/utils-library-manifest" "^0.0.8" - -"@stdlib/math-base-special-abs@^0.0.x": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@stdlib/math-base-special-abs/-/math-base-special-abs-0.0.6.tgz#1e95dbeaf417ef779c6ab6beaf15f9f96cae6fa9" - integrity sha512-FaaMUnYs2qIVN3kI5m/qNlBhDnjszhDOzEhxGEoQWR/k0XnxbCsTyjNesR2DkpiKuoAXAr9ojoDe2qBYdirWoQ== - dependencies: - "@stdlib/math-base-napi-unary" "^0.0.x" - "@stdlib/number-float64-base-to-words" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/math-base-special-copysign@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/math-base-special-copysign/-/math-base-special-copysign-0.0.7.tgz#d2ead27ff93a84a46263ecfa5f9838a8ab809cfc" - integrity sha512-7Br7oeuVJSBKG8BiSk/AIRFTBd2sbvHdV3HaqRj8tTZHX8BQomZ3Vj4Qsiz3kPyO4d6PpBLBTYlGTkSDlGOZJA== - dependencies: - "@stdlib/constants-float64-high-word-abs-mask" "^0.0.x" - "@stdlib/constants-float64-high-word-sign-mask" "^0.0.x" - "@stdlib/math-base-napi-binary" "^0.0.x" - "@stdlib/number-float64-base-from-words" "^0.0.x" - "@stdlib/number-float64-base-get-high-word" "^0.0.x" - "@stdlib/number-float64-base-to-words" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/math-base-special-ldexp@^0.0.5": - version "0.0.5" - resolved "https://registry.yarnpkg.com/@stdlib/math-base-special-ldexp/-/math-base-special-ldexp-0.0.5.tgz#df5a1fc0252a6d6cc5f12126af903e7391d78aad" - integrity sha512-RLRsPpCdcJZMhwb4l4B/FsmGfEPEWAsik6KYUkUSSHb7ok/gZWt8LgVScxGMpJMpl5IV0v9qG4ZINVONKjX5KA== - dependencies: - "@stdlib/constants-float64-exponent-bias" "^0.0.x" - "@stdlib/constants-float64-max-base2-exponent" "^0.0.x" - "@stdlib/constants-float64-max-base2-exponent-subnormal" "^0.0.x" - "@stdlib/constants-float64-min-base2-exponent-subnormal" "^0.0.x" - "@stdlib/constants-float64-ninf" "^0.0.x" - "@stdlib/constants-float64-pinf" "^0.0.x" - "@stdlib/math-base-assert-is-infinite" "^0.0.x" - "@stdlib/math-base-assert-is-nan" "^0.0.x" - "@stdlib/math-base-special-copysign" "^0.0.x" - "@stdlib/number-float64-base-exponent" "^0.0.x" - "@stdlib/number-float64-base-from-words" "^0.0.x" - "@stdlib/number-float64-base-normalize" "^0.0.x" - "@stdlib/number-float64-base-to-words" "^0.0.x" - -"@stdlib/number-ctor@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/number-ctor/-/number-ctor-0.0.7.tgz#e97a66664639c9853b6c80bc7a15f7d67a2fc991" - integrity sha512-kXNwKIfnb10Ro3RTclhAYqbE3DtIXax+qpu0z1/tZpI2vkmTfYDQLno2QJrzJsZZgdeFtXIws+edONN9kM34ow== - -"@stdlib/number-float64-base-exponent@^0.0.x": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@stdlib/number-float64-base-exponent/-/number-float64-base-exponent-0.0.6.tgz#cd4483d9faccaf7324c385da8e37d5ecf2f120b0" - integrity sha512-wLXsG+cvynmapoffmj5hVNDH7BuHIGspBcTCdjPaD+tnqPDIm03qV5Z9YBhDh91BdOCuPZQ8Ovu2WBpX+ySeGg== - dependencies: - "@stdlib/constants-float64-exponent-bias" "^0.0.x" - "@stdlib/constants-float64-high-word-exponent-mask" "^0.0.x" - "@stdlib/number-float64-base-get-high-word" "^0.0.x" - -"@stdlib/number-float64-base-from-words@^0.0.x": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@stdlib/number-float64-base-from-words/-/number-float64-base-from-words-0.0.6.tgz#886e7dedd086e97d38b7e5fcf4c310467dbaac3c" - integrity sha512-r0elnekypCN831aw9Gp8+08br8HHAqvqtc5uXaxEh3QYIgBD/QM5qSb3b7WSAQ0ZxJJKdoykupODWWBkWQTijg== - dependencies: - "@stdlib/array-float64" "^0.0.x" - "@stdlib/array-uint32" "^0.0.x" - "@stdlib/assert-is-little-endian" "^0.0.x" - "@stdlib/number-float64-base-to-words" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/number-float64-base-get-high-word@^0.0.x": - version "0.0.6" - resolved "https://registry.yarnpkg.com/@stdlib/number-float64-base-get-high-word/-/number-float64-base-get-high-word-0.0.6.tgz#4d3b8731a22017521cc7fc3ba57c7915b3e20fee" - integrity sha512-jSFSYkgiG/IzDurbwrDKtWiaZeSEJK8iJIsNtbPG1vOIdQMRyw+t0bf3Kf3vuJu/+bnSTvYZLqpCO6wzT/ve9g== - dependencies: - "@stdlib/array-float64" "^0.0.x" - "@stdlib/array-uint32" "^0.0.x" - "@stdlib/assert-is-little-endian" "^0.0.x" - "@stdlib/number-float64-base-to-words" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/number-float64-base-normalize@^0.0.x": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@stdlib/number-float64-base-normalize/-/number-float64-base-normalize-0.0.9.tgz#9e98eda47faa9ffc24bcf8161e587ae7b5f96a39" - integrity sha512-+rm7RQJEj8zHkqYFE2a6DgNQSB5oKE/IydHAajgZl40YB91BoYRYf/ozs5/tTwfy2Fc04+tIpSfFtzDr4ZY19Q== - dependencies: - "@stdlib/constants-float64-smallest-normal" "^0.0.x" - "@stdlib/math-base-assert-is-infinite" "^0.0.x" - "@stdlib/math-base-assert-is-nan" "^0.0.x" - "@stdlib/math-base-special-abs" "^0.0.x" - "@stdlib/types" "^0.0.x" - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/number-float64-base-to-float32@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/number-float64-base-to-float32/-/number-float64-base-to-float32-0.0.7.tgz#c7b82bb26cb7404017ede32cebe5864fd84c0e35" - integrity sha512-PNUSi6+cqfFiu4vgFljUKMFY2O9PxI6+T+vqtIoh8cflf+PjSGj3v4QIlstK9+6qU40eGR5SHZyLTWdzmNqLTQ== - dependencies: - "@stdlib/array-float32" "^0.0.x" - -"@stdlib/number-float64-base-to-words@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/number-float64-base-to-words/-/number-float64-base-to-words-0.0.7.tgz#b3e88daa82334d90cf416f5387f503f66849545e" - integrity sha512-7wsYuq+2MGp9rAkTnQ985rah7EJI9TfgHrYSSd4UIu4qIjoYmWIKEhIDgu7/69PfGrls18C3PxKg1pD/v7DQTg== - dependencies: - "@stdlib/array-float64" "^0.0.x" - "@stdlib/array-uint32" "^0.0.x" - "@stdlib/assert-is-little-endian" "^0.0.x" - "@stdlib/os-byte-order" "^0.0.x" - "@stdlib/os-float-word-order" "^0.0.x" - "@stdlib/types" "^0.0.x" - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/os-byte-order@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/os-byte-order/-/os-byte-order-0.0.7.tgz#131e02fb2ec67d172b9fe57caa629809fba11e7f" - integrity sha512-rRJWjFM9lOSBiIX4zcay7BZsqYBLoE32Oz/Qfim8cv1cN1viS5D4d3DskRJcffw7zXDnG3oZAOw5yZS0FnlyUg== - dependencies: - "@stdlib/assert-is-big-endian" "^0.0.x" - "@stdlib/assert-is-little-endian" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/os-float-word-order@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/os-float-word-order/-/os-float-word-order-0.0.7.tgz#067914ee1d1196b20d136c2eb55db6fd217833b4" - integrity sha512-gXIcIZf+ENKP7E41bKflfXmPi+AIfjXW/oU+m8NbP3DQasqHaZa0z5758qvnbO8L1lRJb/MzLOkIY8Bx/0cWEA== - dependencies: - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - "@stdlib/os-byte-order" "^0.0.x" - "@stdlib/utils-library-manifest" "^0.0.x" - -"@stdlib/process-cwd@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/process-cwd/-/process-cwd-0.0.8.tgz#5eef63fb75ffb5fc819659d2f450fa3ee2aa10bf" - integrity sha512-GHINpJgSlKEo9ODDWTHp0/Zc/9C/qL92h5Mc0QlIFBXAoUjy6xT4FB2U16wCNZMG3eVOzt5+SjmCwvGH0Wbg3Q== - dependencies: - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - -"@stdlib/process-read-stdin@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/process-read-stdin/-/process-read-stdin-0.0.7.tgz#684ad531759c6635715a67bdd8721fc249baa200" - integrity sha512-nep9QZ5iDGrRtrZM2+pYAvyCiYG4HfO0/9+19BiLJepjgYq4GKeumPAQo22+1xawYDL7Zu62uWzYszaVZcXuyw== - dependencies: - "@stdlib/assert-is-function" "^0.0.x" - "@stdlib/assert-is-string" "^0.0.x" - "@stdlib/buffer-ctor" "^0.0.x" - "@stdlib/buffer-from-string" "^0.0.x" - "@stdlib/streams-node-stdin" "^0.0.x" - "@stdlib/utils-next-tick" "^0.0.x" - -"@stdlib/regexp-eol@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/regexp-eol/-/regexp-eol-0.0.7.tgz#cf1667fdb5da1049c2c2f8d5c47dcbaede8650a4" - integrity sha512-BTMpRWrmlnf1XCdTxOrb8o6caO2lmu/c80XSyhYCi1DoizVIZnqxOaN5yUJNCr50g28vQ47PpsT3Yo7J3SdlRA== - dependencies: - "@stdlib/assert-has-own-property" "^0.0.x" - "@stdlib/assert-is-boolean" "^0.0.x" - "@stdlib/assert-is-plain-object" "^0.0.x" - "@stdlib/assert-is-string" "^0.0.x" - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - -"@stdlib/regexp-extended-length-path@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/regexp-extended-length-path/-/regexp-extended-length-path-0.0.7.tgz#7f76641c29895771e6249930e1863e7e137a62e0" - integrity sha512-z6uqzMWq3WPDKbl4MIZJoNA5ZsYLQI9G3j2TIvhU8X2hnhlku8p4mvK9F+QmoVvgPxKliwNnx/DAl7ltutSDKw== - dependencies: - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - -"@stdlib/regexp-function-name@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/regexp-function-name/-/regexp-function-name-0.0.7.tgz#e8dc6c7fe9276f0a8b4bc7f630a9e32ba9f37250" - integrity sha512-MaiyFUUqkAUpUoz/9F6AMBuMQQfA9ssQfK16PugehLQh4ZtOXV1LhdY8e5Md7SuYl9IrvFVg1gSAVDysrv5ZMg== - dependencies: - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - -"@stdlib/regexp-regexp@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/regexp-regexp/-/regexp-regexp-0.0.8.tgz#50221b52088cd427ef19fae6593977c1c3f77e87" - integrity sha512-S5PZICPd/XRcn1dncVojxIDzJsHtEleuJHHD7ji3o981uPHR7zI2Iy9a1eV2u7+ABeUswbI1Yuix6fXJfcwV1w== - dependencies: - "@stdlib/utils-define-nonenumerable-read-only-property" "^0.0.x" - -"@stdlib/streams-node-stdin@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/streams-node-stdin/-/streams-node-stdin-0.0.7.tgz#65ff09a2140999702a1ad885e6505334d947428f" - integrity sha512-gg4lgrjuoG3V/L29wNs32uADMCqepIcmoOFHJCTAhVe0GtHDLybUVnLljaPfdvmpPZmTvmusPQtIcscbyWvAyg== - -"@stdlib/string-base-format-interpolate@^0.0.x": - version "0.0.4" - resolved "https://registry.yarnpkg.com/@stdlib/string-base-format-interpolate/-/string-base-format-interpolate-0.0.4.tgz#297eeb23c76f745dcbb3d9dbd24e316773944538" - integrity sha512-8FC8+/ey+P5hf1B50oXpXzRzoAgKI1rikpyKZ98Xmjd5rcbSq3NWYi8TqOF8mUHm9hVZ2CXWoNCtEe2wvMQPMg== - -"@stdlib/string-base-format-tokenize@^0.0.x": - version "0.0.4" - resolved "https://registry.yarnpkg.com/@stdlib/string-base-format-tokenize/-/string-base-format-tokenize-0.0.4.tgz#c1fc612ee0c0de5516dbf083e88c11d14748c30e" - integrity sha512-+vMIkheqAhDeT/iF5hIQo95IMkt5IzC68eR3CxW1fhc48NMkKFE2UfN73ET8fmLuOanLo/5pO2E90c2G7PExow== - -"@stdlib/string-format@^0.0.x": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@stdlib/string-format/-/string-format-0.0.3.tgz#e916a7be14d83c83716f5d30b1b1af94c4e105b9" - integrity sha512-1jiElUQXlI/tTkgRuzJi9jUz/EjrO9kzS8VWHD3g7gdc3ZpxlA5G9JrIiPXGw/qmZTi0H1pXl6KmX+xWQEQJAg== - dependencies: - "@stdlib/string-base-format-interpolate" "^0.0.x" - "@stdlib/string-base-format-tokenize" "^0.0.x" - -"@stdlib/string-lowercase@^0.0.x": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@stdlib/string-lowercase/-/string-lowercase-0.0.9.tgz#487361a10364bd0d9b5ee44f5cc654c7da79b66d" - integrity sha512-tXFFjbhIlDak4jbQyV1DhYiSTO8b1ozS2g/LELnsKUjIXECDKxGFyWYcz10KuyAWmFotHnCJdIm8/blm2CfDIA== - dependencies: - "@stdlib/assert-is-string" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - "@stdlib/process-read-stdin" "^0.0.x" - "@stdlib/streams-node-stdin" "^0.0.x" - "@stdlib/string-format" "^0.0.x" - -"@stdlib/string-replace@^0.0.x": - version "0.0.11" - resolved "https://registry.yarnpkg.com/@stdlib/string-replace/-/string-replace-0.0.11.tgz#5e8790cdf4d9805ab78cc5798ab3d364dfbf5016" - integrity sha512-F0MY4f9mRE5MSKpAUfL4HLbJMCbG6iUTtHAWnNeAXIvUX1XYIw/eItkA58R9kNvnr1l5B08bavnjrgTJGIKFFQ== - dependencies: - "@stdlib/assert-is-function" "^0.0.x" - "@stdlib/assert-is-regexp" "^0.0.x" - "@stdlib/assert-is-regexp-string" "^0.0.x" - "@stdlib/assert-is-string" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - "@stdlib/process-read-stdin" "^0.0.x" - "@stdlib/regexp-eol" "^0.0.x" - "@stdlib/streams-node-stdin" "^0.0.x" - "@stdlib/string-format" "^0.0.x" - "@stdlib/utils-escape-regexp-string" "^0.0.x" - "@stdlib/utils-regexp-from-string" "^0.0.x" - -"@stdlib/types@^0.0.x": - version "0.0.14" - resolved "https://registry.yarnpkg.com/@stdlib/types/-/types-0.0.14.tgz#02d3aab7a9bfaeb86e34ab749772ea22f7b2f7e0" - integrity sha512-AP3EI9/il/xkwUazcoY+SbjtxHRrheXgSbWZdEGD+rWpEgj6n2i63hp6hTOpAB5NipE0tJwinQlDGOuQ1lCaCw== - -"@stdlib/utils-constructor-name@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/utils-constructor-name/-/utils-constructor-name-0.0.8.tgz#ef63d17466c555b58b348a0c1175cee6044b8848" - integrity sha512-GXpyNZwjN8u3tyYjL2GgGfrsxwvfogUC3gg7L7NRZ1i86B6xmgfnJUYHYOUnSfB+R531ET7NUZlK52GxL7P82Q== - dependencies: - "@stdlib/assert-is-buffer" "^0.0.x" - "@stdlib/regexp-function-name" "^0.0.x" - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/utils-convert-path@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/utils-convert-path/-/utils-convert-path-0.0.8.tgz#a959d02103eee462777d222584e72eceef8c223b" - integrity sha512-GNd8uIswrcJCctljMbmjtE4P4oOjhoUIfMvdkqfSrRLRY+ZqPB2xM+yI0MQFfUq/0Rnk/xtESlGSVLz9ZDtXfA== - dependencies: - "@stdlib/assert-is-string" "^0.0.x" - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-read-file" "^0.0.x" - "@stdlib/process-read-stdin" "^0.0.x" - "@stdlib/regexp-eol" "^0.0.x" - "@stdlib/regexp-extended-length-path" "^0.0.x" - "@stdlib/streams-node-stdin" "^0.0.x" - "@stdlib/string-lowercase" "^0.0.x" - "@stdlib/string-replace" "^0.0.x" - -"@stdlib/utils-define-nonenumerable-read-only-property@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/utils-define-nonenumerable-read-only-property/-/utils-define-nonenumerable-read-only-property-0.0.7.tgz#ee74540c07bfc3d997ef6f8a1b2df267ea0c07ca" - integrity sha512-c7dnHDYuS4Xn3XBRWIQBPcROTtP/4lkcFyq0FrQzjXUjimfMgHF7cuFIIob6qUTnU8SOzY9p0ydRR2QJreWE6g== - dependencies: - "@stdlib/types" "^0.0.x" - "@stdlib/utils-define-property" "^0.0.x" - -"@stdlib/utils-define-property@^0.0.x": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@stdlib/utils-define-property/-/utils-define-property-0.0.9.tgz#2f40ad66e28099714e3774f3585db80b13816e76" - integrity sha512-pIzVvHJvVfU/Lt45WwUAcodlvSPDDSD4pIPc9WmIYi4vnEBA9U7yHtiNz2aTvfGmBMTaLYTVVFIXwkFp+QotMA== - dependencies: - "@stdlib/types" "^0.0.x" - -"@stdlib/utils-escape-regexp-string@^0.0.x": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@stdlib/utils-escape-regexp-string/-/utils-escape-regexp-string-0.0.9.tgz#36f25d78b2899384ca6c97f4064a8b48edfedb6e" - integrity sha512-E+9+UDzf2mlMLgb+zYrrPy2FpzbXh189dzBJY6OG+XZqEJAXcjWs7DURO5oGffkG39EG5KXeaQwDXUavcMDCIw== - dependencies: - "@stdlib/assert-is-string" "^0.0.x" - "@stdlib/string-format" "^0.0.x" - -"@stdlib/utils-get-prototype-of@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/utils-get-prototype-of/-/utils-get-prototype-of-0.0.7.tgz#f677132bcbc0ec89373376637148d364435918df" - integrity sha512-fCUk9lrBO2ELrq+/OPJws1/hquI4FtwG0SzVRH6UJmJfwb1zoEFnjcwyDAy+HWNVmo3xeRLsrz6XjHrJwer9pg== - dependencies: - "@stdlib/assert-is-function" "^0.0.x" - "@stdlib/utils-native-class" "^0.0.x" - -"@stdlib/utils-global@^0.0.x": - version "0.0.7" - resolved "https://registry.yarnpkg.com/@stdlib/utils-global/-/utils-global-0.0.7.tgz#0d99dcd11b72ad10b97dfb43536ff50436db6fb4" - integrity sha512-BBNYBdDUz1X8Lhfw9nnnXczMv9GztzGpQ88J/6hnY7PHJ71av5d41YlijWeM9dhvWjnH9I7HNE3LL7R07yw0kA== - dependencies: - "@stdlib/assert-is-boolean" "^0.0.x" - -"@stdlib/utils-library-manifest@^0.0.8", "@stdlib/utils-library-manifest@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/utils-library-manifest/-/utils-library-manifest-0.0.8.tgz#61d3ed283e82c8f14b7f952d82cfb8e47d036825" - integrity sha512-IOQSp8skSRQn9wOyMRUX9Hi0j/P5v5TvD8DJWTqtE8Lhr8kVVluMBjHfvheoeKHxfWAbNHSVpkpFY/Bdh/SHgQ== - dependencies: - "@stdlib/cli-ctor" "^0.0.x" - "@stdlib/fs-resolve-parent-path" "^0.0.x" - "@stdlib/utils-convert-path" "^0.0.x" - debug "^2.6.9" - resolve "^1.1.7" - -"@stdlib/utils-native-class@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/utils-native-class/-/utils-native-class-0.0.8.tgz#2e79de97f85d88a2bb5baa7a4528add71448d2be" - integrity sha512-0Zl9me2V9rSrBw/N8o8/9XjmPUy8zEeoMM0sJmH3N6C9StDsYTjXIAMPGzYhMEWaWHvGeYyNteFK2yDOVGtC3w== - dependencies: - "@stdlib/assert-has-own-property" "^0.0.x" - "@stdlib/assert-has-tostringtag-support" "^0.0.x" - -"@stdlib/utils-next-tick@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/utils-next-tick/-/utils-next-tick-0.0.8.tgz#72345745ec3b3aa2cedda056338ed95daae9388c" - integrity sha512-l+hPl7+CgLPxk/gcWOXRxX/lNyfqcFCqhzzV/ZMvFCYLY/wI9lcWO4xTQNMALY2rp+kiV+qiAiO9zcO+hewwUg== - -"@stdlib/utils-noop@^0.0.x": - version "0.0.14" - resolved "https://registry.yarnpkg.com/@stdlib/utils-noop/-/utils-noop-0.0.14.tgz#8a2077fae0877c4c9e4c5f72f3c9284ca109d4c3" - integrity sha512-A5faFEUfszMgd93RCyB+aWb62hQxgP+dZ/l9rIOwNWbIrCYNwSuL4z50lNJuatnwwU4BQ4EjQr+AmBsnvuLcyQ== - -"@stdlib/utils-regexp-from-string@^0.0.x": - version "0.0.9" - resolved "https://registry.yarnpkg.com/@stdlib/utils-regexp-from-string/-/utils-regexp-from-string-0.0.9.tgz#fe4745a9a000157b365971c513fd7d4b2cb9ad6e" - integrity sha512-3rN0Mcyiarl7V6dXRjFAUMacRwe0/sYX7ThKYurf0mZkMW9tjTP+ygak9xmL9AL0QQZtbrFFwWBrDO+38Vnavw== - dependencies: - "@stdlib/assert-is-string" "^0.0.x" - "@stdlib/regexp-regexp" "^0.0.x" - "@stdlib/string-format" "^0.0.x" - -"@stdlib/utils-type-of@^0.0.x": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@stdlib/utils-type-of/-/utils-type-of-0.0.8.tgz#c62ed3fcf629471fe80d83f44c4e325860109cbe" - integrity sha512-b4xqdy3AnnB7NdmBBpoiI67X4vIRxvirjg3a8BfhM5jPr2k0njby1jAbG9dUxJvgAV6o32S4kjUgfIdjEYpTNQ== - dependencies: - "@stdlib/utils-constructor-name" "^0.0.x" - "@stdlib/utils-global" "^0.0.x" - "@storybook/addon-actions@7.0.5", "@storybook/addon-actions@^7.0.5": version "7.0.5" resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-7.0.5.tgz#59525c66dcf9c5dfa7202f05e6a649eb73dba521" @@ -8847,11 +7922,6 @@ draft-js@^0.10.4, draft-js@~0.10.0, draft-js@~0.10.1: immutable "~3.7.4" object-assign "^4.1.0" -dset@^3.1.1, dset@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.2.tgz#89c436ca6450398396dc6538ea00abc0c54cd45a" - integrity sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q== - duplexer@^0.1.2, duplexer@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" @@ -12782,11 +11852,6 @@ js-base64@^2.1.9: resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== -js-cookie@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-3.0.1.tgz#9e39b4c6c2f56563708d7d31f6f5f21873a92414" - integrity sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw== - js-sdsl@^4.1.4: version "4.2.0" resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.2.0.tgz#278e98b7bea589b8baaf048c20aeb19eb7ad09d0" @@ -14306,13 +13371,6 @@ neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1, neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -new-date@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/new-date/-/new-date-1.0.3.tgz#a5956086d3f5ed43d0b210d87a10219ccb7a2326" - integrity sha512-0fsVvQPbo2I18DT2zVHpezmeeNYV2JaJSrseiHLc17GNOxJzUdx5mvSigPu8LtIfZSij5i1wXnXFspEs2CD6hA== - dependencies: - "@segment/isodate" "1.0.3" - next-tick@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" @@ -14491,11 +13549,6 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -obj-case@0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/obj-case/-/obj-case-0.2.1.tgz#13a554d04e5ca32dfd9d566451fd2b0e11007f1a" - integrity sha512-PquYBBTy+Y6Ob/O2574XHhDtHJlV1cJHMCgW+rDRc9J5hhmRelJB3k5dTK/3cVmFVtzvAKuENeuLpoyTzMzkOg== - object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -17775,7 +16828,7 @@ space-separated-tokens@^2.0.0: resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz#1ecd9d2350a3844572c3f4a312bceb018348859f" integrity sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q== -spark-md5@^3.0.0, spark-md5@^3.0.1: +spark-md5@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/spark-md5/-/spark-md5-3.0.2.tgz#7952c4a30784347abcee73268e473b9c0167e3fc" integrity sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw== @@ -18614,11 +17667,6 @@ tiny-glob@^0.2.9: globalyzer "0.1.0" globrex "^0.1.2" -tiny-hashes@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tiny-hashes/-/tiny-hashes-1.0.1.tgz#ddbe9060312ddb4efe0a174bb3a27e1331c425a1" - integrity sha512-knIN5zj4fl7kW4EBU5sLP20DWUvi/rVouvJezV0UAym2DkQaqm365Nyc8F3QEiOvunNDMxR8UhcXd1d5g+Wg1g== - tinycolor2@^1.4.1: version "1.6.0" resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e" @@ -18816,11 +17864,6 @@ tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== -tslib@^2.4.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410" - integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig== - tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -18973,12 +18016,7 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -unfetch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-3.1.2.tgz#dc271ef77a2800768f7b459673c5604b5101ef77" - integrity sha512-L0qrK7ZeAudGiKYw6nzFjnJ2D5WHblUBwmHIqtPS6oKUd+Hcpk7/hKsSmcHsTlpd1TbTNsiRBUKRq3bHLNIqIw== - -unfetch@^4.1.0, unfetch@^4.2.0: +unfetch@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" integrity sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA== From a5a1d43fb62b0fb2b982121b125b05076e740cba Mon Sep 17 00:00:00 2001 From: Kiril Kartunov Date: Tue, 19 Nov 2024 09:12:11 +0200 Subject: [PATCH 05/40] PM-324 drop Contentful dependency --- src/apps/dev-center/README.md | 13 -- .../landing-page/DevCenterLandingPage.tsx | 2 - .../ArticleCard/ArticleCard.module.scss | 91 ---------- .../ArticleCard/ArticleCard.tsx | 169 ------------------ .../ArticleCard/index.tsx | 1 - .../dev-center-articles-section/Articles.ts | 28 --- .../CardSection/CardSection.module.scss | 102 ----------- .../CardSection/CardSection.tsx | 73 -------- .../CardSection/index.tsx | 1 - .../DevCenterArticlesSection.module.scss | 26 --- .../DevCenterArticlesSection.tsx | 17 -- .../articles.config.ts | 83 --------- .../dev-center-articles-section/index.tsx | 1 - .../models/articleentry.model.ts | 10 -- .../models/blogpost.model.ts | 8 - .../models/index.ts | 3 - .../models/thrivearticle.model.ts | 10 -- 17 files changed, 638 deletions(-) delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.module.scss delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.tsx delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/index.tsx delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/Articles.ts delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.module.scss delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.tsx delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/index.tsx delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.module.scss delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.tsx delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/articles.config.ts delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/index.tsx delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/articleentry.model.ts delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/blogpost.model.ts delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/index.ts delete mode 100644 src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/thrivearticle.model.ts diff --git a/src/apps/dev-center/README.md b/src/apps/dev-center/README.md index adde14a01..ee5fd3480 100644 --- a/src/apps/dev-center/README.md +++ b/src/apps/dev-center/README.md @@ -1,16 +1,3 @@ -# Dev Center Configuration - -The app requires two environment variables, which contain the space id and the key used to access contentful and retrieve Thrive Articles. - -You should create a file named `.env` in the root folder, and write inside the following lines: - -```sh -REACT_APP_CONTENTFUL_EDU_SPACE_ID= -REACT_APP_CONTENTFUL_EDU_CDN_API_KEY= -``` - -We should use the same space ID and API Key as Topcoder Thrive, these are for fetching Thrive articles and videos in the landing page. - ## Landing page We can configure up to 5 articles shown on the landing page. The articles can be from Topcoder Thrive and/or Topcoder Blog. diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/DevCenterLandingPage.tsx b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/DevCenterLandingPage.tsx index 26b0de173..899452ef3 100644 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/DevCenterLandingPage.tsx +++ b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/DevCenterLandingPage.tsx @@ -1,6 +1,5 @@ import { FC } from 'react' -import { DevCenterArticlesection } from './dev-center-articles-section' import { DevCenterGetStarted } from './dev-center-get-started' import { DevCenterHeader } from './dev-center-header' import styles from './DevCenterLandingPage.module.scss' @@ -9,7 +8,6 @@ const DevCenter: FC = () => (
-
) diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.module.scss b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.module.scss deleted file mode 100644 index 700e92492..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.module.scss +++ /dev/null @@ -1,91 +0,0 @@ -@import "@libs/ui/styles/includes"; - -.outerContainer{ - border-radius: 8px; - position: relative; - background-size: 100% 100%; - overflow: hidden; - - @include ltemd{ - background-size: cover; - } - - .innerContainer { - width: 100%; - height: 100%; - background: linear-gradient(180deg, rgba(0, 0, 0, 0) 30.21%, #000000 100%); - - .playButton { - width: 38px; - height: 38px; - color: $tc-white; - position: absolute; - left: calc(50% - 19px); - top: calc(50% - 19px); - } - - .container { - padding-left: $sp-6; - padding-right: $sp-6; - padding-bottom: $sp-6; - position: absolute; - bottom: 0px; - width: 100%; - - .topLine { - display: flex; - flex-direction: row; - justify-content: space-between; - margin-bottom: 14px; - align-items: center; - } - - .author { - opacity: 0.72; - text-transform: capitalize; - display: block; - margin-bottom: $sp-4; - } - - .summary { - @include font-weight-normal; - display: block; - white-space: nowrap; - overflow: hidden; - margin-bottom: $sp-4; - text-overflow: ellipsis; - } - - .readMore { - font-weight: 700; - font-size: 16px; - line-height: 16px; - text-transform: uppercase; - } - - - } - - - } -} - -.mainArticle { - - @include ltemd{ - aspect-ratio: 4 / 3; - } -} - -.smallArticle { - aspect-ratio: 4 /3; - - @include ltemd{ - width: 100%; - max-height: 240px; - } -} - -.mainArticle:hover, .smallArticle:hover{ - cursor: pointer; -} diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.tsx b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.tsx deleted file mode 100644 index ba38a80ba..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/ArticleCard.tsx +++ /dev/null @@ -1,169 +0,0 @@ -import { FC } from 'react' -import classNames from 'classnames' - -import { THRIVE_PAGE } from '~/apps/dev-center/src/config' -import { IconSolid } from '~/libs/ui' - -import { DevCenterTag } from '../../dev-center-tag' -import { isThriveArticle } from '../Articles' -import { BlogPost, ThriveArticle } from '../models' - -import styles from './ArticleCard.module.scss' - -interface ArticleDetails { - author: string - image: string - isThrive: boolean - isVideo: boolean - summary: string - tagText: string - url: string -} - -function openArticle(url: string): void { - window.open( - url, - '_blank', // This is what makes it open in a new window. - ) -} - -function getTagText(isThrive: boolean, isVideo: boolean): string { - return isThrive - ? isVideo - ? 'Thrive Video' - : 'Thrive Article' - : 'Success Story' -} - -function getArticleContent( - article: ThriveArticle | BlogPost, - isThrive: boolean, -): string { - return isThrive ? (article as ThriveArticle).content : (article as BlogPost).contentSnippet -} - -function getArticleDetails(article: ThriveArticle | BlogPost): ArticleDetails { - const isThrive: boolean = isThriveArticle(article) - const thriveArticle: ThriveArticle = article as ThriveArticle - const blogPost: BlogPost = article as BlogPost - const isVideo: boolean = isThrive && thriveArticle.type === 'Video' - - const tagText: string = getTagText(isThrive, isVideo) - - const content: string = getArticleContent(article, isThrive) - const regex: RegExp = /(<([^>]+)>)/gi - const summary: string = content.replace(regex, '') // Remove html from the content string - const url: string = isThrive - ? `${THRIVE_PAGE}/articles/${thriveArticle.slug}` - : blogPost.link - const author: string = !isThrive ? blogPost.creator : '' - const image: string = isThrive - ? thriveArticle.featuredImage.fields.file.url - : blogPost.featuredImage - - return { - author, - image, - isThrive, - isVideo, - summary, - tagText, - url, - } -} - -function getOuterClass(isMain: boolean, className: string): string { - return classNames( - className, - styles.outerContainer, - isMain ? styles.mainArticle : styles.smallArticle, - ) -} - -interface ArticleCardProps { - article: ThriveArticle | BlogPost - className?: string - isMain: boolean -} - -const ArticleCard: FC = props => { - const outerClass: string = getOuterClass(props.isMain, props.className ?? '') - const { - isThrive, - isVideo, - tagText, - summary, - url, - author, - image, - }: ArticleDetails = getArticleDetails(props.article) - - return ( -
-
- {isThrive && isVideo && ( - - )} -
-
- - {isThrive && ( - - {(props.article as ThriveArticle).readTime} - - )} -
- {props.isMain ? ( -

- {props.article.title} -

- ) : ( -

- {props.article.title} -

- )} - {!isThrive && ( - - {author} - - )} - {props.isMain && ( - <> - - {summary} - - - READ MORE - - - )} -
-
-
- ) -} - -export default ArticleCard diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/index.tsx b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/index.tsx deleted file mode 100644 index faf7c7bbc..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/ArticleCard/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default as ArticleCard } from './ArticleCard' diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/Articles.ts b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/Articles.ts deleted file mode 100644 index af43cfba4..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/Articles.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { API_BASE, WP_CONTENT } from '~/apps/dev-center/src/config' - -import { BlogPost, ThriveArticle } from './models' - -/** Check if the article is a BlogPost or a ThriveArticle */ -export function isThriveArticle(article: BlogPost | ThriveArticle): article is ThriveArticle { - return (article as ThriveArticle).readTime !== undefined -} - -/** This is the default image to be used for blog posts that do not provide an url to the hero image */ -const DEFAULT_BLOG_IMAGE: string = `${WP_CONTENT}/uploads/2017/04/SRM_Blog.png` - -/** Get the blog with the given url, or return undefined if the blog couldn't be fetched */ -export async function getBlog(url: string): Promise { - try { - const response: Response = await fetch(`${API_BASE}/blog?limit=200`) - const data: Array = await response.json() - const blog: BlogPost = data.filter(x => x.link === url)[0] - // If the returned data do not contain the URL to the image, use the default one - if (!blog.featuredImage) { - blog.featuredImage = DEFAULT_BLOG_IMAGE - } - - return blog - } catch (e) { - return undefined - } -} diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.module.scss b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.module.scss deleted file mode 100644 index d869817f4..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.module.scss +++ /dev/null @@ -1,102 +0,0 @@ -@import "@libs/ui/styles/includes"; - -.container { - width: 100%; - justify-content: center; - - .innerContainer { - display: grid; - grid-template-columns: 2fr 1fr 1fr; - grid-template-rows: 1fr 1fr; - gap: 32px; - - @include xl{ - grid-template-columns: 1fr 1fr; - grid-template-rows: 2fr 1fr 1fr; - max-width: 812px; - margin: auto; - } - - @include lg{ - grid-template-columns: 1fr 1fr; - grid-template-rows: 2fr 1fr 1fr; - } - - @include ltemd{ - display: flex; - flex-direction: column; - max-width: 400px; - margin: auto; - } - - .mainItem { - grid-row: 1 / span 2; - grid-column: 1; - - @include xl{ - grid-row: 1 ; - grid-column: 1 / span 2; - } - - @include lg{ - grid-row: 1 ; - grid-column: 1 / span 2; - } - } - .item2 { - grid-row: 1; - grid-column: 2; - - @include xl{ - grid-row: 2; - grid-column: 1; - } - @include lg{ - grid-row: 2; - grid-column: 1; - } - } - .item3 { - grid-row: 1; - grid-column: 3; - - @include xl{ - grid-row: 2; - grid-column: 2; - } - @include lg{ - grid-row: 2; - grid-column: 2; - } - } - - .item4 { - grid-row: 2; - grid-column: 2; - - @include xl{ - grid-row: 3; - grid-column: 1; - } - @include lg{ - grid-row: 3; - grid-column: 1; - } - } - .item5 { - grid-row: 2; - grid-column: 3; - - @include xl{ - grid-row: 3; - grid-column: 2; - } - @include lg{ - grid-row: 3; - grid-column: 2; - } - } - } -} - - diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.tsx b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.tsx deleted file mode 100644 index 3617b1f0f..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/CardSection.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { ContentfulClientApi, createClient } from 'contentful' -import { FC, useEffect, useState } from 'react' - -import { ArticleCard } from '../ArticleCard' -import { getBlog } from '../Articles' -import { ArticlesUrl, defaultBlogs } from '../articles.config' -import { ArticleType, BlogPost, ThriveArticle } from '../models' - -import styles from './CardSection.module.scss' - -const CardSection: FC = () => { - const [articles, setArticles]: [ - Array, - React.Dispatch>> - ] = useState>([]) - - useEffect(() => { - const client: ContentfulClientApi = createClient({ - accessToken: ( - process.env.REACT_APP_CONTENTFUL_EDU_CDN_API_KEY - ?? 'EXl1Y8-6VFyHBqJqlxGp2LKmyNJJPutDbKH977G07eg' - ), - space: ( - process.env.REACT_APP_CONTENTFUL_EDU_SPACE_ID - ?? 'piwi0eufbb2g' - ), - }) - Promise.all( - ArticlesUrl.map(async (articleUrl, idx): Promise => { - switch (articleUrl.type) { - case ArticleType.Thrive: - return (await client.getEntry(articleUrl.url)).fields as ThriveArticle - - case ArticleType.Blog: { - const blog: BlogPost - = (await getBlog(articleUrl.url)) - ?? defaultBlogs[idx] - return blog - } - - default: { - return undefined - } - } - }), - ) - .then(arr => setArticles(arr.filter(Boolean) as Array)) - }, []) - - const articleStyles: Array = [ - styles.mainItem, - styles.item2, - styles.item3, - styles.item4, - styles.item5, - ] - - return ( -
-
- {articles.map((article, index) => ( - - ))} -
-
- ) -} - -export default CardSection diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/index.tsx b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/index.tsx deleted file mode 100644 index 5f4ddacdc..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/CardSection/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default as CardSection } from './CardSection' diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.module.scss b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.module.scss deleted file mode 100644 index 8405de69b..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.module.scss +++ /dev/null @@ -1,26 +0,0 @@ -@import "@libs/ui/styles/includes"; - -.container { - background-color: $black-5; - width: 100%; - height: fit-content; - padding: 80px 0px; - margin-top: 64px; - - @include ltemd { - padding: 40px 0px; - } - - .title { - @include font-black-100; - font-weight: 500; - font-size: 44px; - line-height: 44px; - margin-bottom: $sp-8; - - @include ltemd { - font-size: 27px; - line-height: 28px; - } - } -} diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.tsx b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.tsx deleted file mode 100644 index 2987ef6d9..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/DevCenterArticlesSection.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { FC } from 'react' - -import { ContentLayout } from '~/libs/ui' - -import { CardSection } from './CardSection' -import styles from './DevCenterArticlesSection.module.scss' - -const DevCenterArticlesection: FC = () => ( -
- -

Success Stories And Articles

- -
-
-) - -export default DevCenterArticlesection diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/articles.config.ts b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/articles.config.ts deleted file mode 100644 index bc56e7c9f..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/articles.config.ts +++ /dev/null @@ -1,83 +0,0 @@ -/* eslint-disable max-len */ -import { BLOG_PAGE, WP_CONTENT } from '~/apps/dev-center/src/config' - -import { ArticleEntry, ArticleType, BlogPost } from './models' - -/** - * This array defiens which thirive articles and blog pasts should be shown. - * The first element in the array will be the main article. - * For Thrive Articles, the url should be the Contentful ID. - * For Blog Posts, the url is the url linking to the post on topcoder.com - * Example - * { - * type: ArticleType.Blog, - * url: `${BLOG_PAGE}/talent-as-a-service-taas-a-brilliant-solution-to-the-talent-gap/`, - * } - * { - * type: ArticleType.Thrive, - * url: '6KP9iCELCsLWTSWirplWs2', - * } - */ -export const ArticlesUrl: Array = [ - { - type: ArticleType.Thrive, - url: '6KP9iCELCsLWTSWirplWs2', - }, - { - type: ArticleType.Thrive, - url: '1afUuuZVt1JI14iRkAIqba', - }, - { - type: ArticleType.Thrive, - url: 'puRqAymWv7hjjyHyunGK2', - }, - { - type: ArticleType.Thrive, - url: '6yZJ8xSYTEqVJhMeQyA7BA', - }, - { - type: ArticleType.Thrive, - url: '3QOvaHaSxjF26owDurtfKZ', - }, -] - -/** - * This array contains the default blog posts to be shown if the ones specified above are not available. - */ -export const defaultBlogs: Array = [ - { - contentSnippet: 'In light of the incredible speed of innovation, specialized tech talent has never been more critical to business success. Yet access to that talent remains frustratingly difficult for many companies. According to the Society for Human Resources Management, 83% of businesses are having trouble recruiting suitable candidates for their open positions, particularly when it comes […]\nThe post Talent as a Service (TaaS): A Brilliant Solution to the Talent Gap appeared first on Topcoder.', - creator: 'Kiran Hampapura', - featuredImage: `${WP_CONTENT}/uploads/2019/11/taashero.jpg`, - link: `${BLOG_PAGE}/talent-as-a-service-taas-a-brilliant-solution-to-the-talent-gap/`, - title: 'Talent as a Service (TaaS): A Brilliant Solution to the Talent Gap', - }, - { - contentSnippet: 'Can our Topcoder accounts be hacked? Can our well-earned cash be stolen away through the platform? Can customers suffer from intellectual theft? These sensitive questions belong to a discussion on a beyond-interesting topic: security. Honoring Topcoder’s security themed month, we want to raise awareness on what cyber security means for members and customers. We turned […]\nThe post Securing A Safe Work System For Members And Customers With John Wheeler - The Topcoder Nation Show #18 appeared first on Topcoder.', - creator: 'mahestro', - featuredImage: `${WP_CONTENT}/uploads/2022/07/00-tcn-show-18-john-wheeler.png`, - link: `${BLOG_PAGE}/securing-a-safe-work-system-for-members-and-customers-with-john-wheeler-the-topcoder-nation-show-18/`, - title: 'Securing A Safe Work System For Members And Customers With John Wheeler – The Topcoder Nation Show #18', - }, - { - contentSnippet: 'Job opportunities, upskilling, and mentoring are traits that identify the endeavor that this young gentleman is leading in Africa. Meet Abiodun (), born and raised in Lagos; he aims to close the gap between the tech talent in his region and opportunities, leveraging Topcoder as a medium to make it happen. Abiodun loves live music […]\nThe post Building A Tech Community In Africa With Code_Abbey – The Topcoder Nation Show #17 appeared first on Topcoder.', - creator: 'mahestro', - featuredImage: `${WP_CONTENT}/uploads/2022/06/00-tcn-show-17-code_abby-and-gigs-in-africa.png`, - link: `${BLOG_PAGE}/building-a-tech-community-in-africa-with-code_abbey-the-topcoder-nation-show-17/`, - title: 'Building A Tech Community In Africa With Code_Abbey – The Topcoder Nation Show #17', - }, - { - contentSnippet: 'CellPhoneService We just need to do the calculations described in the statement. One part of the calculations that may be tricky for beginners is the fee per each started minute of a call. If we have a call that takes S seconds, the number of minutes we’ll paying for can be computed by dividing S […]\nThe post Single Round Match 833 Editorials appeared first on Topcoder.', - creator: 'misof', - featuredImage: `${WP_CONTENT}/uploads/2017/04/SRM_Blog.png`, - link: `${BLOG_PAGE}/single-round-match-833-editorials/`, - title: 'Single Round Match 833 Editorials', - }, - { - contentSnippet: 'TwoDimensionalSort Imagine that we label rows of the board A to Z from top to bottom. If we got each rook X into its row X, the board would surely be sorted. With N rooks we can always achieve that in at most 2*N moves. In the first N moves we’ll move some rooks horizontally […]\nThe post TCO22 Round 3 Editorial appeared first on Topcoder.', - creator: 'misof', - featuredImage: `${WP_CONTENT}/uploads/2017/04/SRM_Blog.png`, - link: `${BLOG_PAGE}/tco22-round-3-editorial/`, - title: 'TCO22 Round 3 Editorial', - }, -] diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/index.tsx b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/index.tsx deleted file mode 100644 index 664c74822..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default as DevCenterArticlesection } from './DevCenterArticlesSection' diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/articleentry.model.ts b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/articleentry.model.ts deleted file mode 100644 index bf5466632..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/articleentry.model.ts +++ /dev/null @@ -1,10 +0,0 @@ -export enum ArticleType { - Blog = 'blog', - Thrive = 'thrive', -} - -/** The type of the objects used to specy which articles should be shown inside articles.config.ts */ -export interface ArticleEntry { - type: ArticleType, - url: string, -} diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/blogpost.model.ts b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/blogpost.model.ts deleted file mode 100644 index 69d249f4a..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/blogpost.model.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** The type of the blog post retrieved from the api */ -export interface BlogPost { - contentSnippet: string - creator: string - featuredImage: string - link: string - title: string -} diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/index.ts b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/index.ts deleted file mode 100644 index e612c6a52..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './articleentry.model' -export * from './blogpost.model' -export * from './thrivearticle.model' diff --git a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/thrivearticle.model.ts b/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/thrivearticle.model.ts deleted file mode 100644 index 47e84b5d4..000000000 --- a/src/apps/dev-center/src/dev-center-pages/community-app/landing-page/dev-center-articles-section/models/thrivearticle.model.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** The type of the Thrive Articles retrieved from Contentful */ -export interface ThriveArticle { - content: string - contentAuthor: Array<{ fields: { name: string; }; }> - featuredImage: { fields: { file: { url: string; }; title: string; }; } - readTime: string - slug: string - title: string - type?: string -} From aa0d8d1f23938ec5e7969d3b12c51e82ee320010 Mon Sep 17 00:00:00 2001 From: Vasilica Olariu Date: Mon, 6 Jan 2025 16:48:22 +0200 Subject: [PATCH 06/40] PM-460 - handle scurity scan issues --- src/apps/earn/src/config/dev.ts | 2 +- src/apps/earn/src/config/prod.ts | 2 +- src/apps/earn/src/utils/logger.js | 4 ++++ .../course-curriculum/dice-modal/DiceModal.tsx | 3 ++- src/apps/learn/src/free-code-camp/fcc-frame/FccFrame.tsx | 2 +- .../details/sidebar/WorkDetailDetailsSidebar.tsx | 6 +++--- 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/apps/earn/src/config/dev.ts b/src/apps/earn/src/config/dev.ts index 00fb59cea..d25459e52 100644 --- a/src/apps/earn/src/config/dev.ts +++ b/src/apps/earn/src/config/dev.ts @@ -9,7 +9,7 @@ const DevEarnConfig: EarnConfig = { /* Max number of recommended challenges */ CHALLENGE_DETAILS_MAX_NUMBER_RECOMMENDED_CHALLENGES: 3, - SERVER_API_KEY: '79b2d5eb-c1fd-42c4-9391-6b2c9780d591', + SERVER_API_KEY: process.env.REACT_APP_LOG_SERVER_API_KEY as string, API: { V2: 'https://api.topcoder-dev.com/v2', diff --git a/src/apps/earn/src/config/prod.ts b/src/apps/earn/src/config/prod.ts index 595cc41c9..cd30a2994 100644 --- a/src/apps/earn/src/config/prod.ts +++ b/src/apps/earn/src/config/prod.ts @@ -11,7 +11,7 @@ const ProdEarnConfig: EarnConfig = { /** * URL of Topcoder Connect Website */ - SERVER_API_KEY: 'aa9ccf36-3936-450c-9983-097ddba51bef', + SERVER_API_KEY: process.env.REACT_APP_LOG_SERVER_API_KEY as string, API: { V2: 'https://api.topcoder-dev.com/v2', V3: 'https://api.topcoder-dev.com/v3', diff --git a/src/apps/earn/src/utils/logger.js b/src/apps/earn/src/utils/logger.js index b9ff27559..2238c76af 100644 --- a/src/apps/earn/src/utils/logger.js +++ b/src/apps/earn/src/utils/logger.js @@ -33,6 +33,10 @@ _.functions(console).forEach((func) => { let leLogger; const log = (type, ...rest) => { + if (!config.SERVER_API_KEY) { + return; + } + fetch("/community-app-assets/api/logger", { body: JSON.stringify({ data: rest, diff --git a/src/apps/learn/src/course-details/course-curriculum/dice-modal/DiceModal.tsx b/src/apps/learn/src/course-details/course-curriculum/dice-modal/DiceModal.tsx index 62ed321b7..f78ed776e 100644 --- a/src/apps/learn/src/course-details/course-curriculum/dice-modal/DiceModal.tsx +++ b/src/apps/learn/src/course-details/course-curriculum/dice-modal/DiceModal.tsx @@ -2,6 +2,7 @@ import { Dispatch, FC, SetStateAction, useEffect, useState } from 'react' import { EnvironmentConfig } from '~/config' import { BaseModal, Button } from '~/libs/ui' +import { preventDefault } from '~/apps/earn/src/utils/misc' import styles from './DiceModal.module.scss' @@ -49,7 +50,7 @@ const DiceModal: FC = (props: DiceModalProps) => { click below to refresh your settings.

- + - -

- - ); -}; - -DateInput.propTypes = { - id: PT.string, - isStartDateActive: PT.bool, - startDateString: PT.string, - onStartDateChange: PT.func, - onStartDateFocus: PT.func, - isEndDateActive: PT.bool, - endDateString: PT.string, - onEndDateChange: PT.func, - onEndDateFocus: PT.func, - error: PT.string, - onClickCalendarIcon: PT.func, - onStartEndDateChange: PT.func, - placeholder: PT.string, -}; - -export default DateInput; diff --git a/src/apps/earn/src/components/DateRangePicker/DateInput/styles.scss b/src/apps/earn/src/components/DateRangePicker/DateInput/styles.scss deleted file mode 100644 index 8b637437b..000000000 --- a/src/apps/earn/src/components/DateRangePicker/DateInput/styles.scss +++ /dev/null @@ -1,49 +0,0 @@ -@import "@earn/styles/variables"; -@import "@earn/styles/mixins"; - -.container { - &.isError { - input { - border: 1px solid $tc-level-5; - } - - .errorHint { - display: block; - color: $tc-level-5; - font-size: 12px; - padding: 4px 0; - height: 20px; - } - } -} - -.date-range-input { - margin-top: -12px; - font-size: $font-size-sm; - - @include textinput-show-label; -} - -.input-group { - position: relative; - - .icon { - position: absolute; - top: 22px; - right: 14px; - display: block; - cursor: pointer; - appearance: none; - background: none; - border: none; - padding: 0; - } - - input { - padding-right: 46px !important; - } -} - -.errorHint { - display: none; -} diff --git a/src/apps/earn/src/components/DateRangePicker/helpers.js b/src/apps/earn/src/components/DateRangePicker/helpers.js deleted file mode 100644 index df745c982..000000000 --- a/src/apps/earn/src/components/DateRangePicker/helpers.js +++ /dev/null @@ -1,136 +0,0 @@ -import { useEffect, useRef, useState } from "react"; -import moment from "moment"; - -/** - * Check whether the dates are same - * @param {Date} date1. - * @param {Date} date2. - * @return {boolean} - */ -export function isSameDay(date1, date2) { - if (!date1 || !date2) return false; - return moment(date1).isSame(moment(date2), "day"); -} - -/** - * Check whether the date1 is occur before date2 - * @param {Date} date1. - * @param {Date} date2. - * @return {boolean} - */ -export function isBeforeDay(date1, date2) { - if (!date1 || !date2) return false; - return moment(date1).isBefore(moment(date2), "day"); -} - -/** - * Check whether the date1 is occur after date2 - * @param {Date} date1. - * @param {Date} date2. - * @return {boolean} - */ -export function isAfterDay(date1, date2) { - if (!date1 || !date2) return false; - return moment(date1).isAfter(moment(date2), "day"); -} - -const staticRangeHandler = { - range: {}, - isSelected(range) { - const definedRange = this.range(); - return ( - isSameDay(range.startDate, definedRange.startDate) && - isSameDay(range.endDate, definedRange.endDate) - ); - }, -}; - -/** - * Create defined date ranges - * @return {object[]} list of defined ranges - */ -export function createStaticRanges() { - const today = moment(); - const endOfToday = today.set({ - hour: 23, - minute: 59, - second: 59, - millisecond: 999, - }); - const pastWeek = endOfToday.clone().subtract(1, "week"); - const pastMonth = endOfToday.clone().subtract(1, "month"); - const past6Months = endOfToday.clone().subtract(6, "month"); - const pastYear = endOfToday.clone().subtract(1, "year"); - - const ranges = [ - { - label: "Past Week", - range: () => ({ - startDate: pastWeek.startOf("day").toDate(), - endDate: endOfToday.toDate(), - }), - }, - { - label: "Past Month", - range: () => ({ - startDate: pastMonth.startOf("day").toDate(), - endDate: endOfToday.toDate(), - }), - }, - { - label: "Past 6 Months", - range: () => ({ - startDate: past6Months.startOf("day").toDate(), - endDate: endOfToday.toDate(), - }), - }, - { - label: "Past Year", - range: () => ({ - startDate: pastYear.startOf("day").toDate(), - endDate: endOfToday.toDate(), - }), - }, - ]; - - return ranges.map((range) => ({ ...staticRangeHandler, ...range })); -} - -/** - * React hook for checking if the click is from outside the reference - * @param {boolean} initialIsVisible true if visible and false if hidden - */ -export function useComponentVisible(initialIsVisible) { - const [isComponentVisible, setIsComponentVisible] = useState( - initialIsVisible - ); - const ref = useRef(null); - - const handleHideDropdown = (event) => { - if (event.key === "Escape") { - setIsComponentVisible(false); - } - }; - - const handleClickOutside = (event) => { - if (ref.current && !ref.current.contains(event.target)) { - setIsComponentVisible(false); - } - }; - - useEffect(() => { - document.addEventListener("keydown", handleHideDropdown, true); - document.addEventListener("click", handleClickOutside, true); - return () => { - document.removeEventListener("keydown", handleHideDropdown, true); - document.removeEventListener("click", handleClickOutside, true); - }; - }); - - return { ref, isComponentVisible, setIsComponentVisible }; -} - -export default { - useComponentVisible, - createStaticRanges, -}; diff --git a/src/apps/earn/src/components/DateRangePicker/index.jsx b/src/apps/earn/src/components/DateRangePicker/index.jsx deleted file mode 100644 index fbd840320..000000000 --- a/src/apps/earn/src/components/DateRangePicker/index.jsx +++ /dev/null @@ -1,651 +0,0 @@ -import React, { useState, useEffect } from "react"; -import moment from "moment"; -import { DateRangePicker as ReactDateRangePicker } from "react-date-range"; -import PropTypes from "prop-types"; - -import styles from "./style.scss"; -import { styled as styledCss } from "@earn/utils"; - -import DateInput from "./DateInput"; - -import { - useComponentVisible, - createStaticRanges, - isSameDay, - isAfterDay, - isBeforeDay, -} from "./helpers"; - -const styled = styledCss(styles); - -function DateRangePicker(props) { - const { id, range, onChange, placeholder, enterToSubmit = false } = props; - - const [rangeString, setRangeString] = useState({ - startDateString: "", - endDateString: "", - }); - const [activeDate, setActiveDate] = useState(null); - const [preview, setPreview] = useState(null); - const [focusedRange, setFocusedRange] = useState([0, 0]); - const [errors, setErrors] = useState({ - startDate: undefined, - endDate: undefined, - }); - - const { - ref: calendarRef, - isComponentVisible, - setIsComponentVisible, - } = useComponentVisible(false); - - const isStartDateFocused = focusedRange[1] === 0; - const isEndDateFocused = focusedRange[1] === 1; - - useEffect(() => { - setRangeString({ - startDateString: range.startDate - ? moment(range.startDate).format("MMM D, YYYY") - : "", - endDateString: range.endDate - ? moment(range.endDate).format("MMM D, YYYY") - : "", - }); - }, [range]); - - /** - * Handle end date change on user input - * After user input the end date via keyboard, validate it then update the range state - * @param {Object} e Input Event. - */ - const onEndDateChange = (value) => { - const endDateString = value; - const endDate = moment(endDateString, "MMM D, YYYY", true); - const startDate = moment(rangeString.startDateString, "MMM D, YYYY", true); - - if (endDate.isValid() && isBeforeDay(endDate, startDate)) { - setErrors({ - ...errors, - endDate: "Range Error", - }); - } else if (endDate.isValid()) { - onChange({ - endDate: endDate.toDate(), - startDate: range.startDate, - }); - - setErrors({ - ...errors, - endDate: "", - }); - - setRangeString({ - ...rangeString, - endDateString: endDate.format("MMM D, YYYY"), - }); - } else if (endDateString === "") { - onChange({ - endDate: null, - startDate: range.startDate, - }); - - setErrors({ - ...errors, - endDate: "", - }); - } else { - setErrors({ - ...errors, - endDate: "Invalid End Date Format", - }); - - setRangeString({ - ...rangeString, - endDateString, - }); - } - }; - - /** - * Handle start date change on user input - * After user input the start date via keyboard, validate it then update the range state - * @param {Object} e Input Event. - */ - const onStartDateChange = (value) => { - const startDateString = value; - const startDate = moment(startDateString, "MMM D, YYYY", true); - const endDate = moment(rangeString.endDateString, "MMM D, YYYY", true); - - if ( - startDate.isValid() && - endDate.isValid() && - isAfterDay(startDate, endDate) - ) { - setErrors({ - ...errors, - startDate: "Range Error", - }); - } else if (startDate.isValid()) { - onChange({ - endDate: range.endDate, - startDate: startDate.toDate(), - }); - - setErrors({ - ...errors, - startDate: "", - }); - - setRangeString({ - ...rangeString, - startDateString: startDate.format("MMM D, YYYY"), - }); - } else if (startDateString === "") { - onChange({ - endDate: range.endDate, - startDate: null, - }); - - setErrors({ - ...errors, - startDate: "", - }); - } else { - setErrors({ - ...errors, - startDate: "Invalid Start Date Format", - }); - - setRangeString({ - ...rangeString, - startDateString, - }); - } - }; - - const onStartEndDateChange = ({ startDateString, endDateString }) => { - const startDate = moment(startDateString, "MMM D, YYYY", true); - const endDate = moment(endDateString, "MMM D, YYYY", true); - - if ( - startDate.isValid() && - endDate.isValid() && - isBeforeDay(endDate, startDate) - ) { - setErrors({ - ...errors, - endDate: "Range Error", - }); - } else if (startDate.isValid() && endDate.isValid()) { - onChange({ - endDate: endDate.toDate(), - startDate: startDate.toDate(), - }); - setErrors({ - startDate: "", - endDate: "", - }); - } else if (startDate.isValid()) { - onChange({ - endDate: null, - startDate: startDate.toDate(), - }); - setErrors({ - ...errors, - endDate: "Invalid End Date Format", - }); - } else if (endDate.isValid()) { - onChange({ - endDate: endDate.toDate(), - startDate: null, - }); - setErrors({ - ...errors, - startDate: "Invalid Start Date Format", - }); - } else if (startDateString === "" && endDateString === "") { - onChange({ - endDate: null, - startDate: null, - }); - setErrors({ - startDate: "", - endDate: "", - }); - } else if (startDateString === "") { - onChange({ - endDate: endDate.toDate(), - startDate: null, - }); - - setErrors({ - ...errors, - startDate: "", - }); - } else if (endDateString === "") { - onChange({ - endDate: null, - startDate: startDate.toDate(), - }); - - setErrors({ - ...errors, - endDate: "", - }); - } else { - onChange({ - endDate: null, - startDate: null, - }); - setErrors({ - startDate: "Invalid Start Date Format", - endDate: "Invalid End Date Format", - }); - } - }; - - /** - * Trigger to open calendar modal on calendar icon in start date input - */ - const onIconClickStartDate = () => { - const calendarIcon = document.querySelector(id); - if (calendarIcon) { - calendarIcon.blur(); - } - setFocusedRange([0, 0]); // set current focused input to start date - setActiveDate(null); - setIsComponentVisible(true); - setPreview(null); - }; - - /** - * Trigger to open calendar modal on calendar icon in end date input - */ - const onIconClickEndDate = () => { - const calendarIcon = document.querySelector(id); - if (calendarIcon) { - calendarIcon.blur(); - } - setFocusedRange([0, 1]); // set current focused input to end date - setActiveDate(null); - setIsComponentVisible(true); - setPreview(null); - }; - - const onReset = (presetRange) => { - let newStartDate; - let newEndDate; - - if (presetRange) { - newStartDate = presetRange.startDate; - newEndDate = presetRange.endDate; - } - - setFocusedRange([0, 0]); - - setErrors({ - startDate: "", - endDate: "", - }); - - setRangeString({ - startDateString: newStartDate - ? moment(newStartDate).format("MMM D, YYYY") - : "", - endDateString: newEndDate ? moment(newEndDate).format("MMM D, YYYY") : "", - }); - - onChange({ - startDate: newStartDate ? moment(newStartDate) : null, - endDate: newEndDate ? moment(newEndDate) : null, - }); - - setIsComponentVisible(false); - }; - - /** - * Event handler on date selection changes - * @param {Object} newRange nnew range that has endDate and startDate data - */ - const onDateRangePickerChange = (newRange) => { - let newEndDate = newRange.endDate; - let newStartDate = newRange.startDate; - const isUseKeyPress = focusedRange[0] !== 0; - - if (isUseKeyPress) { - setFocusedRange([0, focusedRange[1]]); - } - - let shouldCloseCalendar = true; - let shouldOpenNextCalendar = false; - - // User is active on start date calendar modal - if ( - isStartDateFocused && - (isUseKeyPress || isSameDay(newStartDate, newEndDate)) - ) { - if (range.endDate && isAfterDay(newStartDate, range.endDate)) return; - newEndDate = range.endDate; - shouldCloseCalendar = false; - shouldOpenNextCalendar = true; - setErrors({ - ...errors, - startDate: "", - }); - } else if ( - isEndDateFocused && - (isUseKeyPress || isSameDay(newEndDate, newStartDate)) - ) { - if (range.startDate && isBeforeDay(newEndDate, range.startDate)) return; - newStartDate = range.startDate; - setErrors({ - ...errors, - endDate: "", - }); - } else { - setErrors({ - startDate: "", - endDate: "", - }); - } - - // Emit the payload - - setRangeString({ - startDateString: newStartDate - ? moment(newStartDate).format("MMM D, YYYY") - : "", - endDateString: newEndDate ? moment(newEndDate).format("MMM D, YYYY") : "", - }); - - onChange({ - startDate: newStartDate, - endDate: newEndDate ? moment(newEndDate).endOf("day").toDate() : null, - }); - - if (shouldOpenNextCalendar) { - setFocusedRange([0, 1]); - } - if (shouldCloseCalendar) { - setIsComponentVisible(false); - } - }; - - /** - * Event handler on preview change - * @param {Date} date current date which user hover - */ - const onPreviewChange = (date) => { - if (!(date instanceof Date)) { - setPreview(null); - - // --- - // workaround for fixing issue 132: - // - set the active range's background to transparent color - // to prevent the calendar auto focusing on the day of today by default when no - // start date nor end date are set. - // - does not set focus on the selection range when mouse leaves. - // --- - - // setActiveDate(null); - // if (range.startDate || range.endDate) { - // setFocusedRange([0, focusedRange[1]]); - // } - return; - } - - if (isStartDateFocused && date) { - setPreview({ - startDate: date, - endDate: range.endDate || date, - }); - } else if (isEndDateFocused && date) { - setPreview({ - startDate: range.startDate || date, - endDate: date, - }); - } - - setActiveDate(date); - setFocusedRange([1, focusedRange[1]]); - }; - - /** - * Event handler for user keypress - * @param {Event} e Keyboard event - */ - const handleKeyDown = (e) => { - let currentActiveDate = activeDate; - if (!currentActiveDate) { - currentActiveDate = moment().startOf("month").toDate(); - - if (isStartDateFocused && range.startDate) { - currentActiveDate = range.startDate; - } else if (isEndDateFocused && (range.startDate || range.endDate)) { - currentActiveDate = range.endDate || range.startDate; - } - } - - switch (e.key) { - case "Down": - case "ArrowDown": - currentActiveDate = moment(currentActiveDate).add(7, "days").toDate(); - onPreviewChange(currentActiveDate); - break; - case "Up": - case "ArrowUp": - currentActiveDate = moment(currentActiveDate) - .subtract(7, "days") - .toDate(); - onPreviewChange(currentActiveDate); - break; - case "Left": - case "ArrowLeft": - currentActiveDate = moment(currentActiveDate) - .subtract(1, "days") - .toDate(); - onPreviewChange(currentActiveDate); - break; - case "Right": - case "ArrowRight": - currentActiveDate = moment(currentActiveDate).add(1, "days").toDate(); - onPreviewChange(currentActiveDate); - break; - case "Enter": - if (activeDate) { - onDateRangePickerChange({ - startDate: isStartDateFocused ? activeDate : range.startDate, - endDate: isEndDateFocused ? activeDate : range.endDate, - }); - } - break; - case "Esc": - case "Escape": - setIsComponentVisible(false); - break; - default: - return; // Quit when this doesn't handle the key event. - } - - e.preventDefault(); - }; - - /** - * User Effect for listening to keypress event - */ - useEffect(() => { - if (isComponentVisible) { - document.addEventListener("keydown", handleKeyDown, true); - } else { - document.removeEventListener("keydown", handleKeyDown, true); - } - - return () => { - document.removeEventListener("keydown", handleKeyDown, true); - }; - }); - - /** - * Focus the calendar to the given date, - * so for example, if the user click menu for end date it will open the calendar - * and focus it to current end date - */ - const getShownDate = () => { - if (activeDate) { - return activeDate; - } - - if (isStartDateFocused) { - if (preview) return preview.startDate; - return range.startDate || moment().toDate(); - } - if (preview) return preview.endDate; - return range.endDate || moment().toDate(); - }; - - /** - * Disable the days that cannot be selected - */ - const disabledDay = (date) => { - if (isStartDateFocused) { - return range.endDate ? moment(date).isAfter(range.endDate, "day") : false; - } - return range.startDate - ? moment(date).isBefore(range.startDate, "day") - : false; - }; - - /** - * Get Date Ranges - */ - const getRanges = () => { - if (activeDate) { - return [ - { - ...range, - key: "selection", - color: "#0AB88A", - }, - { - startDate: activeDate, - endDate: activeDate, - key: "active", - color: preview ? "#D8FDD8" : "#D8FDD800", - }, - ]; - } - return [ - { - ...range, - key: "selection", - color: "#0AB88A", - }, - ]; - }; - - /** - * Check whether the preview invalid - */ - const isInvalidPreview = () => { - if (!preview) return false; - if (isStartDateFocused) { - return isAfterDay(preview.startDate, range.endDate); - } - return isBeforeDay(preview.endDate, range.startDate); - }; - - const className = `${(focusedRange[1] === 1 && styles.endDate) || ""} ${ - (range.startDate && range.endDate && styles.isRange) || "" - } ${(isInvalidPreview() && styles.isInvalidPreview) || ""} ${ - ((errors.startDate || errors.endDate) && styles.isErrorInput) || "" - }`; - - return ( -
-
- setFocusedRange([0, 0])} - isEndDateActive={focusedRange[1] === 1 && isComponentVisible} - endDateString={rangeString.endDateString} - onEndDateChange={onEndDateChange} - onEndDateFocus={() => setFocusedRange([0, 1])} - error={errors.startDate || errors.endDate} - onClickCalendarIcon={(event) => { - event === "start" ? onIconClickStartDate() : onIconClickEndDate(); - }} - onStartEndDateChange={onStartEndDateChange} - placeholder={placeholder} - enterToSubmit={enterToSubmit} - /> -
-
- {isComponentVisible && ( -
- { - if (!preview) { - onReset(item.selection || item.active); - } else { - onDateRangePickerChange(item.selection || item.active); - } - }} - dateDisplayFormat="MM/dd/yyyy" - showDateDisplay={false} - staticRanges={createStaticRanges()} - inputRanges={[]} - moveRangeOnFirstSelection={false} - initialFocusedRange={[0, 1]} - showMonthArrow={false} - ranges={getRanges()} - disabledDay={disabledDay} - shownDate={getShownDate()} - preview={preview} - onPreviewChange={onPreviewChange} - /> -
- - -
-
- )} -
-
- ); -} - -// It use https://www.npmjs.com/package/react-date-range internally -// Check the docs for further options - -DateRangePicker.propTypes = { - id: PropTypes.string, - range: PropTypes.object.isRequired, - onChange: PropTypes.func.isRequired, - placeholder: PropTypes.string, -}; - -DateRangePicker.defaultProps = { - id: "input-date-range-calendar-icon", - placeholder: "Date range", -}; - -export default DateRangePicker; diff --git a/src/apps/earn/src/components/DateRangePicker/style.scss b/src/apps/earn/src/components/DateRangePicker/style.scss deleted file mode 100644 index b00f99541..000000000 --- a/src/apps/earn/src/components/DateRangePicker/style.scss +++ /dev/null @@ -1,463 +0,0 @@ -@import "@earn/styles/variables"; -@import "@earn/styles/mixins"; - -$green: #D8FDD8; -$darkGreen: #0AB88A;; - -@mixin phone { - @media (max-width: #{$screen-sm - 1px}) { - @content; - } -} - -@mixin tablet { - @media (min-width: #{$screen-sm}) and (max-width: #{$screen-lg - 1px}) { - @content; - } -} - -.isErrorInput { - :global .rdrDateRangePickerWrapper { - margin-top: -20px !important; - } -} - -.isRange { - :global { - .rdrDay { - .rdrInRange { - background: $green !important; - } - - .rdrStartEdge, - .rdrEndEdge { - background: $green !important; - } - } - } -} - -.isInvalidPreview { - :global { - .rdrDayInPreview, - .rdrDayStartPreview, - .rdrDayEndPreview, - .rdrStartEdge.rdrEndEdge { - border: none !important; - } - } -} - -.dateRangePicker { - display: block; - position: relative; - color: $tc-black; - - :global { - @include phone { - .rdrDateRangePickerWrapper { - position: relative !important; - width: 100% !important; - flex-direction: column-reverse; - align-items: center; - justify-content: flex-end; - padding: 0 20px; - border-radius: 0 !important; - - .rdrDefinedRangesWrapper { - .rdrStaticRanges { - display: inline-flex; - flex-direction: row; - justify-content: space-around; - flex-wrap: wrap; - margin-top: 10px !important; - width: calc(100% - 40px); - - .rdrStaticRange { - width: 50%; - } - - .rdrStaticRangeLabel { - font-size: 14px; - } - - > button:hover .rdrStaticRangeLabel { - background-color: $green; - } - } - } - - .rdrDateRangeWrapper { - width: 100%; - - .rdrMonthAndYearWrapper { - padding-top: 0; - - .rdrMonthAndYearPickers select { - font-size: 16px; - } - } - - .rdrMonth { - width: 100%; - } - - .rdrDayNumber { - font-size: 15px; - } - - .rdrDayToday .rdrDayNumber span:after { - bottom: -4px; - left: calc(50% + 2px); - } - - .rdrMonths { - .rdrWeekDay { - font-size: 15px; - margin-bottom: 10px; - } - - .rdrDay { - .rdrDayStartPreview { - left: 17%; - } - - .rdrDayEndPreview { - right: 17%; - } - } - } - } - } - } - - .rdrDateRangePickerWrapper { - z-index: 15; - position: relative; - // background: $tc-white; - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; - overflow: hidden; - width: 455px; - - .rdrDefinedRangesWrapper { - width: 100%; - border: none; - - .rdrStaticRanges { - margin-top: 60px; - - .rdrStaticRange { - border: none; - } - - button { - color: $tc-gray-80; - - @include roboto-regular; - } - - button:hover .rdrStaticRangeLabel { - background-color: $green; - } - } - - .rdrInputRanges { - display: none; - } - } - } - - .rdrMonthAndYearPickers select { - background: url("data:image/svg+xml;utf8,") no-repeat right 8px center; - - option { - background: $white; - } - - &:hover { - background-color: transparent; - } - } - - .rdrMonths { - border-top: 1px solid $tc-gray-20; - border-bottom: 1px solid $tc-gray-20; - - .rdrWeekDay { - font-weight: bold; - color: #484848; - } - - .rdrDayDisabled { - background: transparent; - - .rdrDayInPreview, - .rdrDayStartPreview, - .rdrDayEndPreview, - .rdrStartEdge.rdrEndEdge { - filter: none !important; - -webkit-filter: none !important; - } - } - - .rdrDayPassive { - .rdrInRange, - .rdrStartEdge, - .rdrEndEdge, - .rdrSelected, - .rdrDayStartPreview, - .rdrDayInPreview, - .rdrDayEndPreview { - display: block; - } - - .rdrInRange ~ .rdrDayNumber span { - opacity: 0.5; - } - } - - .rdrDayEndOfMonth .rdrInRange, - .rdrDayEndOfMonth .rdrStartEdge, - .rdrDayEndOfWeek .rdrInRange, - .rdrDayEndOfWeek .rdrStartEdge { - right: 0; - } - - .rdrDayStartOfMonth .rdrInRange, - .rdrDayStartOfMonth .rdrEndEdge, - .rdrDayStartOfWeek .rdrInRange, - .rdrDayStartOfWeek .rdrEndEdge { - left: 0; - } - - .rdrDayStartOfWeek { - .rdrDayInPreview { - left: 0; - border-radius: 0 !important; - border-left: none; - } - } - - .rdrDayEndOfWeek { - .rdrDayInPreview { - right: 0; - border-radius: 0 !important; - border-right: none; - } - } - - .rdrDayStartOfMonth, - .rdrDayEndOfMonth { - .rdrDayInPreview { - border-radius: 0; - border-left: 0; - border-right: 0; - } - } - - .rdrDay { - margin-bottom: 6px; - - .rdrInRange { - color: transparent; - background: transparent; - - & ~ .rdrDayNumber span { - color: $tc-black; - } - } - - .rdrDayStartPreview { - border-radius: 18px 0 0 18px; - height: 36px; - left: 4px; - border-right: none; - } - - .rdrDayEndPreview { - border-radius: 0 18px 18px 0; - height: 36px; - right: 4px; - border-left: none; - } - - .rdrDayStartPreview.rdrDayEndPreview, - .rdrDayHovered { - border-radius: 50%; - width: 36px; - height: 36px; - left: 4px; - border: 1px solid $green; - } - - .rdrSelected, - .rdrInRange, - .rdrStartEdge, - .rdrEndEdge { - top: 0; - bottom: 0; - border-radius: 0; - } - - .rdrDayInPreview, - .rdrDayStartPreview, - .rdrDayEndPreview { - border-color: $green; - top: 0; - bottom: 0; - } - - .rdrDayStartPreview, - .rdrDayEndPreview { - & ~ .rdrDayNumber span { - color: $tc-black; - } - } - - .rdrStartEdge { - background: transparent; - left: 50%; - - &::after { - content: ""; - position: absolute; - top: 0; - left: -18px; - border-radius: 50%; - width: 36px; - height: 36px; - background: currentColor; - z-index: 0; - } - } - - .rdrEndEdge { - background: transparent; - right: 50%; - - &::after { - content: ""; - position: absolute; - top: 0; - right: -18.2px; - border-radius: 50%; - width: 36px; - height: 36px; - background: currentColor; - z-index: 0; - } - } - - .rdrStartEdge.rdrEndEdge ~ .rdrDayNumber span { - color: $tc-black; - } - - .rdrDayNumber { - top: 0; - bottom: 0; - } - } - - .rdrDayStartOfWeek, - .rdrDayEndOfWeek { - border-radius: 0; - } - - .rdrDayToday .rdrDayNumber span:after { - bottom: -4px; - left: calc(50% + 2px); - background: $darkGreen !important; - } - } - } -} - -.dateInputWrapper { - position: relative; - text-align: left; -} - -.calendar-container { - @include roboto-regular; - - position: absolute; - top: calc(100% + 8px); -} - -.calendar-inner-container { - position: absolute; - padding: 0 18px 0 0; - text-align: right; - border: 1px solid $tc-gray-30; - border-radius: 4px; - background: $tc-white; - z-index: 10; - - @include phone { - width: 100%; - position: fixed; - top: 0; - left: 0; - right: 20px; - bottom: 0; - z-index: 15; - padding: 187px 0 0; - border: 0; - border-radius: 0; - background: rgba(#2A2A2A, 0.6); - - @include down(320px) { - padding: 40px 0 0; - } - - .calendar-footer { - margin: 0 20px; - padding: 20px 0; - } - } - - .calendar-footer { - background: $tc-white; - } - - .calendar-button { - @include roboto-bold; - - width: 71px; - height: 24px; - line-height: 22px; - margin: 9px 4px 16px; - padding: 0; - font-size: 10.5px; - text-align: center; - background: transparent; - border: 1px solid #ccc; - border-radius: 2px; - - @include phone { - width: 79px; - height: 26px; - line-height: 27px; - font-size: 12px; - margin: 0 12px 0; - } - } -} - -@include tablet { - .calendar-container, - .calendar-inner-container { - right: 0; - } - - :global { - .rdrDateRangePickerWrapper { - .calendar-container, - .calendar-inner-container { - right: 62px; - left: auto; - } - } - } -} diff --git a/src/apps/earn/src/components/Dropdown/index.jsx b/src/apps/earn/src/components/Dropdown/index.jsx deleted file mode 100644 index f4b9d2d6b..000000000 --- a/src/apps/earn/src/components/Dropdown/index.jsx +++ /dev/null @@ -1,199 +0,0 @@ -/** - * Dropdown component. - */ -import React, { useState, useRef, useEffect } from "react"; -import PT from "prop-types"; -import _ from "lodash"; -import ReactSelect, { components } from "react-select"; - -import config from "../../config"; - -import styles from "./styles.scss"; -import { styled as styledCss } from "@earn/utils"; -const styled = styledCss(styles) - -const Menu = (props) => { - return ( - - {props.children} - - ); -}; -const MenuList = (props) => { - return ( - - {props.children} - - ); -}; - -const CustomOption = (props) => { - return ( - - {props.children} - - ); -}; - -const ValueContainer = ({ children, ...props }) => ( - - {children} - -); - -const Input = (props) => { - return ( - - ); -}; - -const SingleValue = ({ children, ...props }) => ( - - {children} - -); - -const ControlComponent = (props) => ( - -); -const IndicatorSeparator = () => { - return null; -}; - -function Dropdown({ - className, - options, - label, - required, - placeholder, - onChange, - errorMsg, - searchable, - size, -}) { - const [internalOptions, setInternalOptions] = useState(options); - const selectedOption = _.find(internalOptions, { selected: true }); - const [focused, setFocused] = useState(false); - const delayedOnChange = useRef( - _.debounce((q, cb) => cb(q), config.GUIKIT.DEBOUNCE_ON_CHANGE_TIME) // eslint-disable-line no-undef - ).current; - const sizeStyle = size === "lg" ? "lgSize" : "xsSize"; - useEffect(() => { - setInternalOptions(options); - }, [options]); - return ( -
setFocused(true)} - onBlurCapture={() => setFocused(false)} - className={ - styled( - className, - 'dropdownContainer', - 'container', - sizeStyle, - selectedOption && "haveValue", - errorMsg && "haveError", - focused && "isFocused" - ) - } - > -
- ({ - value: o.label, - label: o.label, - }))} - value={selectedOption} - components={{ - Menu, - MenuList, - Option: CustomOption, - ValueContainer, - SingleValue, - IndicatorSeparator, - Input, - Control: ControlComponent, - }} - onChange={(value) => { - if (value) { - const newOptions = internalOptions.map((o) => ({ - selected: value.label === o.label, - label: o.label, - value: o.value, - })); - setInternalOptions(newOptions); - delayedOnChange(_.cloneDeep(newOptions), onChange); - } - }} - placeholder={`${placeholder}${placeholder && required ? " *" : ""}`} - clearable={false} - /> -
- {label ? ( - - {label} - {required ?  * : null} - - ) : null} - {errorMsg ? ( - - {errorMsg} - - ) : null} -
- ); -} - -Dropdown.defaultProps = { - placeholder: '', - label: '', - required: false, - onChange: () => {}, - errorMsg: '', - searchable: true, - size: 'lg', -}; - -Dropdown.propTypes = { - options: PT.arrayOf( - PT.shape({ - label: PT.string, - selected: PT.bool, - }) - ).isRequired, - placeholder: PT.string, - label: PT.string, - required: PT.bool, - onChange: PT.func, - errorMsg: PT.string, - size: PT.oneOf(["xs", "lg"]), -}; - -export default Dropdown; diff --git a/src/apps/earn/src/components/Dropdown/styles.scss b/src/apps/earn/src/components/Dropdown/styles.scss deleted file mode 100644 index c844913b8..000000000 --- a/src/apps/earn/src/components/Dropdown/styles.scss +++ /dev/null @@ -1,260 +0,0 @@ -@import "@earn/styles/variables"; -@import "@earn/styles/GUIKit/default"; - -.label { - @include textInputLabel; -} - -.relative { - position: relative; -} - -.errorMessage { - @include errorMessage; -} - -.iconDropdown { - position: absolute; - top: 50%; - right: 16px; - pointer-events: none; - margin-top: -4px; -} - -.container { - position: relative; - display: flex; - flex-direction: column; - padding-top: 12px; - - &.haveValue .label, - &.haveError .label, - &.isFocused .label { - display: flex; - } - - &.isFocused { - .label { - color: $gui-kit-level-2; - } - - .iconDropdown { - transform: scale(1, -1); - } - } - - &.haveError .label, - &.haveError.isFocused .label { - color: $gui-kit-level-5; - } - - :global { - // @import '~react-select/dist/react-select'; - - width: 100%; - - .Select-control { - margin: 0; - padding: 0; - border: none; - border-radius: 6px !important; - height: 52px; - outline: none !important; - box-shadow: inset 0 0 0 1px $gui-kit-gray-30 !important; - } - - .Select-input { - padding: 0; - margin: 0; - display: flex; - - input { - font-size: 16px; - padding: 0; - height: 22px; - line-height: 22px; - - &:focus { - border: none; - box-shadow: none; - } - } - } - - .Select-value { - .Select-value-label { - height: 22px; - line-height: 22px; - font-size: 16px; - color: $gui-kit-gray-90 !important; - position: absolute; - right: 0; - top: 0; - bottom: 0; - left: 15px; - height: 100%; - display: flex; - align-items: center; - margin: 0; - } - } - - .Select-placeholder, - .Select-value, - .Select-input { - padding: 0 15px !important; - height: 100% !important; - display: flex !important; - align-items: center !important; - } - - .Select-placeholder { - color: $gui-kit-gray-30; - opacity: 1; - text-transform: none; - font-size: 16px; - } - - .Select-multi-value-wrapper { - width: 100% !important; - height: 100% !important; - } - - .Select-arrow-zone { - padding-right: 15px !important; - - .Select-arrow { - background-image: none; - border: none; - width: 15px; - height: 9px; - background-size: 15px 9px; - top: 0 !important; - border-width: 0 !important; - opacity: 0; - pointer-events: none; - } - } - - .Select { - &.is-open { - .Select-arrow-zone { - .Select-arrow { - transform: scale(1, -1); - } - } - } - - &:not(.is-searchable) { - .Select-input { - display: none !important; - } - } - } - - .Select-menu-outer { - top: calc(100% + 2px) !important; - border: 1px solid $gui-kit-gray-30 !important; - border-radius: 0 !important; - max-height: 269px; - z-index: 7; - margin: 0; - - .Select-menu { - padding: 9px 0; - max-height: 269px; - - .Select-option { - padding: 0 15px !important; - font-size: 16px !important; - line-height: 30px !important; - color: $gui-kit-gray-90 !important; - background-color: transparent !important; - text-decoration: none !important; - - &.is-selected { - font-weight: bold !important; - } - - &:hover { - background-color: #229173 !important; - color: $tc-white !important; - } - } - } - } - } - - &.haveError { - :global { - .Select-control { - box-shadow: inset 0 0 0 2px $gui-kit-level-5 !important; - } - } - } - - // lg size - &.lgSize { - :global { - .Select-control { - height: 52px; - } - - .Select-input { - input { - height: 52px; - } - } - } - } - - // xs size - &.xsSize { - padding-top: 0; - - &.haveValue .label, - &.isFocused .label { - margin-top: -12px; - } - - :global { - .Select-control { - height: 40px; - } - - .Select-input { - input { - font-size: 14px; - height: 40px; - } - } - - .Select-value { - .Select-value-label { - font-size: 14px; - color: $gui-kit-gray-90 !important; - } - } - - .Select-placeholder { - font-size: 14px; - } - - .Select-menu-outer { - * { - font-size: 14px !important; - } - - .Select-menu { - .Select-option { - font-size: 14px !important; - } - } - } - } - - .errorMessage { - @include errorMessageXs; - } - } -} diff --git a/src/apps/earn/src/components/DropdownTerms/index.jsx b/src/apps/earn/src/components/DropdownTerms/index.jsx deleted file mode 100644 index d47070913..000000000 --- a/src/apps/earn/src/components/DropdownTerms/index.jsx +++ /dev/null @@ -1,214 +0,0 @@ -/** - * Dropdown terms component. - */ -import React, { useState, useRef, useEffect } from "react"; -import PT from "prop-types"; -import _ from "lodash"; -import Select from "react-select"; - -import config from "../../config"; -import iconDown from "../../assets/icons/dropdown-arrow.png"; - -import styles from "./styles.scss"; -import { styled as styledCss } from "@earn/utils"; -const styled = styledCss(styles) - -function DropdownTerms({ - terms, - placeholder, - label, - required, - onChange, - errorMsg, - addNewOptionPlaceholder, - size, -}) { - const [internalTerms, setInternalTerms] = useState(terms); - const selectedOption = _.filter(internalTerms, { selected: true }).map( - (o) => ({ - value: o.label, - label: o.label, - }) - ); - const [focused, setFocused] = useState(false); - const delayedOnChange = useRef( - _.debounce((q, cb) => cb(q), config.GUIKIT.DEBOUNCE_ON_CHANGE_TIME) // eslint-disable-line no-undef - ).current; - - const containerRef = useRef(null); - let inputFieldRef = useRef(null); - const latestPropsRef = useRef(null); - latestPropsRef.current = { addNewOptionPlaceholder }; - - useEffect(() => { - const selectInput = containerRef.current.getElementsByClassName( - "Select-input" - ); - if (selectInput && selectInput.length) { - inputFieldRef.current = selectInput[0].getElementsByTagName("input"); - inputFieldRef.current[0].placeholder = focused - ? latestPropsRef.current.addNewOptionPlaceholder - : ""; - inputFieldRef.current[0].style.border = "none"; - inputFieldRef.current[0].style.boxShadow = "none"; - selectInput[0].style.borderTop = "none"; - } - }, [focused, selectedOption]); - useEffect(() => { - setInternalTerms(terms); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [terms && terms.length]); - - const CustomReactSelectRow = React.forwardRef( - ({ className, option, children, onSelect }, ref) => - children ? ( - { - event.preventDefault(); - event.stopPropagation(); - onSelect(option, event); - }} - title={option.title} - tabIndex={-1} - > - {children} - - ) : null - ); - - CustomReactSelectRow.defaultProps = { - children: null, - className: "", - onSelect: () => {}, - }; - - CustomReactSelectRow.propTypes = { - children: PT.node, - className: PT.string, - onSelect: PT.func, - option: PT.object.isRequired, - }; - - return ( -
-
- this.setState({ editURL: this.inputURL.value })} - ref={(node) => { - this.inputURL = node; - }} - className={styled("url")} - tabIndex="0" - value={st.editURL} - /> -
-
- Size%: - - this.setState({ size: _.clamp(this.inputSize.value, 0, 100) }) - } - ref={(node) => { - this.inputSize = node; - }} - className={styled("size")} - tabIndex="-1" - value={st.size} - /> -
-
-
- - -
- {st.previewURL ? ( -
-
- {st.description} -
- ) : null} - - - ); - } -} - -EditModal.defaultProps = { - description: "", - onSave: _.noop, - onCancel: _.noop, - size: 100, - src: "http://", -}; - -EditModal.propTypes = { - description: PT.string, - onSave: PT.func, - onCancel: PT.func, - size: PT.number, - src: PT.string, -}; diff --git a/src/apps/earn/src/components/Editor/Image/EditModal/style.scss b/src/apps/earn/src/components/Editor/Image/EditModal/style.scss deleted file mode 100644 index c3a1aa5ac..000000000 --- a/src/apps/earn/src/components/Editor/Image/EditModal/style.scss +++ /dev/null @@ -1,65 +0,0 @@ -@import "@earn/styles/mixins"; - -.buttons-container { - display: inline-block; - margin-left: 31px; - margin-top: $base-unit * 2; -} - -// Competing against some globals -.container { - @include tc-body-md; - - input { - display: inline-block; - height: $base-unit * 6; - margin: 0; - padding: 0; - margin-left: $base-unit * 1; - vertical-align: middle; - - &.size { - width: 50px; - } - - &.url { - width: 500px; - } - } - - z-index: 1000; -} - -.modalContainer { - top: 30%; - left: 50%; - transform: translate(-50%); - height: auto; - width: 720px; -} - -.modalOverlay { - pointer-events: bounding-box; -} - -.fields-container { - display: flex; - flex-direction: row; - justify-content: space-between; -} - -.field { - display: inline-block; -} - -.preview { - display: block; -} - -.size { - width: 50px; -} - -.url { - width: 100%; -} diff --git a/src/apps/earn/src/components/Editor/Image/Popup/index.jsx b/src/apps/earn/src/components/Editor/Image/Popup/index.jsx deleted file mode 100644 index e01b842d3..000000000 --- a/src/apps/earn/src/components/Editor/Image/Popup/index.jsx +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Popup Component for Link Decorators - */ -import _ from "lodash"; -import PT from "prop-types"; -import React from "react"; - - -import EditModal from "../EditModal"; - -import styles from "./style.scss"; -import { styled as styledCss } from "@earn/utils"; -import { Button } from "~/libs/ui"; -const styled = styledCss(styles) - -export default class Popup extends React.Component { - constructor(props) { - super(props); - this.state = { - editing: props.triggerModal, - }; - } - - render() { - const { onEdit, size, src } = this.props; - const { editing } = this.state; - const renderDisplay = () => ( -
- -
- ); - - const renderEdit = () => ( -
- this.setState({ editing: false })} - onSave={(newSrc, newSize) => { - this.setState({ editing: false }); - onEdit(newSrc, newSize); - }} - /> -
- ); - - return
{editing ? renderEdit() : renderDisplay()}
; - } -} - -Popup.defaultProps = { - size: 100, - src: "http://", - onEdit: _.noop, - triggerModal: false, -}; - -Popup.propTypes = { - onEdit: PT.func, - size: PT.number, - src: PT.string, - triggerModal: PT.bool, -}; diff --git a/src/apps/earn/src/components/Editor/Image/Popup/style.scss b/src/apps/earn/src/components/Editor/Image/Popup/style.scss deleted file mode 100644 index 7fb680869..000000000 --- a/src/apps/earn/src/components/Editor/Image/Popup/style.scss +++ /dev/null @@ -1,6 +0,0 @@ -@import "@earn/styles/mixins"; - -.edit { - height: $base-unit * 4; - width: $base-unit * 4; -} diff --git a/src/apps/earn/src/components/Editor/Image/index.jsx b/src/apps/earn/src/components/Editor/Image/index.jsx deleted file mode 100644 index 5fefc0d78..000000000 --- a/src/apps/earn/src/components/Editor/Image/index.jsx +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Draft Decorator Component - * Renders images within the draft component including a popup edit button and modal - */ -import PT from "prop-types"; - -import { Tooltip } from "~/libs/ui"; - -import Popup from "./Popup"; - -const Image = ({ children, contentState, entityKey, updateEntityData }) => { - const { description, size, src, triggerModal } = contentState - .getEntity(entityKey) - .getData(); - - const popup = ( - { - updateEntityData(entityKey, { src: newSrc, size: newSize }); - }} - size={size} - src={src} - triggerModal={triggerModal} - /> - ); - - return ( - - - {description} - - {children} - - ); -}; - -Image.propTypes = { - contentState: PT.shape().isRequired, - children: PT.node.isRequired, - entityKey: PT.string.isRequired, - updateEntityData: PT.func.isRequired, -}; - -export default Image; diff --git a/src/apps/earn/src/components/Editor/Link/Popup/index.jsx b/src/apps/earn/src/components/Editor/Link/Popup/index.jsx deleted file mode 100644 index 6f6f77a50..000000000 --- a/src/apps/earn/src/components/Editor/Link/Popup/index.jsx +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Popup Component for Link Decorators - */ -import _ from "lodash"; -import PT from "prop-types"; -import React from "react"; - -import styles from "./style.scss"; -import { styled as styledCss } from "@earn/utils"; -import { Button } from "~/libs/ui"; -const styled = styledCss(styles) - -export default class Popup extends React.Component { - constructor(props) { - super(props); - this.state = { - href: props.href, - editing: false, - }; - } - - handleDone() { - const { onEdit } = this.props; - const { href } = this.state; - onEdit(href); - this.setState({ editing: false }); - } - - render() { - const { editing, href } = this.state; - const renderDisplay = () => ( -
- - {href} - - -
- ); - - const renderEdit = () => ( -
- this.setState({ href: this.node.value })} - onKeyUp={(e) => { - if (e.keyCode === 13) { - this.handleDone(); - } - }} - ref={(node) => { - this.node = node; - }} - /> - -
- ); - - return ( -
- {editing ? renderEdit() : renderDisplay()} -
- ); - } -} - -Popup.defaultProps = { - href: "", - onEdit: _.noop, -}; - -Popup.propTypes = { - href: PT.string, - onEdit: PT.func, -}; diff --git a/src/apps/earn/src/components/Editor/Link/Popup/style.scss b/src/apps/earn/src/components/Editor/Link/Popup/style.scss deleted file mode 100644 index 8fb4ddd90..000000000 --- a/src/apps/earn/src/components/Editor/Link/Popup/style.scss +++ /dev/null @@ -1,26 +0,0 @@ -@import "@earn/styles/mixins"; - -.edit { - height: $base-unit * 4; - width: $base-unit * 4; -} - -// Competing against some globals -.container { - a { - display: inline-block; - min-width: $base-unit * 24; - padding-left: $base-unit * 4; - vertical-align: middle; - } - - input[type="text"] { - display: inline-block; - height: $base-unit * 6; - margin: 0; - padding: 0; - margin-left: $base-unit * 1; - width: $base-unit * 48; - vertical-align: middle; - } -} diff --git a/src/apps/earn/src/components/Editor/Link/index.jsx b/src/apps/earn/src/components/Editor/Link/index.jsx deleted file mode 100644 index d36a082cf..000000000 --- a/src/apps/earn/src/components/Editor/Link/index.jsx +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Draft Decorator Component - * Renders links within the draft component including a popup Tooltip to edit - */ -import PT from "prop-types"; - -import { Tooltip } from "~/libs/ui"; - -import Popup from "./Popup"; - -const Link = ({ children, contentState, entityKey, updateEntityData }) => { - const { href, triggerPopup } = contentState.getEntity(entityKey).getData(); - - const popup = ( - updateEntityData(entityKey, { href: updated })} - /> - ); - - return ( - - - - {children} - - - - ); -}; - -Link.defaultProps = { - children: null, -}; - -Link.propTypes = { - children: PT.node, - contentState: PT.shape().isRequired, - entityKey: PT.string.isRequired, - updateEntityData: PT.func.isRequired, -}; - -export default Link; diff --git a/src/apps/earn/src/components/Editor/MarkdownEditor/BlockWrapper.jsx b/src/apps/earn/src/components/Editor/MarkdownEditor/BlockWrapper.jsx deleted file mode 100644 index 257fa80c6..000000000 --- a/src/apps/earn/src/components/Editor/MarkdownEditor/BlockWrapper.jsx +++ /dev/null @@ -1,37 +0,0 @@ -import PT from "prop-types"; -import React from "react"; - -import { EditorBlock } from "draft-js"; - -export default function BlockWrapper(props) { - const { blockProps } = props; - const { type } = blockProps; - const types = type.split("-"); - const thisType = (types[0] || "unstyled").split(":"); - - const leadingLi = - thisType[0] === "li" && !types.slice(1).some((x) => x === "li"); - - if (thisType[0] !== "unstyled") { - const child = BlockWrapper({ - ...props, - blockProps: { - type: types.slice(1).join("-"), - }, - }); - let className = thisType[0]; - if (thisType[1]) className += ` md-syntax-level-${thisType[1]}`; - if (leadingLi) className += " leadingLi"; - if (thisType[0] === "hr") { - return
{child}
; - } - return React.createElement(thisType[0], { className }, child); - } - return ; -} - -BlockWrapper.propTypes = { - blockProps: PT.shape({ - type: PT.string.isRequired, - }).isRequired, -}; diff --git a/src/apps/earn/src/components/Editor/MarkdownEditor/index.jsx b/src/apps/earn/src/components/Editor/MarkdownEditor/index.jsx deleted file mode 100644 index 015d46a62..000000000 --- a/src/apps/earn/src/components/Editor/MarkdownEditor/index.jsx +++ /dev/null @@ -1,127 +0,0 @@ -/** - * Markdown editor. - */ - -import PT from "prop-types"; -import React from "react"; -import Turndown from "turndown"; - -import { ContentState, convertFromHTML, EditorState } from "draft-js"; - -import BlockWrapper from "./BlockWrapper"; -import Connector from "../Connector"; -import GenericEditor from "../GenericEditor"; -import MdUtils from "./md-utils"; - -import ImageEditor from "../Image/EditModal"; - -import styles from "./style.scss"; -import { styled as styledCss } from "../../../utils"; -const styled = styledCss(styles) - -const GUI_STATES = { - IMAGE_EDIT_MODAL: "IMAGE_EDIT_MODAL", - REGULAR: "REGULAR", -}; - -export default class MarkdownEditor extends React.Component { - constructor(props) { - super(props); - this.mdUtils = new MdUtils(); - this.state = { - editor: EditorState.createEmpty(this.mdUtils), - gui: GUI_STATES.REGULAR, - }; - this.turndown = new Turndown(); - } - - componentDidMount() { - const { initialContent } = this.props; - if (initialContent) { - let state = initialContent.replace(/\n/g, "
"); - state = convertFromHTML(state); - state = ContentState.createFromBlockArray( - state.contentBlocks, - state.entityMap - ); - state = EditorState.createWithContent(state, this.mdUtils); - this.onChange(state); - } - } - - onChange(newState) { - const { connector } = this.props; - this.mdUtils.parse(newState.getCurrentContent()); - if (connector && connector.previewer) { - connector.previewer.setVisible(true); - connector.previewer.setContent(this.mdUtils.getHtml()); - } - if (this.editor) { - const selfState = this.mdUtils.highlight(newState); - if (selfState !== newState) { - this.setState({ editor: selfState }); - } - } - } - - getHtml() { - return this.mdUtils.getHtml(); - } - - setHtml(html) { - let state = this.turndown.turndown(html); - state = state.replace(/\n/g, "
"); - state = convertFromHTML(state); - state = ContentState.createFromBlockArray( - state.contentBlocks, - state.entityMap - ); - state = EditorState.createWithContent(state, this.mdUtils); - this.onChange(state); - } - - insertImage() { - setImmediate(() => this.setState({ gui: GUI_STATES.IMAGE_EDIT_MODAL })); - } - - render() { - const { connector, id } = this.props; - const st = this.state; - return ( -
- {st.gui === GUI_STATES.IMAGE_EDIT_MODAL ? ( - this.setState({ gui: GUI_STATES.REGULAR })} - /> - ) : null} - ({ - component: BlockWrapper, - editable: true, - props: { type: block.getType() }, - })} - connector={connector} - decorator={this.mdUtils} - editorState={st.editor} - id={id} - onChange={(state) => this.onChange(state)} - ref={(node) => { - this.editor = node; - }} - /> -
- ); - } -} - -MarkdownEditor.defaultProps = { - connector: new Connector(), - id: null, - initialContent: null, -}; - -MarkdownEditor.propTypes = { - connector: PT.shape(), - id: PT.string, - initialContent: PT.string, -}; diff --git a/src/apps/earn/src/components/Editor/MarkdownEditor/inlineWrapperFactory.jsx b/src/apps/earn/src/components/Editor/MarkdownEditor/inlineWrapperFactory.jsx deleted file mode 100644 index fe0684052..000000000 --- a/src/apps/earn/src/components/Editor/MarkdownEditor/inlineWrapperFactory.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import PT from "prop-types"; -import React from "react"; - -function InlineWrapper({ children, hrefs, key }) { - if (!key || key === "text") { - return {children}; - } - if (key === "mdSyntax") { - return {children}; - } - if (key === "inlineCode") { - return {children}; - } - const keys = key.split("-"); - const child = InlineWrapper({ - children, - key: keys.slice(1).join("-"), - }); - - if (keys[0].startsWith("a:")) { - return {children}; - } - - return React.createElement(keys[0], {}, child); -} - -InlineWrapper.propTypes = { - children: PT.node.isRequired, - hrefs: PT.shape.isRequired, - key: PT.string.isRequired, -}; - -export default function inlineWrapperFactory(key, hrefs) { - return ({ children }) => InlineWrapper({ children, hrefs, key }); -} diff --git a/src/apps/earn/src/components/Editor/MarkdownEditor/md-utils.js b/src/apps/earn/src/components/Editor/MarkdownEditor/md-utils.js deleted file mode 100644 index 23689f398..000000000 --- a/src/apps/earn/src/components/Editor/MarkdownEditor/md-utils.js +++ /dev/null @@ -1,456 +0,0 @@ -/** - * Markdown utilities for DraftJS editor. - * - * There are plenty of Markdown-related plugins for DraftJS in Internet, but it - * looks like nobody made it right so far; thus here we go with the correct - * solution. - */ - -import _ from "lodash"; -import Markdown from "markdown-it"; - -import { EditorState, SelectionState, Modifier } from "draft-js"; - -import { List } from "immutable"; - -import shortId from "shortid"; - -import inlineWrapperFactory from "./inlineWrapperFactory"; - -import "./style.scss"; - -/** - * Counts the specified characters in the given string. - * @param {String} string - * @param {String} char - * @return {Number} - */ -function count(string, char) { - let pos = -1; - let res = 0; - for (;;) { - const c = string[(pos += 1)]; - if (c === char) res += 1; - else if (!c) return res; - } -} - -/** - * Finds position of the n-th occurance of the specified character in the given - * string, and returns it. Returns -1, if not found. - * @param {String} string - * @param {String} char - * @param {Number} n - * @return {Number} - */ -function findNth(string, char, n) { - let pos = -1; - let res = n; - for (;;) { - const c = string[(pos += 1)]; - if (c === char) res -= 1; - if (!res) return pos; - if (!c) return -1; - } -} - -/* Internal. */ -function newSelector(key, pos = 0, end, endKey) { - return SelectionState.createEmpty(key).merge({ - anchorOffset: pos, - focusKey: endKey === undefined ? key : endKey, - focusOffset: end === undefined ? pos : end, - }); -} - -/* Internal. */ -function insertChar(content, key, pos, char) { - return Modifier.insertText(content, newSelector(key, pos), char); -} - -/* Internal. */ -function mergeBlockData(content, key, data) { - return Modifier.mergeBlockData(content, newSelector(key), data); -} - -/* Internal. */ -function removeChar(content, key, pos) { - return Modifier.removeRange(content, newSelector(key, pos, pos + 1)); -} - -/* Internal. */ -function removeLastChar(content, key, pos) { - const s = newSelector(key, pos, 0, content.getKeyAfter(key)); - return Modifier.removeRange(content, s); -} - -/* Internal. */ -function splitBlock(content, key, pos) { - return Modifier.splitBlock(content, newSelector(key, pos)); -} - -/* Internal. */ -function setBlockType(content, key, type) { - const block = content.getBlockForKey(key); - if (block.getType() === type) return content; - return Modifier.setBlockType(content, newSelector(key, 0), type); -} - -export default class MdUtils { - /** - * Constructs a new MdUtils instance. - * @param {ContentState} contentState Optional. If provided, constructor will - * automatically call parse(contentState) in the end of initialization. - */ - constructor(contentState) { - this.markdown = new Markdown(); - this.markdown.disable(["table"]); - this.tokens = []; - if (contentState) this.parse(contentState); - } - - /** - * Private. - * - * Merges and/or splits DraftJS blocks to ensure that the current block - * contains exactly the specified number of lines. - * - * @param {Number} numLines - */ - alignLines(numLines) { - for (;;) { - const text = this.content.getBlockForKey(this.key).getText(); - const numLinesInBlock = 1 + count(text, "\n"); - if (numLinesInBlock < numLines) { - const nextKey = this.content.getKeyAfter(this.key); - if (!nextKey) return; - this.content = removeLastChar(this.content, this.key, text.length); - this.content = insertChar(this.content, this.key, text.length, "\n"); - if (this.selection.getAnchorKey() === nextKey) { - this.selection = this.selection.merge({ - anchorKey: this.key, - anchorOffset: this.selection.getAnchorOffset() + text.length + 1, - }); - } - if (this.selection.getFocusKey() === nextKey) { - this.selection = this.selection.merge({ - focusKey: this.key, - focusOffset: this.selection.getFocusOffset() + text.length + 1, - }); - } - } else if (numLinesInBlock > numLines) { - const splitPoint = findNth(text, "\n", numLines); - this.content = removeChar(this.content, this.key, splitPoint); - this.content = splitBlock(this.content, this.key, splitPoint); - if ( - this.selection.getAnchorKey() === this.key && - this.selection.getAnchorOffset() > splitPoint - ) { - this.selection = this.selection.merge({ - anchorKey: this.content.getKeyAfter(this.key), - anchorOffset: this.selection.getAnchorOffset() - splitPoint - 1, - }); - } - if ( - this.selection.getFocusKey() === this.key && - this.selection.getFocusOffset() > splitPoint - ) { - this.selection = this.selection.merge({ - focusKey: this.content.getKeyAfter(this.key), - focusOffset: this.selection.getFocusOffset() - splitPoint - 1, - }); - } - } else return; - } - } - - getDecorations(block) { - _.noop(this); - const res = block.getData().get("decorations") || List(); - return res.setSize(block.getLength()); - } - - getComponentForKey(key) { - _.noop(this); - return inlineWrapperFactory(key, this.hrefs); - } - - getPropsForKey() { - _.noop(this); - return {}; - } - - /** - * Highlights Markdown syntax in the given DraftJS state. - * @param {EditorState} state DraftJS EditorState that holds a plain text with - * a valid Markdown markup, previously loaded into this MdUtils instance via - * parse(..) method. - * @return {EditorState} Resulting state with the proper formatting and - * styling of the markup. - */ - highlight(state) { - this.blockTypes = []; - this.content = state.getCurrentContent(); - this.decorations = {}; - this.decoreLevel = 0; - this.endLines = []; - this.hrefs = {}; - this.key = this.content.getFirstBlock().getKey(); - this.selection = state.getSelection(); - this.styleLine = 0; - this.tokenId = 0; - this.tokens.forEach(() => this.highlightNextToken()); - while (this.key) { - this.content = setBlockType(this.content, this.key, "unstyled"); - this.highlightInline(); - this.key = this.content.getKeyAfter(this.key); - } - const res = EditorState.push(state, this.content, "custom"); - return EditorState.acceptSelection(res, this.selection); - } - - /** - * Private. - * - * Highlights inline Markdown syntax in the current DraftJS block. - */ - highlightInline(subTokens) { - let pos = 0; - const text = this.content.getBlockForKey(this.key).getText(); - const res = new Array(text.length); - res.fill("mdSyntax"); - - if (subTokens) { - const styles = []; - subTokens.forEach((st) => { - switch (st.type) { - case "link_open": { - const id = shortId().replace(/-/g, ":"); - [[, this.hrefs[id]]] = st.attrs; - styles.push(`a:${id}`); - break; - } - - case "em_open": - case "strong_open": - styles.push(st.tag); - break; - - case "s_open": - styles.push("strike"); - break; - - case "em_close": - case "link_close": - case "s_close": - case "strong_close": - styles.pop(); - break; - - case "code_inline": { - if (!st.content.length) break; - let style = styles.join("-"); - if (!style) style = "inlineCode"; - else style = `${style}-inlineCode`; - pos = text.indexOf(st.content, pos); - const end = pos + st.content.length; - while (pos < end) { - res[pos] = style; - pos += 1; - } - break; - } - - case "text": { - if (!st.content.length) break; - pos = text.indexOf(st.content, pos); - const end = pos + st.content.length; - const style = styles.join("-") || "text"; - while (pos < end) { - res[pos] = style; - pos += 1; - } - if (styles.length && _.last(styles).startsWith("a:")) { - pos += 3 + _.last(styles).slice(2).length; - } - break; - } - - default: - } - }); - } - - let i = text.length - 1; - while (i >= 0 && text[i] === " ") { - res[i] = "text"; - i -= 1; - } - while (i >= 0 && res[i] === "mdSyntax") i -= 1; - if (i < 0) res.fill("mdSyntax"); - - const decorations = List(res); - this.content = mergeBlockData(this.content, this.key, { decorations }); - } - - /** - * Private. - * - * Highlights Markdown syntax in the specified number of lines, starting from - * the first non-styled line. - * - * @param {Number} numLines - */ - highlightLines(numLines) { - this.alignLines(numLines); - const type = this.blockTypes.join("-") || "unstyled"; - this.content = setBlockType(this.content, this.key, type); - } - - /** - * Private. - * - * Highlights all Markdown syntax between the last highlighted DraftJS block - * and the current MarkdownIt token. - */ - highlightNextToken() { - const token = this.tokens[this.tokenId]; - - /* If token opens a new range, we: - * - Style any block before this token line; - * - Remember the range of this token, and the line of the first non-styled - * block. */ - if (token.map) { - const linesBefore = token.map[0] - this.styleLine; - if (linesBefore) { - this.highlightLines(linesBefore); - this.highlightInline(); - [this.styleLine] = token.map; - this.key = this.content.getKeyAfter(this.key); - } - } - - switch (token.type) { - case "blockquote_open": - case "bullet_list_open": - this.decoreLevel += 1; - this.blockTypes.push(`${token.tag}:${this.decoreLevel}`); - this.endLines.push(token.map[1]); - break; - - case "ordered_list_open": - this.decoreLevel += 2; - this.blockTypes.push(`${token.tag}:${this.decoreLevel}`); - this.endLines.push(token.map[1]); - break; - - case "heading_open": - case "list_item_open": - case "paragraph_open": - this.blockTypes.push(token.tag); - this.endLines.push(token.map[1]); - break; - - case "blockquote_close": - case "bullet_list_close": - case "heading_close": - case "list_item_close": - case "ordered_list_close": - case "paragraph_close": { - const linesBefore = _.last(this.endLines) - this.styleLine; - if (linesBefore) { - this.highlightLines(linesBefore); - this.highlightInline(); - this.key = this.content.getKeyAfter(this.key); - this.styleLine = _.last(this.endLines); - } - this.blockTypes.pop(); - this.endLines.pop(); - - switch (token.type) { - case "blockquote_close": - case "bullet_list_close": - this.decoreLevel -= 1; - break; - case "ordered_list_close": - this.decoreLevel -= 2; - break; - default: - } - - break; - } - - case "fence": { - this.blockTypes.push(token.tag); - let numLines = token.map[1] - token.map[0]; - const subTokens = [{ type: "text", content: token.content }]; - const isClosed = 1 + count(token.content, "\n") < numLines; - if (!isClosed) { - let i = 1 + this.tokenId; - while (i < this.tokens.length && !this.tokens[i].map) i += 1; - if ( - i === this.tokens.length || - this.tokens[i].map[0] > token.map[1] - ) { - numLines += 1; - } - } - this.highlightLines(numLines); - this.highlightInline(subTokens); - this.key = this.content.getKeyAfter(this.key); - [, this.styleLine] = token.map; - this.blockTypes.pop(); - break; - } - - case "code_block": - case "hr": { - this.blockTypes.push(token.tag); - this.highlightLines(token.map[1] - token.map[0]); - this.highlightInline(token.children); - this.key = this.content.getKeyAfter(this.key); - [, this.styleLine] = token.map; - this.blockTypes.pop(); - break; - } - - case "inline": - this.highlightLines(token.map[1] - token.map[0]); - this.highlightInline(token.children); - this.key = this.content.getKeyAfter(this.key); - [, this.styleLine] = token.map; - break; - - default: - } - - this.tokenId += 1; - } - - /** - * Returns HTML representation of the Markdown markup previously loaded by - * parse(..) method of MdUtils. - * @return {String} - */ - getHtml() { - if (!this.html) { - this.html = this.markdown.renderer.render(this.tokens, this.env); - } - return this.html; - } - - /** - * Parses the given DraftJS state. The state should contain a plain text with - * Markdown markup. After the parse you can call other methods of MdUtils to - * generate corresponding HTML markup, or DraftJS state for rendered Markdown - * representation, or DraftJS decorator for Markdown syntax highlighting in - * the original state. - * @param {ContentState} state - */ - parse(contentState) { - delete this.html; - this.env = {}; - this.tokens = this.markdown.parse(contentState.getPlainText(), this.env); - } -} diff --git a/src/apps/earn/src/components/Editor/MarkdownEditor/style.scss b/src/apps/earn/src/components/Editor/MarkdownEditor/style.scss deleted file mode 100644 index 24c5e4fe3..000000000 --- a/src/apps/earn/src/components/Editor/MarkdownEditor/style.scss +++ /dev/null @@ -1,148 +0,0 @@ -@import "@earn/styles/mixins"; - -/* Styling of Markdown syntax highlighting. */ -.container { - @include tc-body-md; - - overflow: hidden; - - a { - color: $tc-dark-blue-110; - text-decoration: underline; - } - - code { - background: $tc-gray-neutral-light; - border: 1px solid $tc-gray-20; - border-radius: 6px; - display: block; - font-family: "Roboto Mono", monospace; - padding: 15px 20px; - white-space: pre-wrap; - - &:global.inline { - background: $tc-gray-10; - border: none; - border-radius: 0; - display: inline; - padding: 0 5px; - } - } - - em { - font-style: italic; - } - strong { - font-weight: bold; - } - - /* This styling leads to some artefacts :( */ - :global .hr { - width: 100%; - - > div > span > span { - border-top: 1px solid firebrick; - display: inline-block; - height: 0; - line-height: 0; - width: 100%; - } - } - - :global { - li { - display: inline-block; - position: relative; - - &.leadingLi { - margin-top: 10px; - } - - &::before { - border-left: 3px solid $tc-gray-40; - content: ""; - height: 100%; - position: absolute; - } - } - - $offset: -15; - - @for $level from 0 to 10 { - ol.md-syntax-level-#{$level} > li::before { - left: #{$offset}px; - } - $offset: $offset + 18; - } - - $offset: -5; - - @for $level from 0 to 10 { - ul.md-syntax-level-#{$level} > li::before { - left: #{$offset}px; - } - $offset: $offset + 18; - } - - .blockquote { - position: relative; - - &::before { - border-left: 3px solid $tc-light-blue; - content: ""; - height: 100%; - position: absolute; - } - } - - $offset: -15; - - @for $level from 0 to 10 { - .blockquote.md-syntax-level-#{$level}::before { - left: #{$offset}px; - } - $offset: $offset + 18; - } - - div, - .h1, - .h2, - .h3, - .h4, - .h5, - .h6, - p { - @include tc-body-md; - - margin: 0 !important; - text-transform: none; - } - - .h1 .text { - @include tc-heading-xl; - } - .h2 .text { - @include tc-heading-lg; - } - .h3 .text { - @include tc-heading-md; - } - .h4 .text { - @include tc-heading-sm; - } - .h5 .text { - @include tc-heading-xs; - } - .h6 .text { - @include tc-heading-xs; - } - - .mdSyntax { - @include tc-body-md; - - color: firebrick; - font-family: "Roboto Mono", monospace; - font-weight: bold; - } - } -} diff --git a/src/apps/earn/src/components/Editor/MultiEditor.jsx b/src/apps/earn/src/components/Editor/MultiEditor.jsx deleted file mode 100644 index d5b236874..000000000 --- a/src/apps/earn/src/components/Editor/MultiEditor.jsx +++ /dev/null @@ -1,164 +0,0 @@ -/** - * The MultiEditor component combines together WysiwygEditor and Markdown editor - * allowing to easily switch between them. - */ - -import PT from "prop-types"; -import React from "react"; -import Turndown from "turndown"; - -import { OrderedSet } from "immutable"; - -import Connector from "./Connector"; -import MarkdownEditor from "./MarkdownEditor"; -import WysiwygEditor from "."; - -export const MODES = { - MARKDOWN: "MARKDOWN", - WYSIWYG: "WYSIWYG", -}; - -export default class MultiEditor extends React.Component { - constructor(props) { - super(props); - this.fakeConnector = new Connector(); - this.fakeConnector.setToolbar(this); - this.id = props.id; - this.state = { - mode: props.initialMode, - }; - this.turndown = new Turndown(); - } - - componentDidMount() { - const { connector } = this.props; - if (connector) { - connector.addEditor(this); - this.fakeConnector.setPreviewer(connector.previewer); - } - } - - componentWillReceiveProps({ connector, id }) { - const { connector: prevConnector } = this.props; - this.id = id; - if (connector !== prevConnector) { - if (prevConnector) prevConnector.removeEditor(this); - if (connector) { - connector.addEditor(this); - this.fakeConnector.setPreviewer(connector.previewer); - } - } - } - - componentWillUnmount() { - const { connector } = this.props; - if (connector) connector.removeEditor(this); - } - - onFocusedEditorChanged(state) { - const { connector } = this.props; - if (connector) connector.setFocusedEditor(this, state); - } - - getHtml() { - return this.editor.getHtml(); - } - - setHtml(html) { - this.editor.setHtml(html); - } - - setMode(value) { - const { mode } = this.state; - if (value === mode) return; - const { connector } = this.props; - const state = this.editor.getHtml(); - this.setState({ mode: value }, () => { - this.editor.setHtml(state); - if (connector) connector.setFocusedEditor(this, this.editor.state.editor); - }); - } - - applyBlockStyle(type) { - const { mode } = this.state; - if (mode === MODES.WYSIWYG) this.editor.applyBlockStyle(type); - } - - applyColorStyle(type, color) { - const { mode } = this.state; - if (mode === MODES.WYSIWYG) { - this.editor.applyColorStyle(type, color); - } - } - - focus() { - const { mode } = this.state; - if (mode === MODES.WYSIWYG) this.editor.focus(); - } - - insertImage(src, triggerModal) { - const { mode } = this.state; - switch (mode) { - case MODES.WYSIWYG: - return this.editor.insertImage(src, triggerModal); - case MODES.MARKDOWN: - return this.editor.insertImage(); - default: - return undefined; - } - } - - insertLink(title, href, triggerPopup) { - const { mode } = this.state; - if (mode === MODES.WYSIWYG) { - this.editor.insertLink(title, href, triggerPopup); - } - } - - toggleInlineStyle(styleName) { - const { mode } = this.state; - if (mode === MODES.WYSIWYG) { - return this.editor.toggleInlineStyle(styleName); - } - return OrderedSet(); - } - - render() { - const { mode } = this.state; - switch (mode) { - case MODES.MARKDOWN: - return ( - { - if (node) this.editor = node; - }} - /> - ); - case MODES.WYSIWYG: { - return ( - { - if (node) this.editor = node; - }} - /> - ); - } - default: - throw new Error("Unknown mode"); - } - } -} - -MultiEditor.defaultProps = { - connector: null, - id: null, - initialMode: MODES.WYSIWYG, -}; - -MultiEditor.propTypes = { - connector: PT.shape(), - id: PT.string, - initialMode: PT.oneOf(Object.values(MODES)), -}; diff --git a/src/apps/earn/src/components/Editor/Previewer/index.jsx b/src/apps/earn/src/components/Editor/Previewer/index.jsx deleted file mode 100644 index 526885fb4..000000000 --- a/src/apps/earn/src/components/Editor/Previewer/index.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import PT from "prop-types"; -import React from "react"; - -import styles from "./style.scss"; -import { styled as styledCss } from "../../../utils"; -const styled = styledCss(styles) - -export default class Previewer extends React.Component { - constructor(props) { - super(props); - if (props.connector) props.connector.setPreviewer(this); - this.state = { - content: props.initialContent, - visible: false, - }; - } - - setContent(content) { - setImmediate(() => this.setState({ content })); - } - - setVisible(newVisible) { - const { visible } = this.state; - if (newVisible === visible) return; - setImmediate(() => this.setState({ visible: newVisible })); - } - - render() { - const { content, visible } = this.state; - return ( -
- {visible ? ( -
-
Rendering Preview
-
-
- ) : null} -
- ); - } -} - -Previewer.defaultProps = { - connector: null, - initialContent: "", -}; - -Previewer.propTypes = { - connector: PT.shape(), - initialContent: PT.string, -}; diff --git a/src/apps/earn/src/components/Editor/Previewer/style.scss b/src/apps/earn/src/components/Editor/Previewer/style.scss deleted file mode 100644 index d1776dade..000000000 --- a/src/apps/earn/src/components/Editor/Previewer/style.scss +++ /dev/null @@ -1,25 +0,0 @@ -@import "@earn/styles/mixins"; - -.container { - background: white; - overflow: hidden; - position: relative; -} - -.content { - border: 1px solid $tc-gray-40; - height: 33vh; - margin: 0 0 10px; - padding-top: 25px; -} - -.title { - @include tc-label-xs; - - background: $tc-gray-neutral-dark; - color: $tc-gray-40; - left: 1px; - position: absolute; - padding: 5px 10px; - top: 1px; -} diff --git a/src/apps/earn/src/components/Editor/Toolbar/ColorPicker/index.jsx b/src/apps/earn/src/components/Editor/Toolbar/ColorPicker/index.jsx deleted file mode 100644 index 4bc508922..000000000 --- a/src/apps/earn/src/components/Editor/Toolbar/ColorPicker/index.jsx +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Component - * Implements a color picker dropdown populated with the colors found in utils/editor - */ -import _ from "lodash"; -import PT from "prop-types"; -import React from "react"; -import * as Colors from "react-color"; - -import { EDITOR_COLOR_MAP } from "../../../../utils/editor"; - -import styles from "./style.scss"; -import { styled as styledCss } from "@earn/utils"; -const styled = styledCss(styles) - -const ColorPicker = ({ onChange, style, visible }) => ( -
- {visible ? ( - { - e.preventDefault(); - onChange(_.findKey(EDITOR_COLOR_MAP, (value) => value === hex)); - }} - className={styled("color-picker")} - /> - ) : null} -
-); - -ColorPicker.defaultProps = { - onChange: _.noop, - style: "", - visible: false, -}; - -ColorPicker.propTypes = { - onChange: PT.func, - style: PT.string, - visible: PT.bool, -}; - -export default ColorPicker; diff --git a/src/apps/earn/src/components/Editor/Toolbar/ColorPicker/style.scss b/src/apps/earn/src/components/Editor/Toolbar/ColorPicker/style.scss deleted file mode 100644 index a3272ea00..000000000 --- a/src/apps/earn/src/components/Editor/Toolbar/ColorPicker/style.scss +++ /dev/null @@ -1,7 +0,0 @@ -// The react-color component has inline styles which we need to overwrite -.color-picker { - display: inline-flex !important; - flex-wrap: nowrap !important; - position: absolute !important; - width: auto !important; -} diff --git a/src/apps/earn/src/components/Editor/Toolbar/index.jsx b/src/apps/earn/src/components/Editor/Toolbar/index.jsx deleted file mode 100644 index 587f11dd5..000000000 --- a/src/apps/earn/src/components/Editor/Toolbar/index.jsx +++ /dev/null @@ -1,298 +0,0 @@ -/** - * Component - * Implements a Toolbar that can control multiple components - */ -import _ from "lodash"; -import PT from "prop-types"; -import React from "react"; -import Sticky from "react-stickynode"; - -import { Button } from "~/libs/ui"; -import Select from "../../Select"; -import { EDITOR_BLOCK_STYLE_MAP } from "../../../utils/editor"; - -import { RichUtils } from "draft-js"; - -import ColorPicker from "./ColorPicker"; -import Connector from "../Connector"; -import MultiEditor, { MODES } from "../MultiEditor"; - -import styles from "./style.scss"; -import { styled as styledCss } from "../../../utils"; -const styled = styledCss(styles) - -/** - * Component class, provides a Toolbar that can control multiple Editor components - * connected to it via the Connector class - */ -export default class Toolbar extends React.Component { - constructor(props) { - super(props); - this.state = { - block: null, - editor: null, - // markdown: false, - pickingTextColor: false, - // pickingHighlightColor: false, - - BOLD: false, - ITALIC: false, - }; - } - - componentDidMount() { - const { connector } = this.props; - connector.setToolbar(this); - } - - componentWillReceiveProps({ connector: newConnector }) { - const { connector } = this.props; - const prevConnector = connector; - if (newConnector !== prevConnector) { - if (prevConnector) prevConnector.setToolbar(null); - if (newConnector) newConnector.setToolbar(this); - } - } - - componentWillUnmount() { - const { connector } = this.props; - connector.setToolbar(null); - } - - onFocusedEditorChanged(newState) { - const { connector } = this.props; - const editor = connector.focusedEditor; - if (editor) { - const inlineStyle = newState.getCurrentInlineStyle(); - const block = RichUtils.getCurrentBlockType(newState); - this.setState({ - editor, - block, - BOLD: inlineStyle.has("BOLD"), - // INLINE_CODE: inlineStyle.has('CODE'), - ITALIC: inlineStyle.has("ITALIC"), - UNDERLINE: inlineStyle.has("UNDERLINE"), - STRIKETHROUGH: inlineStyle.has("STRIKETHROUGH"), - }); - } else { - this.setState({ - block: "unstyled", - editor: null, - BOLD: false, - // INLINE_CODE: false, - ITALIC: false, - UNDERLINE: false, - STRIKETHROUGH: false, - }); - } - } - - render() { - const st = this.state; - const disableStyling = !st.editor; - const { connector, nodeId, onSave } = this.props; - - const createStyleButton = (label, name, active, className) => ( - - ); - - return ( - -
- {connector.focusedEditor instanceof MultiEditor ? ( -
- { - st.editor.applyBlockStyle(value); - this.setState({ block: value }); - }} - onFocus={(e) => e.preventDefault()} - options={_.map(EDITOR_BLOCK_STYLE_MAP, (label, value) => ({ - label, - value, - }))} - placeholder="Block Style" - value={st.editor ? st.block : null} - /> -
- - {/* I guess, we gonna drop the inline Markdown option. Just for - * a case, let's keep the button code around for a bit longer. */ - /* - - */} -
-
- ); - } -} - -Toolbar.defaultProps = { - connector: new Connector(), - onSave: _.noop, - nodeId: null, -}; - -Toolbar.propTypes = { - connector: PT.instanceOf(Connector), - onSave: PT.func, - nodeId: PT.string, -}; diff --git a/src/apps/earn/src/components/Editor/Toolbar/style.scss b/src/apps/earn/src/components/Editor/Toolbar/style.scss deleted file mode 100644 index 07db930cc..000000000 --- a/src/apps/earn/src/components/Editor/Toolbar/style.scss +++ /dev/null @@ -1,81 +0,0 @@ -@import "@earn/styles/mixins"; - -@mixin button { - margin: 0 1px; - padding: 0 10px; -} - -.basic { - @include button; -} - -.bold { - @include button; - - font-weight: bold; -} - -.container { - background: $tc-gray-neutral-light; - padding: 10px; - width: 100%; -} - -.highlight-color-picker { - display: inline; - position: absolute; - transform: translate(-56px, 44px); -} - -.inlineCode { - @include button; - @include roboto-mono-regular; -} - -.italic { - @include button; - - font-style: italic; -} - -.select { - @include tc-label-md; -} - -.select-wrapper { - @include button; - - display: inline-block; - vertical-align: middle; - width: 250px; -} - -.save { - @include button; -} - -.separator { - display: inline-block; - height: 30px; - margin: 0 5px; - vertical-align: middle; - width: 1px; -} - -.strikethrough { - @include button; - - text-decoration: line-through; -} - -.text-color-picker { - display: inline; - position: absolute; - transform: translate(-44px, 44px); -} - -.underline { - @include button; - - text-decoration: underline; -} diff --git a/src/apps/earn/src/components/Editor/index.jsx b/src/apps/earn/src/components/Editor/index.jsx deleted file mode 100644 index bf12218ea..000000000 --- a/src/apps/earn/src/components/Editor/index.jsx +++ /dev/null @@ -1,306 +0,0 @@ -/** - * Content editor based on DraftJS. - * - * DraftJS is not Redux-friendly, thus our editor uses local state, unlike most - * of our code. Technically, it is possible to keep its state in Redux store, - * but it will have performance drawback, as it will demand constant conversions - * between the Redux state segment and the internal state of the editor. - */ -import _ from "lodash"; -import PT from "prop-types"; -import React from "react"; - -import { - ContentState, - convertFromHTML, - EditorState, - Modifier, - RichUtils, -} from "draft-js"; -import "draft-js/dist/Draft.css"; - -import Editor from "draft-js-plugins-editor"; -import createMarkdownShortcutsPlugin from "draft-js-markdown-shortcuts-plugin"; - -import { EDITOR_COLOR_MAP, editorStateToHTML } from "../../utils/editor"; - -import Connector from "./Connector"; -import createCustomPlugin from "./plugin"; - -import styles from "./style.scss"; - -export default class EditorWrapper extends React.Component { - constructor(props) { - super(props); - this.id = props.id; - - this.state = { - editor: EditorState.createEmpty(), - markdown: false, - }; - - // Each Editor needs its own instance of plugins - this.markdownPlugin = createMarkdownShortcutsPlugin(); - // We need to inject the EditorWrapper into the plugin so that it can - // modify state.editorState - this.customPlugin = createCustomPlugin({ - editor: this, - }); - } - - componentDidMount() { - const { connector, initialContent } = this.props; - connector.addEditor(this); - if (initialContent) { - let editorState = convertFromHTML(initialContent); - editorState = ContentState.createFromBlockArray( - editorState.contentBlocks, - editorState.entityMap - ); - editorState = EditorState.createWithContent(editorState); - this.initialContent = editorState.getCurrentContent(); - setImmediate(() => this.setState({ editor: editorState })); - } - } - - componentWillReceiveProps({ connector, id }) { - const { connector: prevConnector } = this.props; - this.id = id; - if (connector !== prevConnector) { - if (prevConnector) prevConnector.removeEditor(this); - if (connector) connector.addEditor(this); - } - } - - componentWillUnmount() { - const { connector } = this.props; - connector.removeEditor(this); - } - - getHtml() { - const { editor } = this.state; - return editorStateToHTML(editor.getCurrentContent()); - } - - setHtml(html) { - let state = convertFromHTML(html); - state = ContentState.createFromBlockArray( - state.contentBlocks, - state.entityMap - ); - state = EditorState.createWithContent(state); - setImmediate(() => this.setState({ editor: state })); - } - - /** - * Sets the block type/style at the current selection. Type map can be found in utils/editor. - * Only one block type/style can be applied, this will replace the previous. - * @param {String} type The new block style - */ - applyBlockStyle(type) { - const { editor } = this.state; - let editorState = editor; - editorState = RichUtils.toggleBlockType(editorState, type); - this.setState({ editorState }); // eslint-disable-line - } - - /** - * Sets the color at the current selection for the specified category. - * Type map can be found in utils/editor. - * @param {String} type Category, TEXT or HIGHLIGHT - * @param {String} color The new color name - */ - applyColorStyle(type, color) { - let { editor: editorState } = this.state; - let contentState = editorState.getCurrentContent(); - - const sel = editorState.getSelection(); - - // Clear any existing colors - contentState = _.reduce( - EDITOR_COLOR_MAP, - (state, value, name) => - Modifier.removeInlineStyle(state, sel, `${type}_${name}`), - contentState - ); - - editorState = EditorState.push( - editorState, - contentState, - "change-inline-style" - ); - - // Apply new color - editorState = RichUtils.toggleInlineStyle(editorState, `${type}_${color}`); - - this.setState({ editor: editorState }); - } - - focus() { - if (this.node) this.node.focus(); - } - - /** - * Inserts a new image at current cursor selection. - * @param {String} src The default src - * @param {Boolean} triggerModal Whether to trigger the img selection/resize modal on creation - */ - insertImage(src, triggerModal) { - let { editor: editorState } = this.state; - let contentState = editorState.getCurrentContent(); - - // If the user has a range selected, it needs to be collapsed before insertText will work - // This sets the starting and ending range to the same position, - // which is equivalent to just a cursor/caret - let sel = editorState.getSelection(); - const startKey = sel.getStartKey(); - const startOffset = sel.getStartOffset(); - sel = sel.merge({ - anchorKey: startKey, - anchorOffset: startOffset, - focusKey: startKey, - focusOffset: startOffset, - }); - - contentState = contentState.createEntity("IMG", "SEGMENTED", { - src, - triggerModal, - }); - const key = contentState.getLastCreatedEntityKey(); - - // Using insertText so that images behave in an inline fashion - contentState = Modifier.insertText(contentState, sel, " ", null, key); - - editorState = EditorState.push( - editorState, - contentState, - "insert-characters" - ); - - this.setState({ editor: editorState }); - } - - /** - * Inserts a new link at current cursor, or applies to selected text - * @param {String} title Default title to display for the link, if no text is selected in range - * @param {String} href The href - * @param {Boolean} triggerPopup Whether to trigger the popup on creation - */ - insertLink(title, href, triggerPopup) { - let { editor: editorState } = this.state; - let contentState = editorState.getCurrentContent(); - - const sel = editorState.getSelection(); - - contentState = contentState.createEntity("LINK", "MUTABLE", { - href, - triggerPopup, - }); - const key = contentState.getLastCreatedEntityKey(); - - // Selection is a just the cursor, insert new link - if (sel.isCollapsed()) { - // Inserts a space at the cursor, needed so that the user can 'escape' - // from the link entity by clicking after the link, or pressing right arrow - contentState = Modifier.insertText(contentState, sel, " ", null, null); - // Because selection hasn't been updated, this will insert the link *before* - // the newly created space. - contentState = Modifier.insertText(contentState, sel, title, null, key); - - editorState = EditorState.push( - editorState, - contentState, - "insert-characters" - ); - } else { - // Selection is a range, keep the text but make it a link - editorState = RichUtils.toggleLink(editorState, sel, key); - } - - this.setState({ editor: editorState }); - } - - /** - * Toggle an inline text style on/off - * @param {String} styleName Name of the style - * @return {String} The resulting style of the selection - */ - toggleInlineStyle(styleName) { - const { editor } = this.state; - const editorState = RichUtils.toggleInlineStyle(editor, styleName); - this.setState({ editor: editorState }); - return editorState.getCurrentInlineStyle(); - } - - render() { - const { connector, theme } = this.props; - - const st = this.state; - - let containerStyles = styles.container; - if (st.editor.getSelection().getHasFocus()) { - containerStyles += ` ${styles.focused}`; - } - if (theme.container) { - containerStyles += ` ${theme.container}`; - } - - return ( -
this.focus()} - onKeyPress={() => this.focus()} - onFocus={() => this.focus()} - role="button" - tabIndex={0} - > - { - const editorState = RichUtils.handleKeyCommand(state, command); - if (editorState) { - connector.setFocusedEditor(this, editorState); - this.setState({ editor: editorState }); - return true; - } - return false; - }} - onChange={(newState) => { - const p = _.get(this, "props.connector.previewer"); - if (p) p.setVisible(false); - - const hasFocus = newState.getSelection().getHasFocus(); - if ( - !connector.modified && - this.initialContent && - this.initialContent !== newState.getCurrentContent() - ) { - connector.modified = true; - } - connector.setFocusedEditor(hasFocus ? this : null, newState); - this.setState({ editor: newState }); - }} - plugins={[st.markdown ? this.markdownPlugin : {}, this.customPlugin]} - ref={(node) => { - this.node = node; - }} - spellCheck - /> -
- ); - } -} - -EditorWrapper.defaultProps = { - connector: new Connector(), - id: null, - initialContent: null, - theme: {}, -}; - -EditorWrapper.propTypes = { - connector: PT.instanceOf(Connector), - id: PT.string, - initialContent: PT.string, - theme: PT.shape(), -}; diff --git a/src/apps/earn/src/components/Editor/plugin.jsx b/src/apps/earn/src/components/Editor/plugin.jsx deleted file mode 100644 index 2941806cd..000000000 --- a/src/apps/earn/src/components/Editor/plugin.jsx +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Custom DraftJS plugin. - * - * Facilitates the extra functionality required for component. - * Including: Images, Links, and the Note block. - * - * In the future, it should also be possible to validate allowed block elements here, - * and also substitute them for the nearest available option when HTML is rendered. - */ -import _ from "lodash"; -import React from "react"; -import { Map } from "immutable"; -import { EditorState } from "draft-js"; -import { EDITOR_COLOR_MAP } from "../../utils/editor"; - -import Image from "./Image"; -import Link from "./Link"; - -/** - * This is based on the strategy that draft-js-markdown-shortcuts-plugin uses - * so it will work on images and links created with markdown - * - * @param {String} type The block type to create the strategy for, ex. 'IMG', 'LINK' - * @return {Function} The strategy function - */ -const createStrategy = (type) => (contentBlock, callback, contentState) => { - contentBlock.findEntityRanges((metadata) => { - const key = metadata.getEntity(); - return key !== null && contentState.getEntity(key).getType() === type; - }, callback); -}; - -/** - * Creates a custom plugin instance - * - * @param {Object} config Config object, standard interface for Draft JS plugins - * @return {Object} Object representing the Custom Plugin instance, is passed to the - */ -export default ({ editor }) => { - // Store the editor in the closure - const updateEntityData = (key, data) => { - let editorState = editor.state.editor; - - editorState = EditorState.push( - editorState, - editorState.getCurrentContent().replaceEntityData(key, data), - "change-block-data" - ); - - // Force re-render for new data - editorState = EditorState.forceSelection( - editorState, - editorState.getSelection() - ); - - editor.setState({ editorState }); - }; - - const inlineStyles = {}; - - _.forIn(EDITOR_COLOR_MAP, (value, name) => { - inlineStyles[`TEXT_${name}`] = { color: value }; - inlineStyles[`HIGHLIGHT_${name}`] = { background: value }; - }); - - return { - // Provides custom html element rendering for block types - blockRenderMap: Map({ - // draft-js and draft-js-markdown-shortcuts-plugin use inconsistent rendering of - // code-blocks, so we override both of them - "code-block": { - element: "span", - wrapper: , - }, - note: { - element: "span", - wrapper:
, - }, - }), - // Provides custom styling for inline elements (mainly text) - customStyleMap: { - CODE: { - background: "#fafafb", - fontFamily: '"Roboto Mono", monospace', - }, - ...inlineStyles, - }, - // Provides custom component rendering for images and links - decorators: [ - { - strategy: createStrategy("LINK"), - component: Link, - props: { updateEntityData }, - }, - { - strategy: createStrategy("IMG"), - component: Image, - props: { updateEntityData }, - }, - ], - }; -}; diff --git a/src/apps/earn/src/components/Editor/style.scss b/src/apps/earn/src/components/Editor/style.scss deleted file mode 100644 index d3dea4cb3..000000000 --- a/src/apps/earn/src/components/Editor/style.scss +++ /dev/null @@ -1,71 +0,0 @@ -@import "@earn/styles/mixins"; - -:global { - // Has a default z-index of 0 which interferes with component - .DraftEditor-editorContainer { - z-index: auto; - } - - // Draft.js sets some list-related globals that need to be undone, - // and these can't be changed using the blockStyleFn mechanism - .public-DraftStyleDefault-orderedListItem.public-DraftStyleDefault-listLTR::before { - width: auto; - position: relative; - left: 0; - } - - .public-DraftStyleDefault-depth0.public-DraftStyleDefault-listLTR { - margin-left: 0; - } -} - -.container { - @include tc-body-md; - - border: 1px solid $tc-gray-10; - margin: 10px 0; - padding: 10px; - - &:hover { - border: 1px solid $tc-gray-40; - } - - // Draft.js will render code-blocks like
- // This will prevent the code/pre styles from being applied twice - pre { - code { - background: none; - border: 0; - border-radius: none; - margin: 0; - padding: 0; - } - } -} - -.focused { - border: 1px solid $tc-dark-blue; - - &:hover { - border: 1px solid $tc-dark-blue-110; - } -} - -.note { - @include tc-body-sm; - - background: $tc-yellow-30; - border: 1px solid $tc-yellow-70; - border-radius: 6px; - font-style: italic; - color: $tc-black; - line-height: 20px; - padding: 15px 20px; - margin: 25px 0; - - a, - p, - ul { - font-size: 13px; - } -} diff --git a/src/apps/earn/src/components/ErrorMessage/index.jsx b/src/apps/earn/src/components/ErrorMessage/index.jsx deleted file mode 100644 index 6c1eddaba..000000000 --- a/src/apps/earn/src/components/ErrorMessage/index.jsx +++ /dev/null @@ -1,58 +0,0 @@ -import { useEffect } from "react"; -import PT from "prop-types"; -import { BaseModal, Button } from "~/libs/ui"; - -const ErrorMessage = ({ title, details, onOk }) => { - useEffect(() => { - document.body.classList.add("scrolling-disabled-by-modal"); - - return () => { - document.body.classList.remove("scrolling-disabled-by-modal"); - }; - }, []); - - return ( - { - e.preventDefault(); - onOk(); - }} - > - OK - - )} - > -
- - ); -}; - -ErrorMessage.defaultProps = { - details: "", -}; - -ErrorMessage.propTypes = { - title: PT.string.isRequired, - details: PT.string, - onOk: PT.func.isRequired, -}; - -export default ErrorMessage; diff --git a/src/apps/earn/src/components/ErrorMessage/styles.scss b/src/apps/earn/src/components/ErrorMessage/styles.scss deleted file mode 100644 index 5c7328798..000000000 --- a/src/apps/earn/src/components/ErrorMessage/styles.scss +++ /dev/null @@ -1,49 +0,0 @@ -@import '@earn/styles/variables'; -@import '@earn/styles/mixins'; - -$sm-space-10: $base-unit * 2; -$sm-space-15: $base-unit * 3; -$sm-space-25: $base-unit * 5; -$sm-space-40: $base-unit * 8; -$button-space-32: 6 * $base-unit; - -.container { - @include roboto-regular; - - overflow: hidden; - padding: 8 * $base-unit; - text-align: center; - - @include xs-to-sm { - padding: 40px 10px; - } -} - -.details { - font-weight: 400; - font-size: 13px; - color: $tc-gray-60; - line-height: $sm-space-25; - padding: 0 $sm-space-15; - margin-bottom: $sm-space-10; - text-align: justify; - - a { - color: $tc-dark-blue; - text-decoration: underline; - } -} - -.title { - color: $tc-red; - font-size: 15px; - font-weight: bold; - line-height: $sm-space-25; - margin-bottom: $sm-space-10; - padding: 0 $sm-space-15; - - .id { - color: #000; - font-weight: 500; - } -} diff --git a/src/apps/earn/src/components/GigsRadioButton/index.jsx b/src/apps/earn/src/components/GigsRadioButton/index.jsx deleted file mode 100644 index e7997d2fe..000000000 --- a/src/apps/earn/src/components/GigsRadioButton/index.jsx +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Radio button component. - */ -import { Fragment, useEffect, useRef, useState } from "react"; -import PT from "prop-types"; -import cn from "classnames"; -import _ from "lodash"; -import styles from "./styles.scss"; -import config from "../../config"; - -function RadioButton({ - className, - layout = "", - options, - onChange, - size, - errorMsg, -}) { - const [internalOptions, setInternalOptions] = useState(options); - const optionsWithKey = internalOptions.map((o, oIndex) => ({ - ...o, - key: oIndex, - })); - let sizeStyle = size === "lg" ? "lgSize" : null; - if (!sizeStyle) { - sizeStyle = size === "xs" ? "xsSize" : "smSize"; - } - const delayedOnChange = useRef( - _.debounce((q, cb) => cb(q), config.GUIKIT.DEBOUNCE_ON_CHANGE_TIME) // eslint-disable-line no-undef - ).current; - - useEffect(() => { - setInternalOptions(options); - }, [options]); - - return ( - -
- {optionsWithKey.map((o) => ( -
- -
- ))} -
- {errorMsg ? {errorMsg} : null} -
- ); -} - -RadioButton.defaultProps = { - onChange: () => {}, - size: "sm", - errorMsg: "", -}; - -RadioButton.propTypes = { - options: PT.arrayOf( - PT.shape({ - label: PT.string, - value: PT.bool.isRequired, - }) - ).isRequired, - onChange: PT.func, - size: PT.oneOf(["xs", "sm", "lg"]), - errorMsg: PT.string, -}; - -export default RadioButton; diff --git a/src/apps/earn/src/components/GigsRadioButton/styles.scss b/src/apps/earn/src/components/GigsRadioButton/styles.scss deleted file mode 100644 index 9d1daa675..000000000 --- a/src/apps/earn/src/components/GigsRadioButton/styles.scss +++ /dev/null @@ -1,178 +0,0 @@ -@import "../../styles/variables"; -@import '../../styles/GUIKit/default'; - -/* Create a custom radio button */ -.checkmark { - position: absolute; - top: 0; - left: 0; - background-color: $tc-white; - border-radius: 50%; - border: 1px solid $gui-kit-gray-30; - - /* Create the indicator (the dot/circle - hidden when not checked) */ - &::after { - content: ''; - position: absolute; - display: none; - top: 50%; - left: 50%; - margin-top: -6px; - margin-left: -6px; - width: 12px; - height: 12px; - border-radius: 50%; - background-color: $tc-white; - box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.35); - } - - &.hasError { - border: 2px solid $gui-kit-level-5; - } -} - -.radioButton { - display: flex; - align-items: center; -} - -.label { - font-size: 14px; - cursor: pointer; -} - -/* The container */ -.container { - display: block; - position: relative; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - color: $gui-kit-gray-90; - - /* Hide the browser's default radio button */ - input { - position: absolute; - opacity: 0; - cursor: pointer; - - /* When the radio button is checked, add a blue background */ - &:checked ~ .checkmark { - background-color: $gui-kit-level-2; - box-shadow: inset 0 1px 2px 0 rgba(0, 0, 0, 0.29); - border: none; - - /* Show the indicator (dot/circle) when checked */ - &::after { - display: block; - } - } - } -} - -.radioButtonContainer { - display: flex; - flex-direction: column; - - &.horizontal { - flex-direction: row; - - .radioButton { - margin-right: 28px; - - &:last-child { - margin-right: 0; - } - } - } - - .label { - color: $gui-kit-gray-90; - } - - // lg size - &.lgSize { - .container { - padding-left: 24px; - line-height: 24px; - height: 24px; - - .checkmark { - height: 24px; - width: 24px; - - &::after { - margin-top: -6px; - margin-left: -6px; - width: 12px; - height: 12px; - } - } - } - - .label { - margin-left: 8px; - } - } - - // sm size - &.smSize { - .container { - padding-left: 20px; - line-height: 20px; - height: 20px; - - .checkmark { - height: 20px; - width: 20px; - - &::after { - margin-top: -5px; - margin-left: -5px; - width: 10px; - height: 10px; - } - } - } - - .label { - margin-left: 8px; - } - } - - // xs size - &.xsSize { - .container { - padding-left: 15px; - line-height: 15px; - height: 15px; - - .checkmark { - height: 16px; - width: 16px; - - &::after { - margin-top: -4px; - margin-left: -4px; - width: 8px; - height: 8px; - } - } - } - - .label { - margin-left: 8px; - } - } -} - -.errorMessage { - display: block; - - @include errorMessage; - - color: #ef476f; - margin-left: 0; -} diff --git a/src/apps/earn/src/components/LoginModal/index.jsx b/src/apps/earn/src/components/LoginModal/index.jsx deleted file mode 100644 index 6c6557bd0..000000000 --- a/src/apps/earn/src/components/LoginModal/index.jsx +++ /dev/null @@ -1,82 +0,0 @@ -import { useCallback } from "react"; -import MediaQuery from "react-responsive"; -import PT from "prop-types"; -import cn from "classnames"; - -import { Button } from "~/libs/ui"; - -import blobYellow from "../../assets/images/blob-yellow.svg"; -import blobPurple from "../../assets/images/blob-purple.svg"; -import progressBar from "../../assets/images/progress-bar.svg"; -import progressBarMid from "../../assets/images/progress-bar-mid.svg"; -import ProgressBarXS from "../../assets/images/progress-bar-mobile.svg"; -import thinkingFaceMobile from "../../assets/images/thinking-face-mobile.svg"; -import thinkingFace from "../../assets/images/thinking-face-laptop-tablet.svg"; -import { makeLoginUrl, makeRegisterUrl } from "../../utils/url"; -import modalStyles from "../../styles/_modal.scss"; - -import styles from "./styles.scss"; -import BaseModal from "../../../../../libs/ui/lib/components/modals/base-modal/BaseModal"; - -function LoginModal({ onClose, open }) { - const onClickBtnRegister = useCallback(() => { - window.open(makeRegisterUrl(window.location.href)); - }, []); - - return ( - -
- - -

YAY! You are almost done!

-

- Looks like you're not a Topcoder member yet. Or maybe you're - not logged in? - - - - - - - It's quick to register and it's free! -

- - - - - - - - - -
- -
-

- Already a member? Login here -

-
-
- ); -} - -LoginModal.defaultProps = { - utmSource: "gig_listing", -}; - -LoginModal.propTypes = { - utmSource: PT.string, -}; - -export default LoginModal; diff --git a/src/apps/earn/src/components/LoginModal/styles.scss b/src/apps/earn/src/components/LoginModal/styles.scss deleted file mode 100644 index 9e0533fad..000000000 --- a/src/apps/earn/src/components/LoginModal/styles.scss +++ /dev/null @@ -1,156 +0,0 @@ -@import "../../styles/mixins"; - -.title { - position: relative; - color: #9d41c9; - @include barlow-condensed-medium; - font-size: 60px; - line-height: 58px; - text-transform: uppercase; - margin: 0; - margin-bottom: 30px; - - @include xs-to-sm { - max-width: 400px; - margin: auto; - font-size: 60px !important; - line-height: 58px !important; - margin-bottom: 30px; - } - - @media (max-width: 425px) { - max-width: 230px; - margin: auto; - font-size: 36px !important; - line-height: 34px !important; - margin-bottom: 30px; - } -} - -.loginMsg { - color: #2a2a2a; - font-size: 24px; - line-height: 36px; - margin-bottom: 40px; - - img { - display: inline; - } - - @media (max-width: 425px) { - text-align: left !important; - font-size: 20px; - line-height: 30px; - margin-bottom: 30px; - } -} - -.controls { - display: flex; - align-content: center; - justify-content: center; - margin: 0; - - & > button:first-child { - margin-right: 10px !important; - } - - & > a:first-child { - margin-right: 10px !important; - } -} - -.referrals { - display: flex; - overflow: auto; - - .sucessMsg { - font-size: 24px; - line-height: 36px; - margin-bottom: 40px; - } - - .rightAlign { - justify-content: flex-end; - } -} - -.loginRequired { - display: flex; - flex-direction: column; - padding: 80px 55px 40px 60px; - text-align: center; - position: relative; - overflow: hidden; - - @include xs-to-sm { - padding: 50px 35px 40px; - } - - @media (max-width: 425px) { - padding: 50px 35px 70px; - } - - .progressBar { - display: block; - width: 100%; - max-width: 100%; - - @include phone-only { - margin-bottom: 40px; - } - } - - .blobYellow, - .blobPurple { - display: block; - position: absolute; - max-width: 100%; - } - - .blobYellow { - top: 0; - right: 0; - - @media (max-width: 425px) { - max-width: 62px; - } - } - - .blobPurple { - bottom: -5px; - left: 0; - - @media (max-width: 425px) { - max-width: 84px; - bottom: -40px; - } - } - - .thinkingFace { - width: 23px; - margin: 0 5px; - transform: translateY(4px); - - @media (max-width: 425px) { - width: 21px; - transform: translateY(2px); - } - } - - .regTxt { - position: relative; - font-size: 16px; - margin: 30px 0 0; - - a { - color: #0D61BF; - text-decoration: underline; - } - } -} - -.overlay { - background-color: #2a2a2a; - opacity: 0.95; -} diff --git a/src/apps/earn/src/components/Menu/index.jsx b/src/apps/earn/src/components/Menu/index.jsx deleted file mode 100644 index 60fca660b..000000000 --- a/src/apps/earn/src/components/Menu/index.jsx +++ /dev/null @@ -1,182 +0,0 @@ -import React, { useRef, useEffect } from "react"; -import { navigate } from "react-router-dom"; -import PT from "prop-types"; -import _ from "lodash"; - -import IconChevronUp from "../../assets/icons/menu-chevron-up.svg"; -import { MenuSelection, getMenuIcon } from "../../utils"; - -import styles from "./styles.scss"; -import { styled as styledCss } from "@earn/utils"; -const styled = styledCss(styles) - -const Menu = ({ menu, selected, onSelect, isLoggedIn, onUpdateMenu }) => { - const selectionRef = useRef(); - if (!selectionRef.current) { - selectionRef.current = new MenuSelection( - _.cloneDeep(menu), - selected, - onSelect, - onUpdateMenu - ); - } - - useEffect(() => { - selectionRef.current.setMenu(menu); - }, [menu]); - - useEffect(() => { - selectionRef.current.select(selected); - }, [selected]); - - // useEffect(() => { - // if (selectionRef.current.isAuth(selected) && isLoggedIn === false) { - // utils.auth.logIn(); - // } - // }, [selected, isLoggedIn]); - - const onSelectMenuItem = (name, path) => { - selectionRef.current.select(name); - if (path) { - navigate(path); - } - }; - - const getIcon = (menuItem, active) => { - const name = active ? menuItem.iconActive : menuItem.icon; - return getMenuIcon(name); - }; - - const isExpandable = (menuItem) => - selectionRef.current.isExpandable(menuItem); - const isSelected = (menuItem) => selectionRef.current.isSelected(menuItem); - const isExpanded = (menuItem) => selectionRef.current.isExpanded(menuItem); - const isActive = (menuItem) => selectionRef.current.isActive(menuItem); - - const renderSubSubmenu = (subMenuItem) => { - return ( -
    - {subMenuItem.children.map((subSubmenuItem) => ( -
  • - { - onSelectMenuItem(subSubmenuItem.name, subSubmenuItem.path); - }} - > - {subSubmenuItem.name} - -
  • - ))} -
- ); - }; - - const renderSubmenu = (menuItem) => { - if (!menuItem.children) { - return null; - } - - return ( -
    - {menuItem.children.map((subMenuItem) => ( -
  • - { - onSelectMenuItem( - subMenuItem.name, - isExpandable(subMenuItem) ? null : subMenuItem.path - ); - }} - > - {subMenuItem.name} - - {isExpandable(subMenuItem) && renderSubSubmenu(subMenuItem)} -
  • - ))} -
- ); - }; - - return ( - - ); -}; - -Menu.propTypes = { - menu: PT.shape(), - selected: PT.string, - onSelect: PT.func, - isLoggedIn: PT.oneOf([null, true, false]), -}; - -export default Menu; diff --git a/src/apps/earn/src/components/Menu/styles.scss b/src/apps/earn/src/components/Menu/styles.scss deleted file mode 100644 index 3782a14a4..000000000 --- a/src/apps/earn/src/components/Menu/styles.scss +++ /dev/null @@ -1,102 +0,0 @@ -@import "@earn/styles/variables"; - -$menu-padding-x: 4 * $base-unit; -$menu-padding-y: 20px; - -.menu { - padding: $menu-padding-y $menu-padding-x (3 * $base-unit); - - &.logged-in {} - - &.logged-out { - .menu-item-auth { - display: none; - } - } -} - -.menu-item { - padding: 4px 0; - cursor: pointer; - - .link { - display: flex; - align-items: center; - line-height: 26px; - outline: none; - } - - .icon { - width: 24px; - height: 24px; - margin-right: 16px; - text-align: left; - } - - .text {} - - .arrow { - width: 21px; - height: 21px; - margin-left: 8px; - line-height: 1; - text-align: center; - vertical-align: middle; - - &.up {} - &.down { - transform: rotate(180deg); - } - } - - &.active > .link { - font-weight: 500; - } - - &.selected > .link { - color: $tc-turquoise-dark1; - } -} - -.menu-item-main > .link { - margin-left: -20px; - margin-right: -20px; - padding-left: 20px; - padding-right: 20px; -} - -.menu-item-main.active > .link { - box-shadow: inset 4px 0 $tc-turquoise; -} - -.menu-item-main > .link + ul, -.menu-item-secondary > .link + ul { - display: none; -} - -.menu-item-main.expanded > .link + ul, -.menu-item-secondary.expanded > .link + ul { - display: block; - cursor: default; -} - -.menu-item-secondary.active.collapsed { - color: $tc-turquoise-dark1; -} - -.sub-menu { - padding-left: 24px + 16px; - - .menu-item { - cursor: default; - .link { - cursor: pointer; - display: inline-block; - } - } - -} - -.sub-submenu { - padding-left: 20px; -} diff --git a/src/apps/earn/src/components/MetaTags/index.jsx b/src/apps/earn/src/components/MetaTags/index.jsx deleted file mode 100644 index fd60501f3..000000000 --- a/src/apps/earn/src/components/MetaTags/index.jsx +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Auxiliary wrapper around React Helmet that helps to generate meta tags for - * generic use cases. - * - * NOTE: This component relies on `domain` path of Redux store to hold - * the current app domain, which will serve as the base path for the bundled - * images. - */ - -import React from "react"; -import PT from "prop-types"; -import { connect } from "react-redux"; -import { Helmet } from "react-helmet"; - -function MetaTags({ - description, - domain, - image, - siteName, - socialDescription, - socialTitle, - title, - url, -}) { - const img = `${domain}${image}`; - const socTitle = socialTitle || title; - const socDesc = socialDescription || description; - return ( - - {/* General tags. */} - {title} - - - {/* Twitter cards. */} - - - - {image ? : null} - {siteName ? : null} - - {/* Open Graph data. */} - - {image ? : null} - {image ? : null} - - {siteName ? : null} - {url ? : null} - - ); -} - -MetaTags.defaultProps = { - image: null, - siteName: null, - socialDescription: null, - socialTitle: null, - url: null, -}; - -MetaTags.propTypes = { - description: PT.string.isRequired, - domain: PT.string, - image: PT.string, - siteName: PT.string, - socialDescription: PT.string, - socialTitle: PT.string, - title: PT.string.isRequired, - url: PT.string, -}; - -/* TODO: It is not good to depend on the domain written into redux state here, - * better pass it via the renderer context at the server side, and get it from - * the location at the frontend side, or something similar? */ -export default connect((state) => ({ domain: state.domain }))(MetaTags); diff --git a/src/apps/earn/src/components/MultiSelect/index.jsx b/src/apps/earn/src/components/MultiSelect/index.jsx deleted file mode 100644 index 161147612..000000000 --- a/src/apps/earn/src/components/MultiSelect/index.jsx +++ /dev/null @@ -1,237 +0,0 @@ -//import "react-select/dist/react-select.css"; -import styles from './styles.scss'; -import React, { useState } from 'react'; -import PT from 'prop-types'; -import Select, { components } from 'react-select'; -import cn from 'classnames'; -import iconDown from '../../assets/icons/dropdown-arrow.png'; - -const Arrow = () => ( - icon down -); - -const Menu = (props) => { - return ( - - {props.children} - - ); -}; -const MenuList = (props) => { - return ( - - {props.children} - - ); -}; - -const CustomOption = (props) => { - return ( - - {props.children} - - ); -}; - -const ValueContainer = ({ children, ...props }) => ( - - {children} - -); - -const ControlComponent = (props) => { - return ( - - ); -}; -const IndicatorsContainer = (props) => { - return ( - - ); -}; -const SelectContainer = (props) => { - return ( - - ); -}; - -const MultiValueContainer = (props) => { - return ( - - ); -}; - -const MultiValueLabel = (props) => { - return ( - - ); -}; - -const MultiValueRemove = ({ children, ...props }) => ( - - {children} - -); - -const Input = (props) => { - return ( - - ); -}; - -const Placeholder = (props) => { - return ( - - ); -}; - -const IndicatorSeparator = () => { - return null; -}; -const DropdownIndicator = () => { - return null; -}; - -/** - * Displays a multi-select field. - * - * @param {Object} props component properties - * @returns {JSX.Element} - */ -const MultiSelect = ({ - className, - clearable, - label, - isRequired = false, - onChange, - onFocus, - options, - optLabelKey, - optValueKey, - placeholder, - showArrow = false, - size, - value, - error, -}) => { - const [focused, setFocused] = useState(false); - return ( - <> -
setFocused(true)} - onBlurCapture={() => setFocused(false)} - className={[ - styles.container, - styles[size], - className, - !!error ? styles['hasError'] : '', - ].join(' ')} - > - {label && ( - - {label + (isRequired ? ' *' : '')} - - )} - { - const newOptions = optionsWithKey.map((oWithKeyTmp) => ({ - label: oWithKeyTmp.label, - value: o.key === oWithKeyTmp.key, - })); - setInternalOptions(newOptions); - delayedOnChange(_.cloneDeep(newOptions), onChange); - }} - /> - - {o.label ? {o.label} : null} - -
- ))} -
- {errorMsg ? {errorMsg} : null} - - ); -} - -RadioButton.defaultProps = { - onChange: () => {}, - size: "sm", - errorMsg: "", -}; - -RadioButton.propTypes = { - options: PT.arrayOf( - PT.shape({ - label: PT.string, - value: PT.bool.isRequired, - }) - ).isRequired, - onChange: PT.func, - size: PT.oneOf(["xs", "sm", "lg"]), - errorMsg: PT.string, -}; - -export default RadioButton; diff --git a/src/apps/earn/src/components/RadioButton/styles.module.scss b/src/apps/earn/src/components/RadioButton/styles.module.scss deleted file mode 100644 index 0f8fa0bd5..000000000 --- a/src/apps/earn/src/components/RadioButton/styles.module.scss +++ /dev/null @@ -1,166 +0,0 @@ -@import "@earn/styles/variables"; -@import '@earn/styles/GUIKit/default'; - -/* Create a custom radio button */ -.checkmark { - position: absolute; - top: 0; - left: 0; - background-color: $tc-white; - border-radius: 50%; - border: 1px solid $gui-kit-gray-30; - - /* Create the indicator (the dot/circle - hidden when not checked) */ - &::after { - content: ''; - position: absolute; - display: none; - top: 50%; - left: 50%; - margin-top: -6px; - margin-left: -6px; - width: 12px; - height: 12px; - border-radius: 50%; - background-color: $tc-white; - box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.35); - } - - &.hasError { - border: 2px solid $gui-kit-level-5; - } -} - -.radioButton { - display: flex; - align-items: center; -} - -.label { - font-size: 14px; - cursor: pointer; -} - -/* The container */ -.container { - display: block; - position: relative; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - color: $gui-kit-gray-90; - - /* Hide the browser's default radio button */ - input { - position: absolute; - opacity: 0; - cursor: pointer; - - /* When the radio button is checked, add a blue background */ - &:checked ~ .checkmark { - background-color: $gui-kit-level-2; - box-shadow: inset 0 1px 2px 0 rgba(0, 0, 0, 0.29); - border: none; - - /* Show the indicator (dot/circle) when checked */ - &::after { - display: block; - } - } - } -} - -.radioButtonContainer { - display: flex; - flex-direction: column; - - .label { - color: $gui-kit-gray-90; - } - - // lg size - &.lgSize { - .container { - padding-left: 24px; - line-height: 24px; - height: 24px; - - .checkmark { - height: 24px; - width: 24px; - - &::after { - margin-top: -6px; - margin-left: -6px; - width: 12px; - height: 12px; - } - } - } - - .label { - margin-left: 8px; - } - } - - // sm size - &.smSize { - .container { - padding-left: 20px; - line-height: 20px; - height: 20px; - - .checkmark { - height: 20px; - width: 20px; - - &::after { - margin-top: -5px; - margin-left: -5px; - width: 10px; - height: 10px; - } - } - } - - .label { - margin-left: 8px; - } - } - - // xs size - &.xsSize { - .container { - padding-left: 15px; - line-height: 15px; - height: 15px; - - .checkmark { - height: 16px; - width: 16px; - - &::after { - margin-top: -4px; - margin-left: -4px; - width: 8px; - height: 8px; - } - } - } - - .label { - margin-left: 8px; - } - } -} - -.errorMessage { - display: block; - - @include errorMessage; - - color: #ef476f; - margin-left: 0; -} diff --git a/src/apps/earn/src/components/ReferralAuthModal/index.jsx b/src/apps/earn/src/components/ReferralAuthModal/index.jsx deleted file mode 100644 index 063726d7e..000000000 --- a/src/apps/earn/src/components/ReferralAuthModal/index.jsx +++ /dev/null @@ -1,66 +0,0 @@ -import { useCallback } from "react"; -import PT from "prop-types"; - -import { BaseModal, Button } from "~/libs/ui"; - -import { REFERRAL_PROGRAM_URL } from "../../constants"; -import { makeLoginUrl, makeRegisterUrl } from "../../utils/url"; - -import styles from "./styles.scss"; - -/** - * Displays a modal with "Login" and "Register" buttons which is displayed after - * the user clicks the button in the ReferralBanner. - * - * @param {Object} props component properties - * @returns {JSX.Element} - */ -const ReferralAuthModal = ({ onClose, open }) => { - const onClickBtnLogin = useCallback(() => { - window.location = makeLoginUrl(window.location.href); - }, []); - - const onClickBtnRegister = useCallback(() => { - window.open(makeRegisterUrl(window.location.href)); - }, []); - - return ( - -
Referral Program
-
Please login to receive your referral code.
-
- - -
-
- Find out how the referral program works{" "} - - here - - . -
-
- ); -}; - -ReferralAuthModal.propTypes = { - onClose: PT.func.isRequired, - open: PT.bool.isRequired, -}; - -export default ReferralAuthModal; diff --git a/src/apps/earn/src/components/ReferralAuthModal/styles.scss b/src/apps/earn/src/components/ReferralAuthModal/styles.scss deleted file mode 100644 index a9c23b93b..000000000 --- a/src/apps/earn/src/components/ReferralAuthModal/styles.scss +++ /dev/null @@ -1,48 +0,0 @@ -@import '@libs/ui/styles/includes'; -@import "../../styles/mixins"; -@import "../../styles/variables"; - -.content { - display: block; -} - -.title { - @include barlow-condensed-medium; - font-size: 34px; - line-height: 38px; - text-transform: uppercase; - color: #1e94a3; -} - -.message { - margin: 20px 0 0; - font-size: 20px; - line-height: 30px; - text-align: center; - - @include tablet { - font-size: 24px; - line-height: 36px; - } -} - -.controls { - display: flex; - justify-content: center; - margin: 40px 0 0; - gap: $sp-3; -} - -.hint { - margin: 10px 0 0; - @include roboto-regular; - font-size: 14px; - line-height: 26px; - - a { - font-size: 16px; - line-height: 24px; - color: #0d61bf; - text-decoration: underline; - } -} diff --git a/src/apps/earn/src/components/ReferralEmailModal/index.jsx b/src/apps/earn/src/components/ReferralEmailModal/index.jsx deleted file mode 100644 index 065c75aa4..000000000 --- a/src/apps/earn/src/components/ReferralEmailModal/index.jsx +++ /dev/null @@ -1,68 +0,0 @@ -import modalStyles from "../../styles/_modal.scss"; -import cn from "classnames"; - -import { BaseModal, Button, LinkButton } from "~/libs/ui"; - -import { LoadingCircles } from "~/libs/ui"; -import { GIG_LIST_ROUTE } from "../../constants"; - -import styles from "./styles.scss"; - -const ReferralEmailModal = ({ error, isBusy, isUserError, onClose, open }) => ( - - {isBusy ? ( - <> -
Sending your referral...
- - - ) : ( - <> -
- {error ? "Oops!" : "Congratulations!"} -
-
- {error ? error : "Your referral has been sent."} -
- {!!error && - (isUserError ? ( -
- If you think this is an error please contact -
- support@topcoder.com. -
- ) : ( -
- Looks like there is a problem on our end. Please try again. -
- If this persists please contact{" "} - support@topcoder.com. -
- ))} -
- - - FIND ANOTHER GIG - -
- - )} -
-); - -export default ReferralEmailModal; diff --git a/src/apps/earn/src/components/ReferralEmailModal/styles.scss b/src/apps/earn/src/components/ReferralEmailModal/styles.scss deleted file mode 100644 index c3df4a43b..000000000 --- a/src/apps/earn/src/components/ReferralEmailModal/styles.scss +++ /dev/null @@ -1,24 +0,0 @@ -.sendLoadingIndicator { - display: block; - margin: 20px auto 0; -} - -.hint { - margin: 40px 0 20px; - font-size: 14px; - line-height: 26px; - text-align: center; - - a { - color: #0d61bf; - text-decoration: underline; - } - - + .controls { - margin: 0; - } -} - -.error { - color: #f00; -} diff --git a/src/apps/earn/src/components/SearchField/index.jsx b/src/apps/earn/src/components/SearchField/index.jsx deleted file mode 100644 index 7f58ca0bc..000000000 --- a/src/apps/earn/src/components/SearchField/index.jsx +++ /dev/null @@ -1,63 +0,0 @@ -import styles from "./styles.scss"; -import React, { useCallback } from "react"; -import PT from "prop-types"; -import cn from "classnames"; - -import { ReactComponent as IconMagnifier } from "../../assets/icons/icon-magnifier.svg"; - -/** - * Displays search input field. - * - * @param {Object} props component properties - * @param {string} [props.className] class name added to root element - * @param {string} props.id id for input element - * @param {string} props.placeholder placeholder text - * @param {string} props.name name for input element - * @param {'medium'|'small'} [props.size] field size - * @param {function} props.onChange function called when input value changes - * @param {string} props.value input value - * @returns {JSX.Element} - */ -const SearchField = ({ - className, - id, - name, - size = "medium", - onChange, - placeholder, - value, -}) => { - const onInputChange = useCallback( - (event) => { - onChange(event.target.value); - }, - [onChange] - ); - - return ( -
- - -
- ); -}; - -SearchField.propTypes = { - className: PT.string, - id: PT.string.isRequired, - size: PT.oneOf(["medium", "small"]), - name: PT.string.isRequired, - onChange: PT.func.isRequired, - placeholder: PT.string, - value: PT.oneOfType([PT.number, PT.string]), -}; - -export default SearchField; diff --git a/src/apps/earn/src/components/SearchField/styles.scss b/src/apps/earn/src/components/SearchField/styles.scss deleted file mode 100644 index 8460e83c1..000000000 --- a/src/apps/earn/src/components/SearchField/styles.scss +++ /dev/null @@ -1,38 +0,0 @@ -.container { - display: flex; - align-items: center; - border: 1px solid #aaa; - border-radius: 6px; - background-color: #fff; - - &.medium { - height: 40px; - } - - &.small { - height: 30px; - } -} - -.icon { - margin: auto 10px; - width: 16px; - height: 16px; -} - -input.input { - flex: 1 1 0; - margin: 0; - border: none !important; - padding: 8px 16px 8px 0; - height: 22px; - line-height: 22px; - background: none; - outline: none !important; - box-shadow: none !important; - - &::placeholder { - text-transform: none; - color: #aaa; - } -} diff --git a/src/apps/earn/src/components/Select/index.jsx b/src/apps/earn/src/components/Select/index.jsx deleted file mode 100644 index c0e8a5e25..000000000 --- a/src/apps/earn/src/components/Select/index.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import _ from "lodash"; -import ReactSelect from "react-select"; -import PT from "prop-types"; -import styles from "./style.scss"; - -export default function Select(props) { - const { selectRef } = props; - return ( -
- -
- ); -} - -Select.defaultProps = { - selectRef: _.noop, -}; - -Select.propTypes = { - selectRef: PT.func, -}; diff --git a/src/apps/earn/src/components/Select/style.scss b/src/apps/earn/src/components/Select/style.scss deleted file mode 100644 index f823c926c..000000000 --- a/src/apps/earn/src/components/Select/style.scss +++ /dev/null @@ -1,18 +0,0 @@ -.select { - :global { - // @import "react-select/dist/react-select"; - - width: 100%; - - input.Select-input, - input.Select-input:focus { - background-color: transparent !important; - margin-left: 0 !important; - padding-right: 6px !important; - } - - .Select-multi-value-wrapper { - width: 100% !important; - } - } -} diff --git a/src/apps/earn/src/components/SubmissionManagement/Icons/IconCloudDownload.svg b/src/apps/earn/src/components/SubmissionManagement/Icons/IconCloudDownload.svg deleted file mode 100644 index b17e3bc52..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/Icons/IconCloudDownload.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/src/apps/earn/src/components/SubmissionManagement/Icons/IconMinimalDown.svg b/src/apps/earn/src/components/SubmissionManagement/Icons/IconMinimalDown.svg deleted file mode 100644 index 96fdc951e..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/Icons/IconMinimalDown.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/apps/earn/src/components/SubmissionManagement/Icons/IconMinimalLeft.svg b/src/apps/earn/src/components/SubmissionManagement/Icons/IconMinimalLeft.svg deleted file mode 100644 index 287bf690e..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/Icons/IconMinimalLeft.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - diff --git a/src/apps/earn/src/components/SubmissionManagement/Icons/IconMinimalRight.svg b/src/apps/earn/src/components/SubmissionManagement/Icons/IconMinimalRight.svg deleted file mode 100644 index d2905c94b..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/Icons/IconMinimalRight.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - diff --git a/src/apps/earn/src/components/SubmissionManagement/Icons/IconMinimalUp.svg b/src/apps/earn/src/components/SubmissionManagement/Icons/IconMinimalUp.svg deleted file mode 100644 index 9bf3e2d5a..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/Icons/IconMinimalUp.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - diff --git a/src/apps/earn/src/components/SubmissionManagement/Icons/IconSearch.svg b/src/apps/earn/src/components/SubmissionManagement/Icons/IconSearch.svg deleted file mode 100644 index 30f678532..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/Icons/IconSearch.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/apps/earn/src/components/SubmissionManagement/Icons/IconShare.svg b/src/apps/earn/src/components/SubmissionManagement/Icons/IconShare.svg deleted file mode 100644 index 2c731ab66..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/Icons/IconShare.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - diff --git a/src/apps/earn/src/components/SubmissionManagement/Icons/IconSquareDownload.svg b/src/apps/earn/src/components/SubmissionManagement/Icons/IconSquareDownload.svg deleted file mode 100644 index e56fda655..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/Icons/IconSquareDownload.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/apps/earn/src/components/SubmissionManagement/Icons/IconTrashSimple.svg b/src/apps/earn/src/components/SubmissionManagement/Icons/IconTrashSimple.svg deleted file mode 100644 index 5b430a5e3..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/Icons/IconTrashSimple.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - diff --git a/src/apps/earn/src/components/SubmissionManagement/Icons/IconZoom.svg b/src/apps/earn/src/components/SubmissionManagement/Icons/IconZoom.svg deleted file mode 100644 index 30f678532..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/Icons/IconZoom.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/apps/earn/src/components/SubmissionManagement/ScreeningDetails/index.jsx b/src/apps/earn/src/components/SubmissionManagement/ScreeningDetails/index.jsx deleted file mode 100644 index 706ff51f9..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/ScreeningDetails/index.jsx +++ /dev/null @@ -1,133 +0,0 @@ -/** - * This compnent receives via props the screening object and nicely renders them. - * Note that this component both has the text coming directly from the screening object, - * and the text generated based on the screening status - * - */ - -import PT from 'prop-types'; -import shortid from 'shortid'; -import { styled as styledCss } from '@earn/utils'; - -import styles from './styles.scss'; -const styled = styledCss(styles); - -export default function ScreeningDetails(props) { - const { - screeningObject, - helpPageUrl, - } = props; - - const hasWarnings = screeningObject.warnings; - const hasStatus = screeningObject.status; - const hasStatusPassed = hasStatus === 'passed'; - const hasStatusFailed = hasStatus === 'failed'; - const hasPending = screeningObject.status === 'pending'; - const warnLength = screeningObject.warnings && hasWarnings.length; - - const setStatusInfo = () => { - if (hasPending) { - return { - title: 'Pending', - classname: 'pending', - message: 'Your submission has been received, and will be screened after the end of the phase', - }; - } if (hasStatusPassed && !hasWarnings) { - return { - title: 'Passed Screening', - classname: 'passed', - message: 'You have passed screening.', - }; - } if (hasStatusFailed && !hasWarnings) { - return { - title: 'Failed Screening', - classname: 'failed', - message: 'You have failed screening', - }; - } if (hasStatusPassed && hasWarnings) { - return { - title: 'Passed Screening with Warnings', - classname: 'passed', - message: `You have passed screening, but the screener has given you ${warnLength} warnings that you must fix in round 2.`, - }; - } if (hasStatusFailed && hasWarnings) { - return { - title: 'Failed Screening with Warnings', - classname: 'failed', - message: 'You have failed screening and the screener has given you the following warning.', - }; - } - return { - title: '', - classname: '', - message: 'Your submission has been received, and will be evaluated during Review phase.', - }; - }; - - let warnings = []; - if (screeningObject.warnings) { - warnings = screeningObject.warnings.map((warning, i) => ( -
-
- - Warning - - {' '} - {`${1 + i} : ${warning.brief}`} -
-

- {warning.details} -

-
- )); - } - return ( -
-
-

- {setStatusInfo().title} -

- {/* - NOTE: TonyJ asked to remove the OR links from the page to keep - users within the new Topcoder site as much as we can. Not wiping - out the code just in case we decide to bring it back later. - - Online Review - - */} -
-

- {setStatusInfo().message} - - {' '}Need help? - -

-
- {warnings} - {((hasStatusFailed) || (hasStatusPassed && hasWarnings)) - && ( -

- Need more info on how to pass screening? - Go to help to read Rules & Policies. -

- )} -
-
- ); -} - -ScreeningDetails.defaultProps = { - screeningObject: {}, - helpPageUrl: '', -}; - -ScreeningDetails.propTypes = { - screeningObject: PT.shape({ - status: PT.string, - warnings: PT.arrayOf(PT.shape({ - brief: PT.string.isRequired, - details: PT.string.isRequired, - })), - }), - helpPageUrl: PT.string, -}; diff --git a/src/apps/earn/src/components/SubmissionManagement/ScreeningDetails/styles.scss b/src/apps/earn/src/components/SubmissionManagement/ScreeningDetails/styles.scss deleted file mode 100644 index 2310fef9b..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/ScreeningDetails/styles.scss +++ /dev/null @@ -1,88 +0,0 @@ -@import '@earn/styles/mixins'; -$status-space-10: $base-unit * 2; -$status-space-15: $base-unit * 3; -$status-space-20: $base-unit * 4; -$status-space-25: $base-unit * 5; -$gray-color: $tc-gray-80; -$green-color: $tc-green; -$red-color: $tc-red; - -.online-review-link { - background: none; -} - -.screening-details { - font-weight: 500; - font-size: 14px; - color: $tc-black; - letter-spacing: 0; - line-height: 22px; - - .screening-details-head { - display: flex; - margin-bottom: $base-unit; - - .status-title { - font-weight: 700; - color: $tc-orange; - letter-spacing: 0; - line-height: $status-space-20; - - .passed { - color: $green-color; - } - - &.failed { - color: $red-color; - } - - &.pending { - color: $gray-color; - } - } - - .online-review-link { - display: block; - margin-left: auto; - line-height: $status-space-20; - font-weight: 400; - font-size: 13px; - color: $tc-dark-blue-110; - text-decoration: underline; - padding: 0; - border: none; - text-transform: capitalize; - - &:hover { - opacity: 0.7; - } - - &:focus { - outline: none; - } - } - } - - .screening-warning { - margin-top: $status-space-15; - } - - .more-info { - margin-top: $status-space-15; - margin-bottom: $base-unit; - } - - .warning-bold { - font-weight: 700; - line-height: $status-space-20; - } - - .help-btn { - text-align: right; - } - - .help-link { - color: $tc-dark-blue-110; - cursor: pointer; - } -} diff --git a/src/apps/earn/src/components/SubmissionManagement/ScreeningStatus/index.jsx b/src/apps/earn/src/components/SubmissionManagement/ScreeningStatus/index.jsx deleted file mode 100644 index 3110f371e..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/ScreeningStatus/index.jsx +++ /dev/null @@ -1,97 +0,0 @@ -/** - * This component receives the screening object via props. - * Depending on status, presence and count of warnings, - * it renders itself in one of the ways shown in specs. - * When status is pending it renders just 'Not yet performed' text. - * When no screening object received, nothing is rendered. - * - * When hovered this object should update mouse cursor to pointer, - * and on click it should call the onClick() callback passed from parent. - * Parent code will use that signal to show/hide the panel with - * screening details for this submission. - * - */ - -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; - -import { styled as styledCss } from '@earn/utils'; - -import styles from './styles.scss'; -const styled = styledCss(styles); - -export default function ScreeningStatus(props) { - const { - screeningObject, - onShowDetails, - submissionId, - } = props; - - const hasWarnings = screeningObject.warnings; - const hasStatus = screeningObject.status; - const hasStatusPassed = hasStatus === 'passed'; - const hasStatusFailed = hasStatus === 'failed'; - const hasPending = screeningObject.status === 'pending'; - const warnLength = screeningObject.warnings && hasWarnings.length; - - const setClassName = () => { - if (hasPending) { - return 'pending'; - } if (hasStatusPassed && !hasWarnings) { - return 'pass-with-no-warn'; - } if (hasStatusFailed && !hasWarnings) { - return 'fail-with-no-warn'; - } - return 'has-warn'; - }; - const setStatusClassName = () => { - if (hasStatusPassed && hasWarnings) { - return 'passed'; - } if (hasStatusFailed && hasWarnings) { - return 'failed'; - } - return ''; - }; - return ( - - ); -} - -ScreeningStatus.defaultProps = { - onShowDetails: _.noop, -}; - -ScreeningStatus.propTypes = { - screeningObject: PT.shape({ - status: PT.string, - warnings: PT.array, - }).isRequired, - onShowDetails: PT.func, - submissionId: PT.number.isRequired, -}; diff --git a/src/apps/earn/src/components/SubmissionManagement/ScreeningStatus/styles.scss b/src/apps/earn/src/components/SubmissionManagement/ScreeningStatus/styles.scss deleted file mode 100644 index 80fa75a06..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/ScreeningStatus/styles.scss +++ /dev/null @@ -1,68 +0,0 @@ -@import '@earn/styles/mixins'; -$status-space-10: $base-unit * 2; -$status-space-20: $base-unit * 4; -$status-space-40: $base-unit * 8; -$gray-color: #a3a3ad; -$green-color: #60c700; -$red-color: #f22f24; - -.status { - font-weight: 700; - display: inline-block; - padding: $base-unit $status-space-10; - border-radius: $status-space-40 0 0 $status-space-40; - text-transform: capitalize; - - &.passed { - background: $tc-orange; - } - - &.failed { - background: $red-color; - } -} - -.screening-status { - background: $tc-gray-50; - border-radius: $status-space-40; - font-weight: 400; - font-size: 13px; - line-height: $status-space-20; - color: $tc-white; - padding: $base-unit $status-space-10; - display: inline-block; - text-transform: initial; - cursor: pointer; - - &.has-warn { - padding: 0 $status-space-10 0 0; - } - - &.pass-with-no-warn { - background: $green-color; - - .status { - padding: 0 $base-unit; - } - } - - &.fail-with-no-warn { - background: $red-color; - - .status { - padding: 0 $base-unit; - } - } - - &.pending { - background: transparent; - font-size: 15px; - color: $gray-color; - font-style: italic; - } -} - -.warning { - padding-left: $status-space-10; - display: inline-block; -} diff --git a/src/apps/earn/src/components/SubmissionManagement/Submission/index.jsx b/src/apps/earn/src/components/SubmissionManagement/Submission/index.jsx deleted file mode 100644 index 367db65b9..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/Submission/index.jsx +++ /dev/null @@ -1,145 +0,0 @@ -/** - * This component receives via props a single submission data object, - * and showScreeningDetails boolean property, which should tell whether - * the Screening Details component should be rendered or not - * (and also to choose the proper orientation of arrow icon). - * - * Also, this component will receive the following callbacks to be triggered - * when user clicks on buttons/icons/links: - * onDelete() (to be triggered by delete icon), - * onDownload() (to be triggered by download icon), - * onShowDetails() (to be triggered by details arrow icon, and also by screening status component). - */ - -import _ from 'lodash'; -import moment from 'moment'; -import { COMPETITION_TRACKS, CHALLENGE_STATUS, safeForDownload } from '@earn/utils/tc'; - -import PT from 'prop-types'; - -import { ReactComponent as DeleteIcon } from '../Icons/IconTrashSimple.svg'; -import { ReactComponent as DownloadIcon } from '../Icons/IconSquareDownload.svg'; -import { ReactComponent as ExpandIcon } from '../Icons/IconMinimalDown.svg'; -import ScreeningStatus from '../ScreeningStatus'; -import { styled as styledCss } from '@earn/utils'; - -import styles from './styles.scss'; -const styled = styledCss(styles); - -export default function Submission(props) { - const { - submissionObject, - showScreeningDetails, - track, - onDownload, - onDelete, - onShowDetails, - status, - allowDelete, - } = props; - const formatDate = date => moment(+new Date(date)).format('MMM DD, YYYY hh:mm A'); - const onDownloadSubmission = onDownload.bind(1, submissionObject.id); - const safeForDownloadCheck = safeForDownload(submissionObject.url); - - return ( - - - ID - {submissionObject.legacySubmissionId} -
{submissionObject.id}
- - - TYPE - {submissionObject.type} - - - Submission Date - {formatDate(submissionObject.created)} - - { - track === COMPETITION_TRACKS.DES && ( - - Screening Status - {safeForDownloadCheck !== true ? safeForDownloadCheck : submissionObject.screening - && ( - - )} - - ) - } - -
- - { /* - TODO: At the moment we just fetch downloads from the legacy - Topcoder Studio API, and we don't need any JS code to this. - It may change soon, as we move to the new TC API for - downloads. Then we'll use this commented out code or - remove it for good. - - */ } - {status !== CHALLENGE_STATUS.COMPLETED - && track === COMPETITION_TRACKS.DES - && safeForDownloadCheck === true && ( - - ) - } - -
- - - ); -} - -Submission.defaultProps = { - submissionObject: {}, - showScreeningDetails: false, - onShowDetails: _.noop, -}; - -Submission.propTypes = { - submissionObject: PT.shape({ - id: PT.string, - legacySubmissionId: PT.string, - warpreviewnings: PT.string, - screening: PT.shape({ - status: PT.string, - }), - submitted: PT.string, - type: PT.string, - created: PT.any, - download: PT.any, - url: PT.string, - }), - showScreeningDetails: PT.bool, - track: PT.string.isRequired, - onDownload: PT.func.isRequired, - onDelete: PT.func.isRequired, - onShowDetails: PT.func, - status: PT.string.isRequired, - allowDelete: PT.bool.isRequired, -}; diff --git a/src/apps/earn/src/components/SubmissionManagement/Submission/styles.scss b/src/apps/earn/src/components/SubmissionManagement/Submission/styles.scss deleted file mode 100644 index 3511c9e26..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/Submission/styles.scss +++ /dev/null @@ -1,202 +0,0 @@ -@import '@earn/styles/mixins'; -$submission-space-10: $base-unit * 2; -$submission-space-20: $base-unit * 4; -$submission-space-25: $base-unit * 5; -$submission-space-50: $base-unit * 10; - -.submission-row { - width: 100%; - font-size: 15px; - color: $tc-black; - font-weight: 400; - - @include xs-to-sm { - display: block; - position: relative; - padding: 10px 0; - } - - td { - // vertical-align: middle; - padding: 16px; - background: $tc-white; - border-top: 1px solid $tc-gray-10; - color: $tc-black; - font-weight: 500; - font-size: 14px; - line-height: 22px; - - .mobile-header { - display: none; - - @include xs-to-md { - display: block; - color: #767676; - font-size: 11px; - line-height: 14px; - text-transform: uppercase; - text-align: left; - justify-content: flex-start; - } - } - - @include xs-to-lg { - padding: $submission-space-10; - } - - @include xs-to-sm { - display: block; - border: none; - } - - &.no-submission { - line-height: $submission-space-20; - padding: $submission-space-50 $submission-space-20; - text-align: center; - } - - &.dev-details { - padding: 16px; - - @include xs-to-md { - padding: 0 10px; - } - } - } - - .preview-col { - @include xs-to-sm { - float: left; - } - - .design-img { - width: 90px; - height: 90px; - - @include xs-to-sm { - width: 80px; - height: 80px; - } - } - - .dev-img { - width: 40px; - height: 40px; - } - } - - .id-col { - font-weight: 700; - width: 32%; - - @include xs-to-sm { - width: 80%; - } - } - - .type-col { - width: 21%; - - @include xs-to-sm { - width: 80%; - } - } - - .date-col { - width: 20%; - color: $tc-black; - font-weight: 500; - font-size: 14px; - line-height: 22px; - - @include xs-to-sm { - padding: 0 10px; - width: 80%; - } - } - - .v5-id { - font-weight: 400; - line-height: 22px; - } - - .status-col { - text-align: center; - - button { - background: none; - border: none; - padding: 0; - - .pending { - text-transform: initial; - font-size: 15px; - color: $tc-gray-40; - line-height: $submission-space-20; - } - } - } - - .action-col { - text-align: center; - min-width: 120px; - - @include xs-to-sm { - position: absolute; - right: 0; - top: 10px; - padding: 10px 0; - min-width: 100px; - text-align: right; - - svg { - width: 14px; - height: 14px; - } - } - - .delete-icon { - margin: 0 0 0 24px; - - @include xs-to-sm { - margin-left: 15px; - } - } - - button { - margin-left: 15px; - margin-top: 3px; - background: none; - border: 0; - font-size: 0; - padding: 0; - line-height: 0; - display: inline-block; - - &:focus { - outline: none; - } - - &:disabled { - opacity: 0.5; - } - } - - .expand-icon { - transition: all 1.5s; - margin-left: 24px; - - @include xs-to-sm { - margin-left: 15px; - } - - &.expanded { - transform: rotate(180deg); - } - } - } - - .status-col button:focus { - outline: none; - } -} diff --git a/src/apps/earn/src/components/SubmissionManagement/SubmissionManagement/index.jsx b/src/apps/earn/src/components/SubmissionManagement/SubmissionManagement/index.jsx deleted file mode 100644 index 897e45451..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/SubmissionManagement/index.jsx +++ /dev/null @@ -1,223 +0,0 @@ -/** - * This component should render the entire page assembly, - * but not yet implement the logic behind user actions. - * It still receives submissions and challenge data, all callbacks, etc. from its parent container - * - * Namely, it receives via props: the mock data object (provided along with this specs), - * the showDetails set, and config object holding all necessary callbacks: - * onBack() - to trigger when user clicks Back button under the challenge name; - * onDelete(submissionId); - * onDownload() (to be triggered by download icon) - * onOpenOnlineReview(submissionId); onHelp(submissionId); - * onShowDetails(submissionId); - * onSubmit() - to trigger when user clicks Add Submission button. - */ - -import _ from 'lodash'; -import PT from 'prop-types'; -import moment from 'moment'; - -import { IconOutline, LinkButton, LoadingCircles } from '~/libs/ui'; -import { phaseEndDate } from '@earn/utils/challenge-listing/helper'; - -import SubmissionsTable from '../SubmissionsTable'; - -import styles from './styles.scss'; - -export default function SubmissionManagement(props) { - const { - challenge, - submissions, - loadingSubmissions, - showDetails, - onDelete, - helpPageUrl, - onDownload, - onShowDetails, - challengeUrl, - onlineReviewUrl, - submissionPhaseStartDate, - } = props; - - const { track } = challenge; - - const challengeType = track.toLowerCase(); - - const isDesign = challengeType === 'design'; - const isDevelop = challengeType === 'development'; - const currentPhase = challenge.phases - .filter(p => p.name !== 'Registration' && p.isOpen) - .sort((a, b) => moment(a.scheduledEndDate).diff(b.scheduledEndDate))[0]; - const submissionPhase = challenge.phases.filter(p => p.name === 'Submission')[0]; - const submissionEndDate = submissionPhase && phaseEndDate(submissionPhase); - - const now = moment(); - const end = moment(currentPhase && currentPhase.scheduledEndDate); - const diff = end.isAfter(now) ? end.diff(now) : 0; - const timeLeft = moment.duration(diff); - - const [days, hours, minutes] = [ - timeLeft.get('days'), - timeLeft.get('hours'), - timeLeft.get('minutes'), - ]; - - const componentConfig = { - helpPageUrl, - onDelete, - onDownload: onDownload.bind(0, challengeType), - onlineReviewUrl, - onShowDetails, - }; - return ( -
-
-
- - -

- {challenge.name} -

-
-
-
-
-

- Manage your submissions -

- - {/* { - isDesign && currentPhase && ( -

- - {currentPhase.name} - {' '} - Ends: - - {' '} - {end.format('dddd MM/DD/YY hh:mm A')} -

- ) - } */} -
-
- { - currentPhase && ( -

- Current Deadline:{' '} - {currentPhase.name} -

- ) - } - - { - challenge.status !== 'Completed' ? ( -
-

- Current Deadline Ends: {' '} - - {days > 0 && (`${days}D`)} - {' '} - {hours} - H - {' '} - {minutes} - M - -

-
- ) : ( -

- The challenge has ended -

- ) - } -
- { - isDesign && ( -

- {/* eslint-disable-next-line max-len */} - We always recommend to download your submission to check you uploaded the correct .zip files  - {/* eslint-disable-next-line max-len */} - and also to verify your declarations file is accurate. If you don’t want to see a submission  - {/* eslint-disable-next-line max-len */} - simply delete it. If you have a new submissions, use the “Add Submission” button to add one  - to the top of the list. -

- ) - } - { - isDevelop && ( -

- {/* eslint-disable-next-line max-len */} - We always recommend to download your submission to check you uploaded the correct .zip files  - {/* eslint-disable-next-line max-len */} - and also to verify your declarations file is accurate. If you don’t want to see a submission  - {/* eslint-disable-next-line max-len */} - simply delete it. If you have a new submissions, use the “Add Submission” button to add one  - to the top of the list. -

- ) - } - {loadingSubmissions && } - {!loadingSubmissions - && ( - - ) - } -
- {now.isBefore(submissionEndDate) && ( -
- - { - (!isDevelop || !submissions || submissions.length === 0) - ? 'Add Submission' : 'Update Submission' - } - -
- )} -
- ); -} - -SubmissionManagement.defaultProps = { - onDelete: _.noop, - onShowDetails: _.noop, - onDownload: _.noop, - onlineReviewUrl: '', - helpPageUrl: '', - loadingSubmissions: false, - challengeUrl: '', - submissions: [], -}; - -SubmissionManagement.propTypes = { - showDetails: PT.shape().isRequired, - onDelete: PT.func, - onlineReviewUrl: PT.string, - helpPageUrl: PT.string, - onDownload: PT.func, - onShowDetails: PT.func, - challenge: PT.shape().isRequired, - submissions: PT.arrayOf(PT.shape()), - loadingSubmissions: PT.bool, - challengeUrl: PT.string, - submissionPhaseStartDate: PT.string.isRequired, -}; diff --git a/src/apps/earn/src/components/SubmissionManagement/SubmissionManagement/styles.scss b/src/apps/earn/src/components/SubmissionManagement/SubmissionManagement/styles.scss deleted file mode 100644 index 8c884499f..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/SubmissionManagement/styles.scss +++ /dev/null @@ -1,286 +0,0 @@ -@import '@earn/styles/mixins'; -$submang-space-140: $base-unit * 28; -$submang-space-50: $base-unit * 10; -$submang-space-35: $base-unit * 7; -$submang-space-30: $base-unit * 6; -$submang-space-25: $base-unit * 5; -$submang-space-20: $base-unit * 4; -$gray-color: $tc-gray-40; -$light-gray-color: $tc-gray-neutral-light; - -.btn-wrap { - display: flex; - justify-content: flex-end; - margin-right: 32px; - margin-top: 34px; - color: white; - - @include xs-to-md { - margin-right: 16px; - margin-top: 32px; - } -} - - -.add-sub-btn-warning { - @include roboto-bold; - - font-weight: 700; - font-size: 16px; - line-height: 24px; - border-radius: 50px !important; - background: $tc-red-70 !important; - color: #fff !important; - text-transform: uppercase; - - @include xs-to-md { - font-size: 14px; - line-height: 20px; - } -} - -.submission-management { - padding-bottom: 40px; -} - -.submission-management-content { - padding: 0 32px; - - @include md { - padding: $submang-space-20 $submang-space-35; - } - - @include xs-to-sm { - padding: 0; - } - - .content-head { - display: flex; - justify-content: space-between; - font-weight: 400; - font-size: 15px; - color: $tc-gray-50; - line-height: $submang-space-25; - margin-top: 36px; - margin-bottom: $base-unit; - - @include xs-to-sm { - flex-direction: column; - margin-top: $submang-space-20; - padding: 0 15px; - } - - .title { - @include barlow-bold; - - font-weight: 600; - font-size: 24px; - color: $tc-black; - line-height: 28px; - text-transform: uppercase; - - @include xs-to-md { - font-size: 20px; - line-height: 22px; - } - } - - .round-ends { - font-size: 15px; - color: $tc-black; - line-height: $submang-space-30; - - @include xs-to-sm { - margin-top: 10px; - margin-bottom: 15px; - } - - span.ends-label { - color: $tc-gray-50; - - @include xs-to-sm { - display: block; - margin-bottom: -10px; - } - } - } - } - - .subTitle { - display: flex; - margin-top: 12px; - - @include xs-to-md { - margin: 17px 16px 0 16px; - flex-direction: column; - } - - .round { - @include roboto-regular; - - font-weight: 400; - font-size: 16px; - line-height: 24px; - color: $tc-black; - - span { - @include roboto-bold; - - font-weight: 700; - } - - @include xs-to-md { - font-size: 14px; - line-height: 20px; - } - } - - .seperator { - width: 2px; - height: 24px; - left: 228px; - top: 0; - background: #d4d4d4; - border-radius: 1px; - margin: 0 16px; - - @include xs-to-md { - display: none; - } - } - } - - .recommend-info { - @include roboto-regular; - - font-size: 16px; - font-weight: 400; - color: $tc-black; - line-height: 24px; - margin-bottom: $submang-space-30; - margin-top: 40px; - - @include xs-to-sm { - padding: 0 15px; - margin-top: 32px; - font-size: 14px; - line-height: 20px; - } - } -} - -.submission-management-header { - display: flex; - justify-content: space-between; - width: 100%; - font-weight: 400; - padding: $submang-space-25 32px 0 32px; - background: #fff; - border-bottom: 1px solid $tc-gray-neutral-dark; - - @include md { - padding: $submang-space-25 $submang-space-35; - } - - @include xs-to-sm { - flex-direction: column; - padding: 9px 16px; - } - - .left-col { - display: flex; - padding-right: 200px; - margin-top: 15px; - margin-bottom: 40px; - - @include xs-to-sm { - padding-right: 0; - display: flex; - flex-direction: column; - } - - .name { - @include barlow-bold; - - font-size: 34px; - color: $tc-black; - line-height: 32px; - font-weight: 600; - margin-left: 16px; - margin-top: -6px; - - @include xs-to-sm { - font-size: 28px; - line-height: 32px; - margin-top: 0; - margin-left: 0; - } - } - - .back-btn { - @include roboto-bold; - - font-weight: 700; - font-size: 16px; - line-height: 24px; - border: 0; - color: #137d60 !important; - width: 32px; - height: 24px; - position: relative; - - @include xs-to-md { - margin-left: 0; - margin-bottom: 8px; - } - - svg { - border: 1.5px solid #137d60; - border-radius: 24px; - - @include xs-to-md { - margin-left: 0; - margin-bottom: 15px; - } - } - } - } - - .right-col { - @include roboto-regular; - - min-width: 100px; - - @include xs-to-sm { - margin-top: 10px; - - p, - div { - display: inline-block; - } - } - - .time-left { - font-size: 20px; - color: $tc-gray-80; - line-height: $submang-space-30; - - @include xs-to-sm { - font-size: 15px; - font-weight: bold; - line-height: $submang-space-25; - margin-left: 5px; - } - } - - .left-label { - font-size: 13px; - color: $tc-gray-50; - line-height: $submang-space-20; - - @include xs-to-sm { - margin-left: 5px; - } - } - } -} diff --git a/src/apps/earn/src/components/SubmissionManagement/SubmissionsTable/index.jsx b/src/apps/earn/src/components/SubmissionManagement/SubmissionsTable/index.jsx deleted file mode 100644 index d55aeb8b9..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/SubmissionsTable/index.jsx +++ /dev/null @@ -1,153 +0,0 @@ -/** - * This component will render the entire assemly of submissions table. - * It receives via props the array of submission data objects; - * a showDetails set with submission IDs for which details panel - * should be shown; and type property (design or develop) to know - * whether the screening status column should be rendered. - * - * Also it will receive a bunch of callbacks which should be properly - * wired to the children components: - * onDelete(submissionId) – to delete specified submission; - * onDownload(submissionId) – to download the specified submission; - * onOpenOnlineReview(submissionId); - * onHelp(submissionId); - * onShowDetails(submissionId). - */ - -import _ from 'lodash'; -import React from 'react'; -import PT from 'prop-types'; -import shortid from 'shortid'; -import moment from 'moment'; -import { COMPETITION_TRACKS } from '@earn/utils/tc'; -import Submission from '../Submission'; -import ScreeningDetails from '../ScreeningDetails'; -import styles from './styles.scss'; - -export default function SubmissionsTable(props) { - const { - submissionObjects, - showDetails, - track, - onDelete, - onlineReviewUrl, - helpPageUrl, - onDownload, - onShowDetails, - status, - submissionPhaseStartDate, - } = props; - - const submissionsWithDetails = []; - if (!submissionObjects || submissionObjects.length === 0) { - submissionsWithDetails.push(( - - - You have no submission uploaded so far. - - - )); - } else { - submissionObjects.forEach((subObject) => { - // submissionPhaseStartDate will be the start date of - // the current submission/checkpoint or empty string if any other phase - const allowDelete = submissionPhaseStartDate - && moment(subObject.submissionDate).isAfter(submissionPhaseStartDate); - - const submission = ( - - ); - submissionsWithDetails.push(submission); - - const submissionDetail = ( - - {showDetails[subObject.id] - && ( - - - - )} - - ); - submissionsWithDetails.push(submissionDetail); - }); - } - - return ( -
- - - - - - - {track === COMPETITION_TRACKS.DES && ( - - )} - - - - - {submissionsWithDetails} - -
- ID - - Type - - Submission Date - - Screening Status - - Actions -
-
- ); -} - -const SubShape = PT.shape({ - id: PT.string, - warpreviewnings: PT.string, - screening: PT.shape({ - status: PT.string, - }), - submitted: PT.string, - track: PT.string, -}); - -SubmissionsTable.defaultProps = { - submissionObjects: [], - onDelete: _.noop, - onDownload: _.noop, - onShowDetails: _.noop, - onlineReviewUrl: '', - helpPageUrl: '', -}; - -SubmissionsTable.propTypes = { - submissionObjects: PT.arrayOf(SubShape), - showDetails: PT.shape().isRequired, - track: PT.string.isRequired, - onDelete: PT.func, - onlineReviewUrl: PT.string, - helpPageUrl: PT.string, - onDownload: PT.func, - onShowDetails: PT.func, - status: PT.string.isRequired, - submissionPhaseStartDate: PT.string.isRequired, -}; diff --git a/src/apps/earn/src/components/SubmissionManagement/SubmissionsTable/styles.scss b/src/apps/earn/src/components/SubmissionManagement/SubmissionsTable/styles.scss deleted file mode 100644 index 498a0fac7..000000000 --- a/src/apps/earn/src/components/SubmissionManagement/SubmissionsTable/styles.scss +++ /dev/null @@ -1,164 +0,0 @@ -@import '@earn/styles/mixins'; -$status-space-10: $base-unit * 2; -$status-space-20: $base-unit * 4; -$status-space-25: $base-unit * 5; -$submission-space-10: $base-unit * 2; -$submission-space-20: $base-unit * 4; -$submission-space-25: $base-unit * 5; -$submission-space-50: $base-unit * 10; - -.submissions-table { - // border: 1px solid $tc-gray-10; - overflow: hidden; - // border-radius: 4px 4px 0 0; - - @include xs-to-sm { - border: none; - border-radius: 0; - border-top: 1px solid $tc-gray-10; - border-bottom: 1px solid $tc-gray-10; - margin: 0 16px; - } - - table { - width: 100%; - - th { - @include barlow-bold; - - font-size: 11px; - color: #767676; - font-weight: 600; - line-height: $status-space-20; - text-align: left; - padding: 0 15px 11px 15px; - text-transform: uppercase; - - &.status, - &.actions { - text-align: center; - } - - @include xs-to-sm { - display: none; - } - } - - .no-submission { - line-height: $submission-space-20; - padding: $submission-space-50 $submission-space-20; - text-align: center; - } - } - - .status-col { - text-align: center; - } - - .action-col { - text-align: center; - } -} - -.submission-row { - width: 100%; - font-size: 15px; - color: $tc-black; - font-weight: 400; - - td { - vertical-align: middle; - padding: 16px 16px 2px 16px; - background: $tc-white; - font-size: 14px; - color: $tc-black; - font-weight: 500; - border-top: 1px solid $tc-gray-10; - line-height: 12px; - - @include xs-to-md { - padding: 16px 16px 2px 8px; - } - - &.no-submission { - line-height: $submission-space-20; - padding: $submission-space-50 $submission-space-20; - text-align: center; - } - - &.dev-details { - padding-right: 60px; - border-top: 0; - padding-top: 0; - } - } - - .id-col { - font-weight: 700; - width: 32%; - } - - .type-col { - width: 21%; - } - - .date-col { - width: 20%; - color: $tc-black; - font-weight: 500; - line-height: 22px; - font-size: 14px; - } - - .status-col { - text-align: center; - - button { - background: none; - border: none; - padding: 0; - - .pending { - text-transform: initial; - font-size: 15px; - color: $tc-gray-40; - line-height: $submission-space-20; - } - } - } - - .action-col { - text-align: center; - - .delete-icon { - margin: 0 $submission-space-25; - } - - button { - background: none; - border: 0; - font-size: 0; - padding: 0; - line-height: 0; - display: inline-block; - margin-left: 15px; - margin-top: 3px; - - &:focus { - outline: none; - } - } - - .expand-icon { - transition: all 1.5s; - - &.expanded { - transform: rotate(180deg); - } - } - } - - .status-col button:focus { - outline: none; - } -} diff --git a/src/apps/earn/src/components/Tag/index.jsx b/src/apps/earn/src/components/Tag/index.jsx deleted file mode 100644 index bdbf35d55..000000000 --- a/src/apps/earn/src/components/Tag/index.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from "react"; -import PT from "prop-types"; - -import styles from "./styles.scss"; - -const Tag = ({ tag, onClick }) => ( - { - onClick(tag); - }} - > - {tag} - -); - -Tag.propTypes = { - tag: PT.string, - onClick: PT.func, -}; - -export default Tag; diff --git a/src/apps/earn/src/components/Tag/styles.scss b/src/apps/earn/src/components/Tag/styles.scss deleted file mode 100644 index 81e4dc9f0..000000000 --- a/src/apps/earn/src/components/Tag/styles.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import "@earn/styles/variables"; - -.tag { - display: inline-block; - padding: 3px 4px 3px 5px; - font-size: $font-size-xs; - line-height: 15px; - letter-spacing: 0.55px; - white-space: nowrap; - border: 1px solid $body-color; - border-radius: $border-radius-sm; - cursor: pointer; -} diff --git a/src/apps/earn/src/components/TagList/index.jsx b/src/apps/earn/src/components/TagList/index.jsx deleted file mode 100644 index 4db83b3eb..000000000 --- a/src/apps/earn/src/components/TagList/index.jsx +++ /dev/null @@ -1,148 +0,0 @@ -import { - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from "react"; -import PT from "prop-types"; - -import { Tooltip } from "~/libs/ui"; - -import styles from "./styles.scss"; - -/** - * Displays a tooltip with tags that are not initially shown. - * - * @param {Object} props component properties - * @returns {JSX.Element} - */ -const TagsTooltip = ({ children, onClickTag, renderTag, tags }) => { - const overlay = useMemo( - () => ( -
- {tags - .map((tag) => ({ - tag, - onClickTag, - className: styles.tooltipTag, - })) - .map(renderTag)} -
- ), - [onClickTag, renderTag, tags] - ); - return ( - - {children} - - ); -}; - -/** - * Displays a tag list. Initially displays only the first line of tags. - * - * @param {Object} props component properties - * @param {string} [props.className] class name added to root element - * @param {number} [props.maxTagCount] maximum number of tags to show - * @param {(t: any) => void} [props.onClickTag] function called when tag is clicked - * @param {(t: any) => JSX.Element} props.renderTag function that renders a tag - * @param {Array} props.tags array of tags - * @returns {JSX.Element} - */ -const TagList = ({ - className, - maxTagCount = 5, - onClickTag, - renderTag, - tags, -}) => { - const [isVisible, setIsVisible] = useState(false); - const [showAll, setShowAll] = useState(false); - const [tagsVisible, setTagsVisible] = useState(tags); - - const containerRef = useRef(); - - const onClickBtnMore = useCallback( - (event) => { - event.preventDefault(); - setTagsVisible(tags); - setShowAll(true); - }, - [tags] - ); - - useEffect(() => { - let index = getFirstLineLastElemIndex(containerRef.current); - index = index < 0 ? maxTagCount : Math.min(index, maxTagCount); - if (tags.length < index + 1) { - setShowAll(true); - setTagsVisible(tags); - } else { - setTagsVisible(tags.slice(0, index)); - } - setIsVisible(true); - }, [tags, maxTagCount]); - - return ( -
- {tagsVisible - .map((tag) => ({ className: styles.tag, onClickTag, tag })) - .map(renderTag)} - {!showAll && ( - - - {tags.length - tagsVisible.length}+ - - - )} -
- ); -}; - -TagList.propTypes = { - className: PT.string, - maxTagCount: PT.number, - onClickTag: PT.func.isRequired, - renderTag: PT.func.isRequired, - tags: PT.arrayOf(PT.object).isRequired, -}; - -export default TagList; - -/** - * Searches for the index of the last element on the first line. - * - * @param {Element} container container element - * @returns {number} first line's last element's index - */ -function getFirstLineLastElemIndex(container) { - const firstElement = container.firstElementChild; - let offsetTop = firstElement.offsetTop; - for ( - let elem = firstElement.nextElementSibling, index = 1; - elem; - elem = elem.nextElementSibling, index++ - ) { - if (elem.offsetTop > offsetTop) { - return index - 1; - } - } - return -1; -} diff --git a/src/apps/earn/src/components/TagList/styles.scss b/src/apps/earn/src/components/TagList/styles.scss deleted file mode 100644 index 5fd9114c1..000000000 --- a/src/apps/earn/src/components/TagList/styles.scss +++ /dev/null @@ -1,56 +0,0 @@ -@import "../../styles/mixins"; -@import "../../styles/variables"; - -.container { - position: relative; - display: flex; - flex-wrap: wrap; - height: 27px; - opacity: 0; - - &.visible { - height: auto; - opacity: 1; - } -} - -.btn-more, -.tag { - margin-top: 4px; - margin-right: 4px; - border: 1px solid $body-color; - border-radius: 5px; - padding: 4px 6px 2px; - font-size: 12px; - line-height: 15px; - cursor: pointer; - - &:last-child { - margin-right: 0; - } -} - -.tooltip-tag-list { - display: flex; - flex-wrap: wrap; - background-color: transparent; -} - -.tooltipTag { - flex: 0 0 auto; - margin-top: 4px; - margin-right: 4px; - border-radius: 5px; - padding: 4px 5px 4px 6px; - @include roboto-regular; - font-size: 11px; - letter-spacing: 0.5px; - line-height: 15px; - color: #fff; - background-color: #555; - cursor: pointer; - - &:last-child { - margin-right: 0; - } -} diff --git a/src/apps/earn/src/components/Terms/TermDetails.jsx b/src/apps/earn/src/components/Terms/TermDetails.jsx deleted file mode 100644 index 8aaff868c..000000000 --- a/src/apps/earn/src/components/Terms/TermDetails.jsx +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Terms details component which display text of an agreement - */ - -import React from "react"; -import PT from "prop-types"; - -import { styled as styledCss } from "@earn/utils"; -import { LoadingCircles } from "~/libs/ui"; - -import styles from "./TermDetails.module.scss"; - -const styled = styledCss(styles); - -export default class TermDetails extends React.Component { - constructor(props) { - super(props); - this.state = { - loadingFrame: false, - }; - this.frameLoaded = this.frameLoaded.bind(this); - } - - componentWillMount() { - const { details, getDocuSignUrl } = this.props; - if ( - details.agreeabilityType !== "Electronically-agreeable" && - details.docusignTemplateId - ) { - getDocuSignUrl(details.docusignTemplateId); - this.setState({ loadingFrame: true }); - } - } - - frameLoaded() { - this.setState({ - loadingFrame: false, - }); - } - - render() { - const { details, docuSignUrl, loadingDocuSignUrl } = this.props; - const { loadingFrame } = this.state; - - return ( -
- {details.agreeabilityType === "Electronically-agreeable" && ( -
-
-
- )} - {details.agreeabilityType !== "Electronically-agreeable" && - details.docusignTemplateId === loadingDocuSignUrl && ( - - )} - {details.agreeabilityType !== "Electronically-agreeable" && - details.docusignTemplateId && - !loadingDocuSignUrl && - docuSignUrl && ( -
- {loadingFrame && } -