Skip to content

Commit 68a32ee

Browse files
authored
Merge pull request #1423 from topcoder-platform/Oct_2022_Release
Oct 2022 release
2 parents e695f7d + 0be5404 commit 68a32ee

File tree

10 files changed

+125
-24
lines changed

10 files changed

+125
-24
lines changed

.circleci/config.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ workflows:
150150
context : org-global
151151
filters: &filters-dev
152152
branches:
153-
only: ['develop']
153+
only: ['develop', 'Oct_2022_Release']
154154

155155
# Production builds are exectuted only on tagged commits to the
156156
# master branch.

config/constants/development.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module.exports = {
55
ACCOUNTS_APP_CONNECTOR_URL: `https://accounts-auth0.${DOMAIN}`,
66
ACCOUNTS_APP_LOGIN_URL: `https://accounts-auth0.${DOMAIN}`,
77
COMMUNITY_APP_URL: `https://www.${DOMAIN}`,
8-
MEMBER_API_URL: `${DEV_API_HOSTNAME}/v4/members`,
8+
MEMBER_API_URL: `${DEV_API_HOSTNAME}/v5/members`,
99
MEMBER_API_V3_URL: `${DEV_API_HOSTNAME}/v3/members`,
1010
CHALLENGE_API_URL: `${DEV_API_HOSTNAME}/v5/challenges`,
1111
CHALLENGE_TIMELINE_TEMPLATES_URL: `${DEV_API_HOSTNAME}/v5/timeline-templates`,
@@ -34,6 +34,7 @@ module.exports = {
3434
DS_TRACK_ID: 'c0f5d461-8219-4c14-878a-c3a3f356466d',
3535
QA_TRACK_ID: '36e6a8d0-7e1e-4608-a673-64279d99c115',
3636
CHALLENGE_TYPE_ID: '927abff4-7af9-4145-8ba1-577c16e64e2e',
37+
MARATHON_TYPE_ID: '929bc408-9cf2-4b3e-ba71-adfbf693046c',
3738
SEGMENT_API_KEY: 'QBtLgV8vCiuRX1lDikbMjcoe9aCHkF6n',
3839
CREATE_FORUM_TYPE_IDS: ['927abff4-7af9-4145-8ba1-577c16e64e2e', 'dc876fa4-ef2d-4eee-b701-b555fcc6544c', 'ecd58c69-238f-43a4-a4bb-d172719b9f31'],
3940
FILE_PICKER_API_KEY: process.env.FILE_PICKER_API_KEY,

config/constants/production.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module.exports = {
55
ACCOUNTS_APP_CONNECTOR_URL: process.env.ACCOUNTS_APP_CONNECTOR_URL || `https://accounts-auth0.${DOMAIN}`,
66
ACCOUNTS_APP_LOGIN_URL: `https://accounts-auth0.${DOMAIN}`,
77
COMMUNITY_APP_URL: `https://www.${DOMAIN}`,
8-
MEMBER_API_URL: `${PROD_API_HOSTNAME}/v4/members`,
8+
MEMBER_API_URL: `${PROD_API_HOSTNAME}/v5/members`,
99
MEMBER_API_V3_URL: `${PROD_API_HOSTNAME}/v3/members`,
1010
CHALLENGE_API_URL: `${PROD_API_HOSTNAME}/v5/challenges`,
1111
CHALLENGE_TIMELINE_TEMPLATES_URL: `${PROD_API_HOSTNAME}/v5/timeline-templates`,
@@ -34,6 +34,7 @@ module.exports = {
3434
DS_TRACK_ID: 'c0f5d461-8219-4c14-878a-c3a3f356466d',
3535
QA_TRACK_ID: '36e6a8d0-7e1e-4608-a673-64279d99c115',
3636
CHALLENGE_TYPE_ID: '927abff4-7af9-4145-8ba1-577c16e64e2e',
37+
MARATHON_TYPE_ID: '929bc408-9cf2-4b3e-ba71-adfbf693046c',
3738
SEGMENT_API_KEY: 'QSQAW5BWmZfLoKFNRgNKaqHvLDLJoGqF',
3839
CREATE_FORUM_TYPE_IDS: ['927abff4-7af9-4145-8ba1-577c16e64e2e', 'dc876fa4-ef2d-4eee-b701-b555fcc6544c', 'ecd58c69-238f-43a4-a4bb-d172719b9f31'],
3940
FILE_PICKER_API_KEY: process.env.FILE_PICKER_API_KEY,

src/components/ChallengeEditor/ChallengeView/index.js

+16-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,12 @@ import AssignedMemberField from '../AssignedMember-Field'
2020
import { getResourceRoleByName } from '../../../util/tc'
2121
import { isBetaMode } from '../../../util/cookie'
2222
import { loadGroupDetails } from '../../../actions/challenges'
23-
import { REVIEW_TYPES, CONNECT_APP_URL, PHASE_PRODUCT_CHALLENGE_ID_FIELD } from '../../../config/constants'
23+
import {
24+
REVIEW_TYPES,
25+
CONNECT_APP_URL,
26+
PHASE_PRODUCT_CHALLENGE_ID_FIELD,
27+
DS_TRACK_ID
28+
} from '../../../config/constants'
2429
import PhaseInput from '../../PhaseInput'
2530

2631
const ChallengeView = ({
@@ -91,6 +96,9 @@ const ChallengeView = ({
9196
const showTimeline = false // disables the timeline for time being https://github.com/topcoder-platform/challenge-engine-ui/issues/706
9297
const isTask = _.get(challenge, 'task.isTask', false)
9398
const phases = _.get(challenge, 'phases', [])
99+
const isDataScience = challenge.trackId === DS_TRACK_ID
100+
const useDashboardData = _.find(challenge.metadata, { name: 'show_data_dashboard' })
101+
const useDashboard = useDashboardData ? useDashboardData.value : true
94102

95103
return (
96104
<div className={styles.wrapper}>
@@ -133,6 +141,13 @@ const ChallengeView = ({
133141
<span><span className={styles.fieldTitle}>Challenge Name:</span> {challenge.name}</span>
134142
</div>
135143
</div>
144+
{isDataScience && (
145+
<div className={cn(styles.row, styles.topRow)}>
146+
<div className={styles.col}>
147+
<span><span className={styles.fieldTitle}>Show data dashboard:</span> {useDashboard ? 'Yes' : 'No'}</span>
148+
</div>
149+
</div>
150+
)}
136151
{isTask &&
137152
<AssignedMemberField challenge={challenge} assignedMemberDetails={assignedMemberDetails} readOnly />}
138153
<CopilotField challenge={{

src/components/ChallengeEditor/Type-Field/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import cn from 'classnames'
66
import styles from './Type-Field.module.scss'
77

88
const TypeField = ({ types, onUpdateSelect, challenge, disabled }) => {
9+
types = _.sortBy(types, ['name'])
910
return (
1011
<>
1112
<div className={styles.row}>

src/components/ChallengeEditor/index.js

+69-10
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@ import {
2020
MESSAGE,
2121
COMMUNITY_APP_URL,
2222
DES_TRACK_ID,
23+
DEV_TRACK_ID,
2324
CHALLENGE_TYPE_ID,
25+
MARATHON_TYPE_ID,
2426
REVIEW_TYPES,
2527
MILESTONE_STATUS,
2628
PHASE_PRODUCT_CHALLENGE_ID_FIELD,
27-
QA_TRACK_ID
29+
QA_TRACK_ID,
30+
DS_TRACK_ID
2831
} from '../../config/constants'
2932
import { PrimaryButton, OutlineButton } from '../Buttons'
3033
import TrackField from './Track-Field'
@@ -594,6 +597,8 @@ class ChallengeEditor extends Component {
594597
submissionLimit.count = ''
595598
}
596599
existingMetadata.value = JSON.stringify(submissionLimit)
600+
} else if (existingMetadata.name === 'show_data_dashboard') {
601+
existingMetadata.value = Boolean(value)
597602
} else {
598603
existingMetadata.value = `${value}`
599604
}
@@ -945,17 +950,14 @@ class ChallengeEditor extends Component {
945950
async createNewChallenge () {
946951
if (!this.props.isNew) return
947952
const { metadata, createChallenge, projectDetail } = this.props
948-
const { showDesignChallengeWarningModel, challenge: { name, trackId, typeId, milestoneId } } = this.state
953+
const { challenge: { name, trackId, typeId, milestoneId, challengeType, metadata: challengeMetadata } } = this.state
949954
const { timelineTemplates } = metadata
950955
const isDesignChallenge = trackId === DES_TRACK_ID
956+
const isDataScience = trackId === DS_TRACK_ID
951957
const isChallengeType = typeId === CHALLENGE_TYPE_ID
952-
953-
if (!showDesignChallengeWarningModel && isDesignChallenge && isChallengeType) {
954-
this.setState({
955-
showDesignChallengeWarningModel: true
956-
})
957-
return
958-
}
958+
const isDevChallenge = trackId === DEV_TRACK_ID
959+
const isMM = typeId === MARATHON_TYPE_ID
960+
const showDashBoard = (isDataScience && isChallengeType) || (isDevChallenge && isMM)
959961

960962
// indicate that creating process has started
961963
this.setState({ isSaving: true })
@@ -967,6 +969,10 @@ class ChallengeEditor extends Component {
967969
const defaultTemplate = avlTemplates && avlTemplates.length > 0 ? avlTemplates[0] : STD_DEV_TIMELINE_TEMPLATE
968970
const isTask = _.find(metadata.challengeTypes, { id: typeId, isTask: true })
969971
const tags = trackId === QA_TRACK_ID ? ['QA'] : []
972+
if (challengeType) {
973+
tags.push(challengeType)
974+
}
975+
let timelineTemplateId = defaultTemplate.id
970976

971977
const newChallenge = {
972978
status: 'New',
@@ -979,7 +985,7 @@ class ChallengeEditor extends Component {
979985
reviewType: isTask || isDesignChallenge ? REVIEW_TYPES.INTERNAL : REVIEW_TYPES.COMMUNITY
980986
},
981987
descriptionFormat: 'markdown',
982-
timelineTemplateId: defaultTemplate.id,
988+
timelineTemplateId,
983989
terms: [{ id: DEFAULT_TERM_UUID, roleId: SUBMITTER_ROLE_UUID }],
984990
groups: [],
985991
milestoneId,
@@ -1006,6 +1012,16 @@ class ChallengeEditor extends Component {
10061012
newChallenge.discussions = discussions
10071013
}
10081014
}
1015+
if (showDashBoard) {
1016+
if (!newChallenge.metadata) {
1017+
newChallenge.metadata = []
1018+
}
1019+
let useDashboard = _.find(challengeMetadata, { name: 'show_data_dashboard' })
1020+
if (useDashboard === undefined) {
1021+
useDashboard = { name: 'show_data_dashboard', value: true }
1022+
}
1023+
newChallenge.metadata.push(useDashboard)
1024+
}
10091025
try {
10101026
const action = await createChallenge(newChallenge, projectDetail.id)
10111027
if (isTask) {
@@ -1544,13 +1560,38 @@ class ChallengeEditor extends Component {
15441560
const currentChallengeId = this.getCurrentChallengeId()
15451561
const showTimeline = false // disables the timeline for time being https://github.com/topcoder-platform/challenge-engine-ui/issues/706
15461562
const copilotResources = metadata.members || challengeResources
1563+
const isDevChallenge = challenge.trackId === DEV_TRACK_ID
1564+
const isMM = challenge.typeId === MARATHON_TYPE_ID
1565+
const isChallengeType = challenge.typeId === CHALLENGE_TYPE_ID
1566+
const showDashBoard = (challenge.trackId === DS_TRACK_ID && isChallengeType) || (isDevChallenge && isMM)
1567+
const useDashboardData = _.find(challenge.metadata, { name: 'show_data_dashboard' })
1568+
const useDashboard = useDashboardData ? useDashboardData.value : true
1569+
15471570
const challengeForm = isNew
15481571
? (
15491572
<form name='challenge-new-form' noValidate autoComplete='off' onSubmit={this.createChallengeHandler}>
15501573
<div className={styles.newFormContainer}>
15511574
<TrackField tracks={metadata.challengeTracks} challenge={challenge} onUpdateOthers={this.onUpdateOthers} />
15521575
<TypeField types={metadata.challengeTypes} onUpdateSelect={this.onUpdateSelect} challenge={challenge} />
15531576
<ChallengeNameField challenge={challenge} onUpdateInput={this.onUpdateInput} />
1577+
{
1578+
showDashBoard && (
1579+
<div className={styles.row}>
1580+
<div className={cn(styles.field, styles.col1)}>
1581+
<label htmlFor='isDashboardEnabled'>Use data dashboard :</label>
1582+
</div>
1583+
<div className={cn(styles.field, styles.col2)}>
1584+
<input
1585+
name='isDashboardEnabled'
1586+
type='checkbox'
1587+
id='isDashboardEnabled'
1588+
checked={useDashboard}
1589+
onChange={(e) => this.onUpdateMetadata('show_data_dashboard', e.target.checked)}
1590+
/>
1591+
</div>
1592+
</div>
1593+
)
1594+
}
15541595
{projectDetail.version === 'v4' && <MilestoneField milestones={activeProjectMilestones} onUpdateSelect={this.onUpdateSelect} projectId={projectDetail.id} selectedMilestoneId={selectedMilestoneId} />}
15551596
{useTask && (<DiscussionField hasForum={hasForum} toggleForum={this.toggleForumOnCreate} />)}
15561597
</div>
@@ -1584,6 +1625,24 @@ class ChallengeEditor extends Component {
15841625
</div>
15851626

15861627
<ChallengeNameField challenge={challenge} onUpdateInput={this.onUpdateInput} />
1628+
{
1629+
showDashBoard && (
1630+
<div className={styles.row}>
1631+
<div className={cn(styles.field, styles.col1)}>
1632+
<label htmlFor='isDashboardEnabled'>Use data dashboard :</label>
1633+
</div>
1634+
<div className={cn(styles.field, styles.col2)}>
1635+
<input
1636+
name='isDashboardEnabled'
1637+
type='checkbox'
1638+
id='isDashboardEnabled'
1639+
checked={useDashboard}
1640+
onChange={(e) => this.onUpdateMetadata('show_data_dashboard', e.target.checked)}
1641+
/>
1642+
</div>
1643+
</div>
1644+
)
1645+
}
15871646
{isTask && (
15881647
<AssignedMemberField
15891648
challenge={challenge}

src/components/ChallengesComponent/ChallengeList/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ class ChallengeList extends Component {
178178
<div className={styles.row}>
179179
{!isBillingAccountLoading && !isBillingAccountLoadingFailed && !isBillingAccountExpired && (
180180
<div className={'col-9'}>
181-
<span className={styles.title}>Billing Account: </span><span className={styles.active}>{activeProject.status}</span> &nbsp; <span className={styles.title}>Start Date:</span> {billingStartDate} &nbsp; <span className={styles.title}>End Date:</span> {billingEndDate}
181+
<span className={styles.title}>Billing Account: </span><span className={styles.active}>ACTIVE</span> &nbsp; <span className={styles.title}>Start Date:</span> {billingStartDate} &nbsp; <span className={styles.title}>End Date:</span> {billingEndDate}
182182
</div>
183183
)}
184184
{!isBillingAccountLoading && !isBillingAccountLoadingFailed && isBillingAccountExpired && (

src/components/SelectUserAutocomplete/index.js

+12-8
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import React, { useState, useCallback } from 'react'
88
import PropTypes from 'prop-types'
99
import Select from '../Select'
10-
import { suggestProfiles } from '../../services/user'
10+
import { suggestProfilesV5, fetchProfileV5 } from '../../services/user'
1111
import _ from 'lodash'
1212
import { AUTOCOMPLETE_MIN_LENGTH, AUTOCOMPLETE_DEBOUNCE_TIME_MS } from '../../config/constants'
1313

@@ -27,13 +27,17 @@ export default function SelectUserAutocomplete (props) {
2727
return
2828
}
2929

30-
suggestProfiles(inputValue).then((suggestions) => {
31-
const suggestedOptions = suggestions.map((user) => ({
32-
label: user.handle,
33-
value: user.userId.toString()
34-
}))
35-
setOptions(suggestedOptions)
36-
})
30+
Promise.all([suggestProfilesV5(inputValue), fetchProfileV5(inputValue)]).then(
31+
([suggestions, user]) => {
32+
const suggestedOptions = suggestions.map((u) => ({
33+
label: u.handle,
34+
value: u.userId.toString()
35+
}))
36+
if (user && !_.find(suggestions, u => u.userId === user.userId)) {
37+
suggestedOptions.push({ label: user.handle, value: user.userId.toString() })
38+
}
39+
setOptions(suggestedOptions)
40+
})
3741
}, AUTOCOMPLETE_DEBOUNCE_TIME_MS), []) // debounce, to reduce API calling rate
3842

3943
return (

src/config/constants.js

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const {
1717
DS_TRACK_ID,
1818
QA_TRACK_ID,
1919
CHALLENGE_TYPE_ID,
20+
MARATHON_TYPE_ID,
2021
SEGMENT_API_KEY
2122
} = process.env
2223
export const CREATE_FORUM_TYPE_IDS = typeof process.env.CREATE_FORUM_TYPE_IDS === 'string' ? process.env.CREATE_FORUM_TYPE_IDS.split(',') : process.env.CREATE_FORUM_TYPE_IDS

src/services/user.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import _ from 'lodash'
22
import { axiosInstance } from './axiosWithAuth'
3-
const { MEMBER_API_V3_URL } = process.env
3+
const { MEMBER_API_URL, MEMBER_API_V3_URL } = process.env
44

55
/**
66
* Api request for fetching user profile
@@ -11,6 +11,16 @@ export async function fetchProfile (handle) {
1111
return _.get(response, 'data.result.content')
1212
}
1313

14+
/**
15+
* Api request for fetching user profile v5
16+
* @returns {Promise<*>}
17+
*/
18+
export async function fetchProfileV5 (handle) {
19+
const response = await axiosInstance.get(`${MEMBER_API_URL}?handle=${handle}`)
20+
const data = _.get(response, 'data')
21+
return data.length ? data[0] : undefined
22+
}
23+
1424
/**
1525
* Api request for fetching user profile
1626
* @returns {Promise<*>}
@@ -49,3 +59,12 @@ export async function suggestProfiles (partialHandle) {
4959
const response = await axiosInstance.get(`${MEMBER_API_V3_URL}/_suggest/${encodeURIComponent(partialHandle)}`)
5060
return _.get(response, 'data.result.content')
5161
}
62+
63+
/**
64+
* Api request for finding (suggesting) users by the part of the handle
65+
* @returns {Promise<*>}
66+
*/
67+
export async function suggestProfilesV5 (partialHandle) {
68+
const response = await axiosInstance.get(`${MEMBER_API_URL}/autocomplete?term=${encodeURIComponent(partialHandle)}`)
69+
return _.get(response, 'data')
70+
}

0 commit comments

Comments
 (0)