Skip to content

Commit d336b8f

Browse files
committed
Merge remote-tracking branch 'origin' into TCA-505-reduce-js-bundle-size
2 parents 65710be + 65c3edf commit d336b8f

File tree

55 files changed

+3250
-4918
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+3250
-4918
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ All future user interfaces at Topcoder will be implemented here. Pre-existing us
3434
- Typescript
3535
- React Scripts
3636

37-
This app uses React 17, Typescript 4, and Node 16.
37+
This app uses React 18, Typescript 4, and Node 16.
3838

3939
### IDE
4040

package.json

Lines changed: 80 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -21,122 +21,127 @@
2121
"report:coverage:text": "nyc report --reporter=text"
2222
},
2323
"dependencies": {
24-
"@datadog/browser-logs": "^4.7.1",
24+
"@datadog/browser-logs": "^4.21.2",
2525
"@heroicons/react": "^1.0.6",
26-
"apexcharts": "^3.35.3",
27-
"axios": "^0.26.1",
26+
"apexcharts": "^3.36.0",
27+
"axios": "^1.1.2",
2828
"browser-cookies": "^1.2.0",
29-
"classnames": "^2.3.1",
30-
"contentful": "^9.1.33",
29+
"classnames": "^2.3.2",
30+
"contentful": "^9.2.5",
3131
"crypto-js": "^4.1.1",
3232
"customize-cra": "^1.0.0",
33-
"dompurify": "^2.3.10",
33+
"dompurify": "^2.4.0",
3434
"highlight.js": "^11.6.0",
3535
"html2canvas": "^1.4.1",
3636
"lodash": "^4.17.21",
37-
"marked": "4.0.3",
38-
"moment": "^2.29.3",
39-
"moment-timezone": "^0.5.34",
37+
"markdown-it": "^13.0.1",
38+
"marked": "4.1.1",
39+
"moment": "^2.29.4",
40+
"moment-timezone": "^0.5.37",
4041
"prop-types": "^15.8.1",
42+
"qs": "^6.11.0",
4143
"rc-checkbox": "^2.3.2",
42-
"react": "^17.0.2",
44+
"react": "^18.2.0",
4345
"react-apexcharts": "^1.4.0",
4446
"react-app-rewired": "^2.2.1",
45-
"react-dom": "^17.0.2",
47+
"react-contenteditable": "^3.3.6",
48+
"react-dom": "^18.2.0",
4649
"react-elastic-carousel": "^0.11.5",
4750
"react-gtm-module": "^2.0.11",
48-
"react-redux": "^8.0.2",
49-
"react-redux-toastr": "^7.6.8",
51+
"react-redux": "^8.0.4",
52+
"react-redux-toastr": "^7.6.10",
5053
"react-responsive-modal": "^6.2.0",
51-
"react-router-dom": "^6.2.1",
52-
"react-scripts": "5.0.0",
53-
"react-select": "^5.3.2",
54-
"react-spinners": "^0.13.1",
55-
"react-toastify": "^8.2.0",
56-
"react-tooltip": "^4.2.21",
54+
"react-router-dom": "^6.4.2",
55+
"react-scripts": "5.0.1",
56+
"react-select": "^5.5.0",
57+
"react-spinners": "^0.13.6",
58+
"react-toastify": "^9.0.8",
59+
"react-tooltip": "^4.4.0",
5760
"redux": "^4.2.0",
5861
"redux-logger": "^3.0.6",
59-
"redux-promise-middleware": "^6.1.2",
62+
"redux-promise-middleware": "^6.1.3",
6063
"redux-thunk": "^2.4.1",
61-
"sass": "^1.49.8",
62-
"styled-components": "^5.3.5",
64+
"sanitize-html": "^2.7.2",
65+
"sass": "^1.55.0",
66+
"styled-components": "^5.3.6",
6367
"swr": "^1.3.0",
64-
"tc-auth-lib": "topcoder-platform/tc-auth-lib#1.0.4",
65-
"typescript": "^4.6.3",
66-
"uuid": "^8.3.2"
68+
"tc-auth-lib": "topcoder-platform/tc-auth-lib#1.0.26",
69+
"typescript": "^4.8.4",
70+
"uuid": "^9.0.0"
6771
},
6872
"devDependencies": {
69-
"@babel/core": "^7.7.5",
70-
"@babel/plugin-syntax-jsx": "^7.17.12",
71-
"@babel/plugin-transform-runtime": "^7.8.3",
72-
"@babel/preset-env": "^7.7.6",
73-
"@babel/preset-react": "^7.7.4",
74-
"@babel/preset-typescript": "^7.16.7",
75-
"@babel/runtime": "^7.8.7",
73+
"@babel/core": "^7.19.3",
74+
"@babel/plugin-syntax-jsx": "^7.18.6",
75+
"@babel/plugin-transform-runtime": "^7.19.1",
76+
"@babel/preset-env": "^7.19.4",
77+
"@babel/preset-react": "^7.18.6",
78+
"@babel/preset-typescript": "^7.18.6",
79+
"@babel/runtime": "^7.19.4",
7680
"@cypress/code-coverage": "^3.10.0",
77-
"@stripe/react-stripe-js": "1.7.2",
78-
"@stripe/stripe-js": "1.29.0",
79-
"@testing-library/jest-dom": "^5.14.1",
80-
"@testing-library/react": "^12.0.0",
81-
"@testing-library/user-event": "^13.2.1",
81+
"@stripe/react-stripe-js": "1.13.0",
82+
"@stripe/stripe-js": "1.41.0",
83+
"@testing-library/jest-dom": "^5.16.5",
84+
"@testing-library/react": "^13.4.0",
85+
"@testing-library/user-event": "^14.4.3",
8286
"@types/axios": "^0.14.0",
8387
"@types/cypress": "^1.1.3",
84-
"@types/dompurify": "^2.3.3",
88+
"@types/dompurify": "^2.3.4",
8589
"@types/highlightjs": "^9.12.2",
86-
"@types/jest": "^27.0.1",
87-
"@types/lodash": "^4.14.182",
88-
"@types/marked": "4.0.3",
89-
"@types/node": "^18.7.13",
90-
"@types/reach__router": "^1.3.10",
91-
"@types/react": "^18.0.5",
92-
"@types/react-dom": "^18.0.1",
90+
"@types/jest": "^29.1.2",
91+
"@types/lodash": "^4.14.186",
92+
"@types/markdown-it": "^12.2.3",
93+
"@types/marked": "4.0.7",
94+
"@types/node": "^18.8.5",
95+
"@types/reach__router": "^1.3.11",
96+
"@types/react": "^18.0.21",
97+
"@types/react-dom": "^18.0.6",
9398
"@types/react-gtm-module": "^2.0.1",
9499
"@types/react-redux-toastr": "^7.6.2",
95100
"@types/react-router-dom": "^5.3.3",
101+
"@types/sanitize-html": "^2.6.2",
96102
"@types/segment-analytics": "^0.0.34",
97-
"@types/systemjs": "^6.1.0",
103+
"@types/systemjs": "^6.1.1",
98104
"@types/uuid": "^8.3.4",
99-
"@wdio/junit-reporter": "^7.24.0",
100-
"autoprefixer": "^9.8.6",
105+
"@wdio/junit-reporter": "^7.25.1",
106+
"autoprefixer": "^10.4.12",
101107
"babel-eslint": "^11.0.0-beta.2",
102-
"babel-jest": "^24.9.0",
103-
"babel-plugin-inline-react-svg": "^1.1.2",
104-
"babel-plugin-module-resolver": "^4.0.0",
108+
"babel-jest": "^29.2.0",
109+
"babel-plugin-inline-react-svg": "^2.0.1",
110+
"babel-plugin-module-resolver": "^4.1.0",
105111
"babel-plugin-react-css-modules": "^5.2.6",
106-
"concurrently": "^5.0.1",
107-
"config": "^3.3.6",
108-
"cross-env": "^7.0.2",
109-
"cypress": "^10.6.0",
110-
"eslint": "^8.18.0",
111-
"eslint-config-prettier": "^6.7.0",
112+
"concurrently": "^7.4.0",
113+
"config": "^3.3.8",
114+
"cross-env": "^7.0.3",
115+
"cypress": "^10.10.0",
116+
"eslint": "^8.25.0",
117+
"eslint-config-prettier": "^8.5.0",
112118
"eslint-config-react-app": "^7.0.1",
113-
"eslint-config-react-important-stuff": "^2.0.0",
119+
"eslint-config-react-important-stuff": "^3.0.0",
114120
"eslint-plugin-cypress": "^2.12.1",
115-
"eslint-plugin-prettier": "^3.1.1",
121+
"eslint-plugin-prettier": "^4.2.1",
116122
"file-loader": "^6.2.0",
117-
"husky": "^8.0.0",
123+
"husky": "^8.0.1",
118124
"identity-obj-proxy": "^3.0.0",
119125
"istanbul-lib-coverage": "^3.2.0",
120-
"jest": "^25.2.7",
121-
"jest-cli": "^25.2.7",
126+
"jest": "^29.2.0",
127+
"jest-cli": "^29.2.0",
122128
"lint-staged": "^13.0.3",
123129
"nyc": "^15.1.0",
124-
"postcss-loader": "^4.0.4",
125-
"postcss-scss": "^3.0.2",
126-
"prettier": "^2.0.4",
127-
"pretty-quick": "^2.0.1",
128-
"resolve-url-loader": "^3.1.2",
129-
"sass-loader": "^10.0.5",
130+
"postcss-loader": "^7.0.1",
131+
"postcss-scss": "^4.0.5",
132+
"prettier": "^2.7.1",
133+
"pretty-quick": "^3.1.3",
134+
"resolve-url-loader": "^5.0.0",
135+
"sass-loader": "^13.1.0",
130136
"serve": "^14.0.1",
131137
"start-server-and-test": "^1.14.0",
132-
"style-loader": "^2.0.0",
133-
"systemjs-webpack-interop": "^2.1.2",
138+
"style-loader": "^3.3.1",
139+
"systemjs-webpack-interop": "^2.3.7",
134140
"tslint": "^6.1.3",
135-
"webpack": "^4.41.2",
136-
"webpack-cli": "^3.3.10",
137-
"webpack-config-single-spa-react": "^1.0.3",
138-
"webpack-dev-server": "^3.9.0",
139-
"webpack-merge": "^4.2.2"
141+
"webpack-cli": "^4.10.0",
142+
"webpack-config-single-spa-react": "^4.0.3",
143+
"webpack-dev-server": "^4.11.1",
144+
"webpack-merge": "^5.8.0"
140145
},
141146
"eslintConfig": {
142147
"extends": [

src-ts/lib/functions/xhr-functions/xhr.functions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ function interceptError(instance: AxiosInstance): void {
7474

7575
// if there is server error message, then return it inside `message` property of error
7676
error.message = error?.response?.data?.message || error.message
77+
// if there is server errors data, then return it inside `errors` property of error
78+
error.errors = error?.response?.data?.errors
7779

7880
return Promise.reject(error)
7981
}

src-ts/lib/loading-spinner/LoadingSpinner.module.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,8 @@
2121
&.show {
2222
opacity: 1;
2323
}
24+
&.overlay {
25+
position: fixed;
26+
background: $white-100-opacity-10;
27+
}
2428
}

src-ts/lib/loading-spinner/LoadingSpinner.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,25 @@ import { PuffLoader } from 'react-spinners'
99

1010
import styles from './LoadingSpinner.module.scss'
1111

12+
// This will determine whether we want to show the loading indicator on top of existing content or if its shown
13+
// without any content
14+
type LoadingSpinnerType = 'Overlay' | 'Normal'
15+
1216
export interface LoadingSpinnerProps {
1317
className?: string
1418
hide?: boolean
19+
type?: LoadingSpinnerType
1520
}
1621

17-
const LoadingSpinner: FC<LoadingSpinnerProps> = ({ hide, className }: LoadingSpinnerProps) => {
22+
const LoadingSpinner: FC<LoadingSpinnerProps> = ({ hide, className, type = 'Normal' }: LoadingSpinnerProps) => {
1823

1924
if (!!hide) {
2025
return <></>
2126
}
2227

28+
const isOverlay: boolean = type === 'Overlay'
2329
return (
24-
<div className={classNames(styles['loading-spinner'], styles.show, className)}>
30+
<div className={classNames(styles['loading-spinner'], styles.show, {[styles.overlay]: isOverlay}, className)}>
2531
<PuffLoader color={'#2196f3'} loading={true} size={100} />
2632
</div>
2733
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import "../styles/variables/palette";
2+
3+
.memberSelect {
4+
color: $black-60;
5+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { FC, FocusEvent } from 'react'
2+
import { MultiValue, StylesConfig } from 'react-select'
3+
// tslint:disable-next-line: no-submodule-imports
4+
import AsyncSelect from 'react-select/async'
5+
6+
import { InputWrapper } from '../form/form-groups/form-input/input-wrapper'
7+
8+
import { membersAutocompete, MembersAutocompeteResult } from './input-handle-functions'
9+
import styles from './InputHandleAutocomplete.module.scss'
10+
11+
export interface InputHandleAutocompleteProps {
12+
readonly className?: string
13+
readonly dirty?: boolean
14+
readonly disabled?: boolean
15+
readonly error?: string
16+
readonly hideInlineErrors?: boolean
17+
readonly hint?: string
18+
readonly label?: string | JSX.Element
19+
readonly name: string
20+
readonly onBlur?: (event: FocusEvent<HTMLInputElement>) => void
21+
readonly onChange: (newValue: Array<MembersAutocompeteResult>) => void
22+
readonly placeholder?: string
23+
readonly tabIndex: number
24+
readonly value?: Array<MembersAutocompeteResult>
25+
}
26+
27+
const InputHandleAutocomplete: FC<InputHandleAutocompleteProps> = (props: InputHandleAutocompleteProps) => {
28+
const customStyles: StylesConfig<any> = {
29+
control: (provided) => ({
30+
...provided,
31+
border: 'none',
32+
}),
33+
input: (provided) => ({
34+
...provided,
35+
color: 'inherit',
36+
fontSize: 16,
37+
}),
38+
multiValue: (provided) => ({
39+
...provided,
40+
borderRadius: 50,
41+
}),
42+
multiValueLabel: (provided) => ({
43+
...provided,
44+
fontSize: 12,
45+
}),
46+
option: (provided) => ({
47+
...provided,
48+
borderBottom: '1px solid #E9E9E9',
49+
color: 'inherit',
50+
fontSize: 16,
51+
fontWeight: 400,
52+
padding: 16,
53+
}),
54+
placeholder: (provided) => ({
55+
...provided,
56+
color: 'inherit',
57+
fontSize: 16,
58+
fontWeight: 400,
59+
}),
60+
valueContainer: (provided) => ({
61+
...provided,
62+
padding: 0,
63+
}),
64+
}
65+
66+
return (
67+
<InputWrapper
68+
{...props}
69+
dirty={!!props.dirty}
70+
disabled={!!props.disabled}
71+
label={props.label || props.name}
72+
hideInlineErrors={props.hideInlineErrors}
73+
type='text'
74+
>
75+
<AsyncSelect
76+
className={styles.memberSelect}
77+
cacheOptions
78+
getOptionLabel={({ handle }) => handle}
79+
getOptionValue={({ userId }) => userId}
80+
isMulti
81+
key={props.value?.length}
82+
loadOptions={membersAutocompete}
83+
styles={customStyles}
84+
placeholder={props.placeholder}
85+
onBlur={props.onBlur}
86+
onChange={(newValue: MultiValue<MembersAutocompeteResult>) => props.onChange(newValue as Array<MembersAutocompeteResult>)}
87+
value={props.value}
88+
isDisabled={props.disabled}
89+
/>
90+
</InputWrapper>
91+
)
92+
}
93+
94+
export default InputHandleAutocomplete
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as InputHandleAutocomplete } from './InputHandleAutocomplete'
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import qs from 'qs'
2+
3+
import { xhrGetAsync } from '..'
4+
import { EnvironmentConfig } from '../../config'
5+
6+
export interface MembersAutocompeteQuery {
7+
term: string
8+
}
9+
10+
export interface MembersAutocompeteResult {
11+
firstName: string
12+
handle: string
13+
lastName: string
14+
userId: string
15+
}
16+
17+
export async function membersAutocompete(term: string): Promise<Array<MembersAutocompeteResult>> {
18+
const query: MembersAutocompeteQuery = {
19+
term,
20+
}
21+
22+
return xhrGetAsync(`${EnvironmentConfig.API.V5}/members/autocomplete?${qs.stringify(query)}`)
23+
}

0 commit comments

Comments
 (0)