diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 000000000..c818c7b00 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +16.15.0 \ No newline at end of file diff --git a/README.md b/README.md index 5fc311e18..44b167472 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,17 @@ The Platform UI is the official Topcoder web app to host all modern user interfa Beginning March, 2022 all future user interfaces at Topcoder will be implemented here. Pre-existing user interfaces will be ported to here over time until this is the only user interface any user sees when interacting with Topcoder. -It is written using React 17, Typescript 4, and Node 16. - -## Serving Locally +- [Local Environment Setup](#local-environment-setup) +- [Deployments](#deployments) +- [Yarn Commands](#yarn-commands) +- [Folder Structure](#folder-structure) +- [Adding a Tool or Util](#adding-a-tool-or-util) +- [Git](#git) +- [Linting](#linting) +- [Styling](#styling) +- [Icons](#icons) + +## Local Environment Setup ### Dependencies - Node @@ -14,53 +22,128 @@ It is written using React 17, Typescript 4, and Node 16. - Typescript - React Scripts -### To Serve +This app uses React 17, Typescript 4, and Node 16. + +### IDE + +Use the [VS Code](https://code.visualstudio.com/download) IDE for MFE development. + +### nvm +Use the node version manager [nvm](https://github.com/nvm-sh/nvm/blob/master/README.md) to easily and safely manage the required version of NodeJS (aka, node). Download and install it per the instructions for your development operating system. Installing a version of node via `nvm` will also install `npm`. + +Once nvm is installed, run: + +>% nvm install + + +At the root of the project directory you'll notice a file called `.nvmrc` which specifies the node version used by the project. The command `nvm use` will use the version specified in the file if no version is supplied on the command line. +See [the nvm Github README](https://github.com/nvm-sh/nvm/blob/master/README.md#nvmrc) for more information on setting this up. + +>**NOTE:** The current node version mentioned in the `.nvmrc` is `16.15.0` + +You can verify the versions of `nvm`, `node`, and `npm` using the commands below. +| Command | Supported Version | +| ----------------- | -------- | +| `% npm -v` | 8.5.5 | +| `% node -v` | v16.15.0 | +| `% nvm --version` | 0.39.1 | +| `% nvm current` | v15.15.0 | + -- Add the local topcoder domain to your hosts file --- 127.0.0.1 local.topcoder-dev.com +### Hosting +You will need to add the following line to your hosts file. The hosts file is normally located at `/etc/hosts` (Mac). Do not overwrite the existing localhost entry also pointing to 127.0.0.1. -- Open a bash shell +``` +127.0.0.1 local.topcoder-dev.com +``` +### Serving -\> git clone https://github.com/topcoder-platform/platform-ui.git +1. Open a bash shell +2. Run the following commands -\> cd platform-ui +>% git clone https://github.com/topcoder-platform/platform-ui.git -\> yarn install +>% cd platform-ui -\> yarn start +>% yarn install -- go to https://local.topcoder-dev.com:3000/ +>% yarn start -*NOTE: SSL is required for authentication, so you must accept the invalid cert.* +3. Go to https://local.topcoder-dev.com:3003/ -### To create a personal config in order to track logs to your local environment +### Local SSL -- Add [hostname] to src/config/app-host-environment.enum.ts -- Copy an existing config from src/config/environment.*.config.ts -- Rename new config environment.[hostname].config.ts -- Rename config variable to EnvironmentConfig[HostName] -- Set the ENV variable to AppHostEnvironment.[hostnama] -- Add the switch case for the host name to src/config/environment.config.ts -- Prior to starting the server, set your host name: -\> export REACT_APP_HOST_ENV=[hostname] +SSL is required for authentication to work properly. + +The `yarn start` command serves the site using the cert and key in the /ssl directory. + +For easier development, it is recommended that you add this certificate to your trusted root authorities and as a trused cert in your browser. Google your browser and OS for more info. + +Otherwise, you will need to override the exception each time you load the site. Firefox users may need to user an incognito browser in order to override the exception. + +### Personal Config + +1. Add [hostname] to src-ts/config/environments/app-host-environment.enum.ts +2. Copy an existing config from src-ts/config/environments/environment.*.config.ts +3. Rename new config environment.[hostname].config.ts +4. Rename config variable to EnvironmentConfig[HostName] +5. Set the ENV variable to AppHostEnvironment.[hostname] +6. Add the switch case for the host name to src-ts/config/environments/environment.config.ts +7. Prior to starting the server, set your host name: +```% export REACT_APP_HOST_ENV=[hostname]``` #### For further convenience -- Copy start-ssl-*.sh -- Rename to start-ssl-[hostname].sh -- Set the REACT_APP_HOST_ENV=[hostname] -- Add "start:[hostname]": "sh start-ssl-[hostname].sh" to scripts in package.json +1. Copy start-ssl-*.sh +2. Rename to start-ssl-[hostname].sh +3. Set the REACT_APP_HOST_ENV=[hostname] +4. Add "start:[hostname]": "sh start-ssl-[hostname].sh" to scripts in package.json + +## Deployments + +The app uses CircleCI for CI/CD. + +The "dev" branch is auto-deployed to the dev environment: https://platform-mvp.topcoder-dev.com. + +The "master" branch is auto-deployed to the production environment: https://platform-mvp.topcoder.com. + +## yarn Commands + +| Command | Description | +| --------------------- | ------------------------------------------------------------------------------------- | +| `yarn start` | Serve dev mode build with the default config | +| `yarn start:` | Serve dev mode build with dev's personal config | +| `yarn build` | Build dev mode build with the default config and outputs static files in /builds | +| `yarn build:prod` | Build prod mode build with the prod config and outputs static files in /builds | +| `yarn lint` | Run tslint against ts/x files and outputs report | +| `yarn lint:fix` | Run tslint against ts/x files, fixes auto-fixable issues, and outputs report | +| `yarn eslint` | Run eslint against js/x files and outputs report | +| `yarn eslint:fix` | Run eslint against js/x files, fixes auto-fixable issues, and outputs report | +| `yarn test` | Run unit tests, watching for changes and re-running per your specifications | +| `yarn test:no-watch` | Run unit tests once, without watching for changes or re-running | -## Developing +## Folder Structure -The following descriptions correspond to the top-level directories within the -src directory. +The folder structure of the app has the following goals: -### config +- Hierarchy represents dependence +- Limit nesting +- Limit the number of folders w/in a given parent +- Easy to find items (familiar to React engineers) +- Short names +- Ubiquitous language -Definitions of configurations for a specific host environment. +### /src & /src-ts -### header +The Work Tool is currently migrating from javascript to typescript. That's why in the root of the repository there are two source folders(`src` and `src-ts`). + +>**NOTE:** All work should be done in the /src-ts directory unless expressly instructed otherwise. + +### /src-ts/config + +Definitions of configurations for a specific host environment. See the [Personal Config](#personal-config) section for further info. + +### /src-ts/header Defines the entire header panel of the UI: @@ -68,10 +151,7 @@ Defines the entire header panel of the UI: - Tool Selectors - Utility Selectors -// TODO: Search - - -### lib +### /src-ts/lib Shared code that should be stable and should not be modified unless expressly intending to modify the *entire* Platform UI. @@ -80,70 +160,295 @@ When using items in this directory, there are only 3 permissable locations from which to import: .ts or tsx: -- /lib +- /src-ts/lib .tsx -- /lib/styles/index.scss +- /src-ts/lib/styles/index.scss .scss -- /lib/styles +- /src-ts/lib/styles/includes +- /src-ts/lib/styles/typography +- /src-ts/lib/styles/variables -// TODO: more info about what exists in the lib +See the [Styling](#styling) section for more details about stylesheets -### tools +### /src-ts/tools The majority of development should happen in subdirectories of the tools directory. -The Tool Selectors correlate 1:1 to directories within the tools directory. +The Tool Selectors on the site [Header](#src-tsheader) correlate 1:1 to directories within the tools directory. The name of a tool's directory should correlate w/the name of the tool and its url. -I.e. src/tools/[tool-name] == platform.topcoder.com/[tool-name] +``` +i.e. /src-ts/tools/[tool-name] == platform.topcoder.com/[tool-name] +e.g. /src-ts/tools/work == platform.topcoder.com/work +``` -E.g. src/tools/self-service == platform.topcoder.com/self-service +>**NOTE:** Tools should not import modules from any directories other than lib. If it is necessary to import from outside the lib, the shared code should generally be moved to lib. -Tools should generally not import modules from any directories other than lib. +### /src-ts/utils -If it is necessary to import from outside the lib, the shared code should -generally be moved to lib. +This directory includes shared utilities that are not specific to a tool (e.g. Profile Settings.) -#### Adding a Tool to the Tool Selectors +The Utility Selectors in the site [Header](#src-tsheader) correlate 1:1 to directories within the utils directory. -All of the routes for a tool, including root, section, and subsections should be -defined in a top-level file. +The name of a util's directory should correlate w/the name of the util and its url. -I.e. [toolName]Routes in src/tools/[tool-name]/[tool-name].routes.ts +``` +i.e. /src-ts/utils/[util-name] == platform.topcoder.com/[util-name] +e.g. /src-ts/utils/profile == platform.topcoder.com/profile +``` -E.g. selfServiceRoutes in src/tools/self-service/self-service.routes.ts +>**NOTE:** Utils should not import modules from any directories other than lib. If it is necessary to import from outside the lib, the shared code should generally be moved to lib. -These routes then need to be added to the src/tools/tools.routes.ts file, -at which time the tool selectors should automatically be updatd. +## Adding a Tool or Util -### utils +All of the routes for a given tool or util (including root, section, and subsection routes) should be +defined in a top-level file in the tool/util folder. -Shared utilities that are not specific to a tool. +``` +i.e. [toolName]Routes in /src-ts/tools/[tool-name]/[tool-name].routes.ts +i.e. [utilName]Routes in src-ts/utils/[util-name]/[util-name].routes.ts -The Utility Selectors correlate 1:1 to directories within the utils directory. +e.g. workRoutes in /src-ts/tools/work/work.routes.tsx +e.g. settingsRoutes in src-ts/tools/settings/settings.routes.tsx +``` -The name of a util's directory should correlate w/the name of the util and its url. +These routes then need to be added to the routes file for the parent tools/utils: + +``` +/src-ts/tools/tools.routes.ts +/src-ts/utils/utils.routes.ts +``` + +Simply adding the routes to one of thes files above will register the tool/util +with the application and will display the new component. + +### Platform Route + +The PlatformRoute model has several useful options: + +| property | description | +| ---------------- | ---------------------------------------- | +| `children: Array` | The children property defines subsections that will inherit the url path from the parent. | +| `element: JSX.Element` | The element property is the JSX element that should appear at the specified URL. | +| `disabled?: boolean` | When a route is marked as disabled, it will not be registered and will the URL will return a 404. | +| `hide?: boolean` | When a route is hidden, it will be registered and the URL will be available through deep-linking but will not be visible in either the Tools or Utils Selectors. This is useful for handling redirects for obsolete routes. | +| `requireAuth?: boolean` | Requiring authentication for a route means that users who are not logged in will be redirected to the Login Form when they try to access the route. | +| `route: string` | The route property is the path to the route, relative to its parent(s). | +| `title: string` | The title property is the text that will appear in the Tools or Utils Selectors (this is irrelevant on hidden routes). | + +## Git + +### Branching +When working on Jira tickets, we link associated Git PRs and branches to the tickets. Use the following naming convention for branches: + +`[TICKET #]_short-description` + +e.g.: `PROD-1516_work-issue` + +#### Branching strategy +TBD + +### Commits +We use [Smart Commits](https://bigbrassband.com/git-integration-for-jira/documentation/smart-commits.html#bbb-nav-basic-examples) to link comments and time tracking to tickets. You would enter the following as your commit message: + +`[TICKET #] #comment #time ` + +e.g.: `PROD-001 #comment adding readme notes #time 45m` + + +## Linting + +### Rules +While [TSLint](https://palantir.github.io/tslint/) is technically deprecated in favor of [Typescript ESLint](https://typescript-eslint.io/), TSLint is still far better at linting Typescript files than ESLint. So, for the time being, TSLint will be the primary linter, but ESLint remains configured for JS/X files. + +The following command will install TSLint globally: + +>% yarn global add tslint typescript + +### Command Line + +#### View All Lint Errors + +>% yarn lint + +#### Fix All Auto-fixable and View All Non-fixable Lint Errors + +>% yarn lint:fix + +OR + +>% yarn eslint:fix + +### VS Code + +VS Code has several plugins and settings that make linting easy. + +#### Format on Save + +The most useful feature is to automatically apply all lint rules any time you save a file. + +1) Code → Preferences → Settings + +2) Search for “save” to find the setting + - Editor: Code Actions on Save + +3) Click the “Edit in settings.json” link + +4) Add the following config: + ``` + { + ... + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll.tslint": true, + }, + } + ``` + +#### TSLint Plugin + +Created by Microsoft, this plugin will allow you to see lint errors in the Problems panel. + +>**WARNING:** Other lint plugins can interfere with TSLint, so it is recommended that you uninstall/disable all other lint plugins (e.g. ESLint, Prettier, etc). + +## Styling + +We use [Sass](https://sass-lang.com/) for styling, which is a preprocessor scripting language that compiles to CSS and allows for the use of variables, nested rules, mixins, functions, etc. + +**Variables** can be used to store any CSS value that you want to reuse throughout your stylesheets. Variables are prefixed with the $ symbol. + +e.g. styles.scss +``` +$primary-color: #333; + +body { + color: $primary-color; +} +``` + +**Mixins** let you create groups of CSS declarations that you want to reuse throughout your site. You can also pass in values to make your mixin more flexible, and you call them using `@include`. + +e.g. styles.scss +``` +@mixin theme($theme: DarkGray) { + background: $theme; + color: #fff; +} + +.info { + @include theme; +} +.alert { + @include theme($theme: DarkRed); +} +``` + +Shared stylesheets are located in `src-ts/lib/styles/`. We use variables and mixins for handling padding, colors and breakpoints in the application, among others. To reference these in your SCSS files, simply add the following line at the top of your file. + +``` +@import '[path to]/lib/styles/includes'; +@import '[path to]/lib/styles/typography'; +@import '[path to]/lib/styles/variables'; +``` + +### Colors & Gradients + +Colors and Gradients are defined as variables in `src-ts/lib/styles/_palette.scss`. + +>**WARNING:** Do not use any colors that are not already defined in the palette. If a mockup you are working from has a different color, find the color in the palette that is closest. + +### Padding + +Padding for various screen sizes are defined as variables in `src-ts/lib/styles/_layout.scss`. This file also contains a mixin called `pagePaddings` that determines the correct padding to use for the current screen size based on breakpoints. + +### Breakpoints + +Breakpoint mixins are defined in `src-ts/lib/styles/_breakpoints.scss` and can be used to apply different styling based on the screen width. + +Here is an example that applies a different height value than the default to a css class selector if the screen is considered small (376px - 464px). + +_breakpoints.scss +``` +$sm-min: 376px; +$sm-max: 464px; + +@mixin sm { + @media (min-width: #{$sm-min}) and (max-width: #{$sm-max}){ + @content; + } +} +``` -I.e. src/utils/[util-name] == platform.topcoder.com/[util-name] +example.scss +``` +@import '../lib/styles'; -E.g. src/utils/profile == platform.topcoder.com/profile +.example { + height: 100px; + @include sm { + height: 50px; + } +} +``` +>**WARNING:** Do not add any breakpoints! -Utils should generally not import modules from any directories other than lib. +## Icons -If it is necessary to import from outside the lib, the shared code should -generally be moved to lib. +### Heroicons +We use the SVG icons library [Heroicons](https://heroicons.com/), where each icon is available in an `outline` or `solid` version. -#### Adding a Util to the Util Selectors +We import both sets of icons in the file `src-ts/lib/svgs/index.ts`. +``` +import * as IconOutline from '@heroicons/react/outline' +import * as IconSolid from '@heroicons/react/solid' +``` -All of the routes for a util, including root, section, and subsections should be -defined in a top-level file. +Then, to use an icon from either of these sets, you would import the corresponding set into your JSX file and reference the icon of your choice as a component: -I.e. [utilName]Routes in src/utils/[util-name]/[util-name].routes.ts +e.g.: +``` + +``` -E.g. homeRoutes in src/tools/home/home.routes.ts +### Custom SVGs +Custom SVGs can also be imported and used directly as a React component. Save your SVG in its own index (i.e. "barrel" file within your tool (e.g. /src-ts/tools/my-tool/my-tool/lib/svgs), and then import the SVG into the barrel file as a component: +``` +import { ReactComponent as CustomSVG } from './customSvg.svg' +``` + +The export the svg from the barrel file to be used w/in your tool: +``` +export { CustomSVG } +``` +See the /src-ts/lib/svgs for an example. + +>**NOTE:** Custom SVGs should be saved w/in a given tool. Only global SVGs should be in the main /lib/svgs directory. + +### Styling Icons + +You can style an SVG icon by overwritting its properties through CSS (height, width, fill, etc.). +There are also existing mixins located in `src-ts/lib/styles/_icons.scss` with pre-defined widths and heights for various icon sizes. + +e.g.: +``` +.logo-link { + svg { + width: calc($pad-xxl + $pad-xxxxl); + height: $pad-xl; + fill: none; + + path { + fill: $tc-white; + } + } +} -These routes then need to be added to the src/utils/utils.routes.ts file, -at which time the tool selectors should automatically be updated. \ No newline at end of file +.no-logo-link { + svg { + @include icon-lg; + } +} +``` diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 000000000..cd5b145c6 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,70 @@ +module.exports = function (api) { + const isProd = process.env.APPMODE === "production"; + api.cache(!isProd); + + const generateScopedName = isProd + ? "[hash:base64:6]" + : "self_service_[path][name]___[local]___[hash:base64:6]"; + return { + presets: ["@babel/preset-env", "@babel/preset-react"], + plugins: [ + [ + "@babel/plugin-transform-runtime", + { + useESModules: true, + regenerator: false, + }, + ], + [ + "react-css-modules", + { + filetypes: { + ".scss": { + syntax: "postcss-scss", + }, + }, + generateScopedName, + }, + ], + [ + "inline-react-svg", + { + "svgo": { + "plugins": [ + { + "cleanupIDs": false + } + ] + } + } + ], + ], + env: { + test: { + presets: [ + [ + "@babel/preset-env", + { + targets: "current node", + }, + ], + ], + plugins: [ + [ + "module-resolver", + { + alias: { + styles: "./src/styles", + components: "./src/components", + hooks: "./src/hooks", + utils: "./src/utils", + constants: "./src/constants", + services: "./src/services", + }, + }, + ], + ], + }, + }, + }; +}; diff --git a/build-dev.sh b/build-dev.sh index 0534e4be0..3785e177f 100644 --- a/build-dev.sh +++ b/build-dev.sh @@ -1,2 +1,2 @@ export REACT_APP_HOST_ENV=dev -yarn react-scripts build +yarn react-app-rewired build diff --git a/build-prod.sh b/build-prod.sh index 207f2033f..d2af5746f 100644 --- a/build-prod.sh +++ b/build-prod.sh @@ -1,2 +1,2 @@ export REACT_APP_HOST_ENV=prod -yarn react-scripts build +yarn react-app-rewired build diff --git a/config-overrides.js b/config-overrides.js new file mode 100644 index 000000000..75f62850f --- /dev/null +++ b/config-overrides.js @@ -0,0 +1,3 @@ +const { removeModuleScopePlugin } = require('customize-cra') + +module.exports = removeModuleScopePlugin() diff --git a/config/dev.js b/config/dev.js new file mode 100644 index 000000000..99a848249 --- /dev/null +++ b/config/dev.js @@ -0,0 +1,38 @@ +module.exports = { + /** + * URL of Topcoder Community Website + */ + TOPCODER_COMMUNITY_WEBSITE_URL: "https://topcoder-dev.com", + TERMS_URL: + "https://www.topcoder-dev.com/challenges/terms/detail/317cd8f9-d66c-4f2a-8774-63c612d99cd4", + PRIVACY_POLICY_URL: "https://www.topcoder-dev.com/policy", + SIGN_IN_URL: `https://accounts-auth0.topcoder-dev.com/?retUrl=https%3A%2F%2Fplatform.topcoder-dev.com%2Fself-service%2Fwizard®Source=selfService`, + SIGN_UP_URL: `https://accounts-auth0.topcoder-dev.com/?retUrl=https%3A%2F%2Fplatform.topcoder-dev.com%2Fself-service%2Fwizard®Source=selfService&mode=signUp`, + /** + * URL of Topcoder Connect Website + */ + CONNECT_WEBSITE_URL: "https://connect.topcoder-dev.com", + VANILLA_EMBED_JS: "https://vanilla.topcoder-dev.com/js/embed.js", + VANILLA_EMBED_TYPE: "mfe", + VANILLA_FORUM_API: "https://vanilla.topcoder-dev.com/api/v2", + VANILLA_ACCESS_TOKEN: "va.JApNvUOx3549h20I6tnl1kOQDc75NDIp.0jG3dA.EE3gZgV", + + API: { + V5: "https://api.topcoder-dev.com/v5", + V3: "https://api.topcoder-dev.com/v3", + }, + + STRIPE: { + API_KEY: "pk_test_rfcS49MHRVUKomQ9JgSH7Xqz", + API_VERSION: "2020-08-27", + CUSTOMER_TOKEN: + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJUb3Bjb2RlciBVc2VyIl0sImlzcyI6Imh0dHBzOi8vYXBpLnRvcGNvZGVyLWRldi5jb20iLCJoYW5kbGUiOiJ0ZXN0MSIsImV4cCI6MjU2MzA3NjY4OSwidXNlcklkIjoiNDAwNTEzMzMiLCJpYXQiOjE0NjMwNzYwODksImVtYWlsIjoidGVzdEB0b3Bjb2Rlci5jb20iLCJqdGkiOiJiMzNiNzdjZC1iNTJlLTQwZmUtODM3ZS1iZWI4ZTBhZTZhNGEifQ.jl6Lp_friVNwEP8nfsfmL-vrQFzOFp2IfM_HC7AwGcg", + ADMIN_TOKEN: + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJUb3Bjb2RlciBVc2VyIiwiYWRtaW5pc3RyYXRvciJdLCJpc3MiOiJodHRwczovL2FwaS50b3Bjb2Rlci1kZXYuY29tIiwiaGFuZGxlIjoidGVzdDEiLCJleHAiOjI1NjMwNzY2ODksInVzZXJJZCI6IjQwMDUxMzMzIiwiaWF0IjoxNDYzMDc2MDg5LCJlbWFpbCI6InRlc3RAdG9wY29kZXIuY29tIiwianRpIjoiYjMzYjc3Y2QtYjUyZS00MGZlLTgzN2UtYmViOGUwYWU2YTRhIn0.wKWUe0-SaiFVN-VR_-GwgFlvWaDkSbc8H55ktb9LAVw", + }, + /** + * Expire time period of auto saved intake form: 24 hours + */ + AUTO_SAVED_COOKIE_EXPIRED_IN: 24 * 60, + TIME_ZONE: "Europe/London", +}; diff --git a/config/index.js b/config/index.js new file mode 100644 index 000000000..4cbf464b5 --- /dev/null +++ b/config/index.js @@ -0,0 +1,14 @@ +/* global process */ + +module.exports = (() => { + const env = process.env.APPENV || "dev"; + + console.info(`APPENV: "${env}"`); + + // for security reason don't let to require any arbitrary file defined in process.env + if (["prod", "dev"].indexOf(env) < 0) { + return require("./dev"); + } + + return require("./" + env); +})(); diff --git a/config/local.js b/config/local.js new file mode 100644 index 000000000..7af0bba50 --- /dev/null +++ b/config/local.js @@ -0,0 +1,3 @@ +module.exports = { + COMMUNITY_ADMIN_URL: "", +}; diff --git a/config/prod.js b/config/prod.js new file mode 100644 index 000000000..ff5d082bc --- /dev/null +++ b/config/prod.js @@ -0,0 +1,39 @@ +module.exports = { + /** + * URL of Topcoder Community Website + */ + TOPCODER_COMMUNITY_WEBSITE_URL: "https://topcoder.com", + TERMS_URL: + "https://www.topcoder.com/challenges/terms/detail/564a981e-6840-4a5c-894e-d5ad22e9cd6f", + PRIVACY_POLICY_URL: "https://www.topcoder.com/policy", + SIGN_IN_URL: `https://accounts-auth0.topcoder.com/?retUrl=https%3A%2F%2Fplatform.topcoder.com%2Fself-service%2Fwizard®Source=selfService`, + SIGN_UP_URL: `https://accounts-auth0.topcoder.com/?retUrl=https%3A%2F%2Fplatform.topcoder.com%2Fself-service%2Fwizard®Source=selfService&mode=signUp`, + + /** + * URL of Topcoder Connect Website + */ + CONNECT_WEBSITE_URL: "https://connect.topcoder.com", + VANILLA_EMBED_JS: "https://discussions.topcoder.com/js/embed.js", + VANILLA_EMBED_TYPE: "standard", + VANILLA_FORUM_API: "https://vanilla.topcoder.com/api/v2", + VANILLA_ACCESS_TOKEN: "va.JApNvUOx3549h20I6tnl1kOQDc75NDIp.0jG3dA.EE3gZgV", + + API: { + V5: "https://api.topcoder.com/v5", + V3: "https://api.topcoder.com/v3", + }, + + STRIPE: { + API_KEY: "pk_live_m3bCBVSfkfMOEp3unZFRsHXi", + API_VERSION: "2020-08-27", + CUSTOMER_TOKEN: + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJUb3Bjb2RlciBVc2VyIl0sImlzcyI6Imh0dHBzOi8vYXBpLnRvcGNvZGVyLWRldi5jb20iLCJoYW5kbGUiOiJ0ZXN0MSIsImV4cCI6MjU2MzA3NjY4OSwidXNlcklkIjoiNDAwNTEzMzMiLCJpYXQiOjE0NjMwNzYwODksImVtYWlsIjoidGVzdEB0b3Bjb2Rlci5jb20iLCJqdGkiOiJiMzNiNzdjZC1iNTJlLTQwZmUtODM3ZS1iZWI4ZTBhZTZhNGEifQ.jl6Lp_friVNwEP8nfsfmL-vrQFzOFp2IfM_HC7AwGcg", + ADMIN_TOKEN: + "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJUb3Bjb2RlciBVc2VyIiwiYWRtaW5pc3RyYXRvciJdLCJpc3MiOiJodHRwczovL2FwaS50b3Bjb2Rlci1kZXYuY29tIiwiaGFuZGxlIjoidGVzdDEiLCJleHAiOjI1NjMwNzY2ODksInVzZXJJZCI6IjQwMDUxMzMzIiwiaWF0IjoxNDYzMDc2MDg5LCJlbWFpbCI6InRlc3RAdG9wY29kZXIuY29tIiwianRpIjoiYjMzYjc3Y2QtYjUyZS00MGZlLTgzN2UtYmViOGUwYWU2YTRhIn0.wKWUe0-SaiFVN-VR_-GwgFlvWaDkSbc8H55ktb9LAVw", + }, + /** + * Expire time period of auto saved intake form: 24 hours + */ + AUTO_SAVED_COOKIE_EXPIRED_IN: 24 * 60, + TIME_ZONE: "Europe/London", +}; diff --git a/package.json b/package.json index d39f28664..0317b2c88 100644 --- a/package.json +++ b/package.json @@ -2,35 +2,114 @@ "name": "@topcoder-platform/platform-ui", "version": "0.1.0", "private": true, + "scripts": { + "start": "sh start-ssl.sh", + "start:bsouza": "sh start-ssl-bsouza.sh", + "build": "sh build-dev.sh", + "build:prod": "sh build-prod.sh", + "lint": "tslint 'src-ts/**/*.{ts,tsx}'", + "lint:fix": "tslint 'src-ts/**/*.{ts,tsx}' --fix", + "eslint": "eslint 'src/**/*.{js,jsx}'", + "eslint:fix": "eslint 'src/**/*.{js,jsx}' --fix", + "test": "react-scripts test --watchAll", + "test:no-watch": "react-scripts test --watchAll=false --passWithNoTests" + }, "dependencies": { "@datadog/browser-logs": "^4.5.0", "@heroicons/react": "^1.0.6", + "apexcharts": "^3.35.3", "axios": "^0.26.1", "browser-cookies": "^1.2.0", "classnames": "^2.3.1", + "crypto-js": "^4.1.1", + "lodash": "^4.17.21", + "moment": "^2.29.3", + "moment-timezone": "^0.5.34", + "prop-types": "^15.8.1", + "rc-checkbox": "^2.3.2", "react": "^17.0.2", + "react-apexcharts": "^1.4.0", "react-dom": "^17.0.2", + "react-elastic-carousel": "^0.11.5", "react-gtm-module": "^2.0.11", + "react-redux": "^8.0.2", + "react-redux-toastr": "^7.6.8", "react-responsive-modal": "^6.2.0", "react-router-dom": "^6.2.1", "react-scripts": "5.0.0", + "react-select": "^5.3.2", + "react-spinners": "^0.13.1", "react-toastify": "^8.2.0", + "react-tooltip": "^4.2.21", + "redux": "^4.2.0", + "redux-logger": "^3.0.6", + "redux-promise-middleware": "^6.1.2", + "redux-thunk": "^2.4.1", "sass": "^1.49.8", + "styled-components": "^5.3.5", "tc-auth-lib": "topcoder-platform/tc-auth-lib#1.0.3", "typescript": "^4.4.2", + "uuid": "^8.3.2", "web-vitals": "^2.1.0" }, - "scripts": { - "start": "sh start-ssl.sh", - "start:bsouza": "sh start-ssl-bsouza.sh", - "build": "react-scripts build", - "build:dev": "sh build-dev.sh", - "build:prod": "sh build-prod.sh", - "eject": "react-scripts eject", - "lint": "tslint src/**/*.{ts,tsx}", - "lint:fix": "tslint src/**/*.{ts,tsx} --fix", - "test": "react-scripts test", - "test:no-watch": "npm test -- --watchAll=false" + "devDependencies": { + "@babel/core": "^7.7.5", + "@babel/plugin-syntax-jsx": "^7.17.12", + "@babel/plugin-transform-runtime": "^7.8.3", + "@babel/preset-env": "^7.7.6", + "@babel/preset-react": "^7.7.4", + "@babel/preset-typescript": "^7.16.7", + "@babel/runtime": "^7.8.7", + "@stripe/react-stripe-js": "1.7.2", + "@stripe/stripe-js": "1.29.0", + "@testing-library/jest-dom": "^5.14.1", + "@testing-library/react": "^12.0.0", + "@testing-library/user-event": "^13.2.1", + "@types/axios": "^0.14.0", + "@types/jest": "^27.0.1", + "@types/lodash": "^4.14.182", + "@types/node": "^16.7.13", + "@types/reach__router": "^1.3.10", + "@types/react": "^17.0.20", + "@types/react-dom": "^17.0.9", + "@types/react-gtm-module": "^2.0.1", + "@types/react-redux-toastr": "^7.6.2", + "@types/react-router-dom": "^5.3.3", + "@types/systemjs": "^6.1.0", + "autoprefixer": "^9.8.6", + "babel-eslint": "^11.0.0-beta.2", + "babel-jest": "^24.9.0", + "babel-plugin-inline-react-svg": "^1.1.2", + "babel-plugin-module-resolver": "^4.0.0", + "babel-plugin-react-css-modules": "^5.2.6", + "concurrently": "^5.0.1", + "config": "^3.3.6", + "cross-env": "^7.0.2", + "customize-cra": "^1.0.0", + "eslint": "^8.18.0", + "eslint-config-prettier": "^6.7.0", + "eslint-config-react-app": "^7.0.1", + "eslint-config-react-important-stuff": "^2.0.0", + "eslint-plugin-prettier": "^3.1.1", + "file-loader": "^6.2.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^25.2.7", + "jest-cli": "^25.2.7", + "postcss-loader": "^4.0.4", + "postcss-scss": "^3.0.2", + "prettier": "^2.0.4", + "pretty-quick": "^2.0.1", + "react-app-rewired": "^2.2.1", + "resolve-url-loader": "^3.1.2", + "sass": "^1.48.0", + "sass-loader": "^10.0.5", + "style-loader": "^2.0.0", + "systemjs-webpack-interop": "^2.1.2", + "webpack": "^4.41.2", + "webpack-cli": "^3.3.10", + "webpack-config-single-spa-react": "^1.0.3", + "webpack-dev-server": "^3.9.0", + "webpack-merge": "^4.2.2" }, "eslintConfig": { "extends": [ @@ -53,17 +132,5 @@ "last 1 safari version" ] }, - "devDependencies": { - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^12.0.0", - "@testing-library/user-event": "^13.2.1", - "@types/axios": "^0.14.0", - "@types/jest": "^27.0.1", - "@types/node": "^16.7.13", - "@types/react": "^17.0.20", - "@types/react-dom": "^17.0.9", - "@types/react-gtm-module": "^2.0.1", - "@types/react-router-dom": "^5.3.3" - }, "types": "./types/index.d.ts" } diff --git a/public/global.css b/public/global.css new file mode 100644 index 000000000..cbe37a3b9 --- /dev/null +++ b/public/global.css @@ -0,0 +1,61 @@ +@import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"); +@import url("https://fonts.googleapis.com/css2?family=Barlow+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"); +@import url('https://fonts.googleapis.com/css2?family=Barlow:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); + +body { + background-color: #f4f5f6; + font-family: Roboto, Arial, Helvetica, sans-serif; + margin: 0; + padding: 0; +} + +/* Eric Meyer's "Reset CSS" 2.0 */ + +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} \ No newline at end of file diff --git a/public/index.html b/public/index.html index 3376e76cd..59b04f059 100644 --- a/public/index.html +++ b/public/index.html @@ -8,9 +8,11 @@ + +