Skip to content

Commit 06bad4c

Browse files
authored
Merge pull request #341 from topcoder-platform/gamification
Gamification Sprint 4 - deploy for QA
2 parents adb9dd6 + 1a4198a commit 06bad4c

31 files changed

+983
-24
lines changed

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,17 @@
3434
"highlight.js": "^11.6.0",
3535
"html2canvas": "^1.4.1",
3636
"lodash": "^4.17.21",
37+
"markdown-it": "^13.0.1",
3738
"marked": "4.0.3",
3839
"moment": "^2.29.3",
3940
"moment-timezone": "^0.5.34",
4041
"prop-types": "^15.8.1",
42+
"qs": "^6.11.0",
4143
"rc-checkbox": "^2.3.2",
4244
"react": "^17.0.2",
4345
"react-apexcharts": "^1.4.0",
4446
"react-app-rewired": "^2.2.1",
47+
"react-contenteditable": "^3.3.6",
4548
"react-dom": "^17.0.2",
4649
"react-elastic-carousel": "^0.11.5",
4750
"react-gtm-module": "^2.0.11",
@@ -85,6 +88,7 @@
8588
"@types/highlightjs": "^9.12.2",
8689
"@types/jest": "^27.0.1",
8790
"@types/lodash": "^4.14.182",
91+
"@types/markdown-it": "^12.2.3",
8892
"@types/marked": "4.0.3",
8993
"@types/node": "^18.7.13",
9094
"@types/reach__router": "^1.3.10",

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
}
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+
}

src-ts/tools/gamification-admin/game-config/gamification-config.model.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export interface GamificationConfigModel {
22
ACCEPTED_BADGE_MIME_TYPES: string
3+
CSV_HEADER: Array<string>,
34
MAX_BADGE_IMAGE_FILE_SIZE: number
45
ORG_ID: string
56
PAGE_SIZE: number

src-ts/tools/gamification-admin/game-config/gamification.default.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { GamificationConfigModel } from './gamification-config.model'
22

33
export const GamificationConfigDefault: GamificationConfigModel = {
44
ACCEPTED_BADGE_MIME_TYPES: 'image/svg+xml,image/svg',
5+
CSV_HEADER: ['tc_handle', 'badge_id'],
56
MAX_BADGE_IMAGE_FILE_SIZE: 5000000, // 5mb in bytes
67
ORG_ID: '6052dd9b-ea80-494b-b258-edd1331e27a3',
78
PAGE_SIZE: 12,

src-ts/tools/gamification-admin/game-lib/game-badge.model.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,11 @@ export interface GameBadge {
66
badge_name: string
77
badge_status: string
88
id: string
9+
member_badges?: Array<{
10+
awarded_at: string,
11+
awarded_by: string,
12+
user_handle: string,
13+
user_id: string,
14+
}>
915
organization_id: string
1016
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './game-badge.model'
22
export * from './use-get-game-badges-page.hook'
33
export * from './use-gamification-breadcrumb.hook'
4+
export * from './use-get-game-badge-details.hook'

0 commit comments

Comments
 (0)