From 9adc5876a217254cee1f8130ab12e1813ce1d90c Mon Sep 17 00:00:00 2001
From: maxceem
Date: Sat, 12 Dec 2020 16:50:11 +0200
Subject: [PATCH 01/23] chore: deploy 'feature/taas-jobs-2'
---
.circleci/config.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 897301638..e9b9fb9e5 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -128,7 +128,7 @@ workflows:
- build-dev
filters:
branches:
- only: ['dev']
+ only: ['dev', 'feature/taas-jobs-2']
- deployTest01:
context : org-global
From 478debac3cd87db98a56ee51ada9f23ea09c8839 Mon Sep 17 00:00:00 2001
From: Vigneshkumar Chinnachamy M
Date: Sun, 13 Dec 2020 02:36:22 +0530
Subject: [PATCH 02/23] load and cache all skills for skills question
---
src/api/skills.js | 48 +++++++++++++++++++
.../SkillsQuestion/SkillsQuestionBase.jsx | 28 ++++-------
2 files changed, 57 insertions(+), 19 deletions(-)
create mode 100644 src/api/skills.js
diff --git a/src/api/skills.js b/src/api/skills.js
new file mode 100644
index 000000000..d912a1572
--- /dev/null
+++ b/src/api/skills.js
@@ -0,0 +1,48 @@
+import { TC_API_URL, SKILL_PROVIDER_ID } from '../config/constants'
+import { axiosInstance as axios } from './requestInterceptor'
+
+const skillPageSize = 100
+let cachedSkillsAsPromise
+
+/**
+ * Loads and caches all the skills the first time. Returns the skills list from the cache from the second time.
+ */
+export function getSkills() {
+ cachedSkillsAsPromise = cachedSkillsAsPromise || getAllSkills().catch(ex => {
+ console.error('Error loading skills', ex)
+ cachedSkillsAsPromise = null
+ })
+
+ return cachedSkillsAsPromise
+}
+
+/**
+ * Recursively loads all the pages from skills api.
+ */
+function getAllSkills() {
+ let skills = []
+
+ return new Promise((resolve, reject) => {
+ const loop = (page) => getSkillsPage(page)
+ .then((skillResponse) => {
+ skills = skills.concat(skillResponse.data)
+ if (skillResponse.data.length === skillPageSize) {
+ page++
+ loop(page)
+ } else {
+ resolve(skills)
+ }
+ })
+ .catch(ex => reject(ex))
+
+ loop(1)
+ })
+}
+
+/**
+ * Loads the skills in the given page.
+ * @param {number} page The page number to load
+ */
+function getSkillsPage(page) {
+ return axios.get(`${TC_API_URL}/v5/skills?skillProviderId=${SKILL_PROVIDER_ID}&perPage=${skillPageSize}&orderBy=name&page=${page}`)
+}
\ No newline at end of file
diff --git a/src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx b/src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx
index 684f11c0a..2c99acac5 100644
--- a/src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx
+++ b/src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx
@@ -3,11 +3,8 @@ import _ from 'lodash'
import SkillsCheckboxGroup from './SkillsCheckboxGroup'
import Select from '../../../../components/Select/Select'
import './SkillsQuestion.scss'
-import { axiosInstance as axios } from '../../../../api/requestInterceptor'
-import { TC_API_URL, SKILL_PROVIDER_ID } from '../../../../config/constants'
import { createFilter } from 'react-select'
-
-let cachedOptions
+import { getSkills } from '../../../../api/skills'
/**
* If `categoriesMapping` is defined - filter options using selected categories.
@@ -42,7 +39,7 @@ class SkillsQuestion extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
- options: cachedOptions || [],
+ options: [],
availableOptions: [],
customOptionValue: '',
}
@@ -51,20 +48,13 @@ class SkillsQuestion extends React.PureComponent {
}
componentWillMount() {
- if (!cachedOptions) {
- axios.get(`${TC_API_URL}/v5/skills?skillProviderId=${SKILL_PROVIDER_ID}&perPage=100&orderBy=name`)
- .then(resp => {
- const options = _.get(resp, 'data', [])
-
- cachedOptions = options.map((option) => ({
- skillId: option.id,
- name: option.name
- }))
- this.updateOptions(cachedOptions)
- })
- } else {
- this.updateOptions(cachedOptions)
- }
+ getSkills().then(skills => {
+ const options = skills.map(skill => ({
+ skillId: skill.id,
+ name: skill.name
+ }))
+ this.updateOptions(options)
+ })
}
componentWillReceiveProps(nextProps) {
From ad04c7bd8e40dab496f6a685539fd4a90fd688d5 Mon Sep 17 00:00:00 2001
From: Vigneshkumar Chinnachamy M
Date: Sun, 13 Dec 2020 02:38:34 +0530
Subject: [PATCH 03/23] add new line at the end of the file - skills.js
---
src/api/skills.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/api/skills.js b/src/api/skills.js
index d912a1572..892c3716a 100644
--- a/src/api/skills.js
+++ b/src/api/skills.js
@@ -45,4 +45,4 @@ function getAllSkills() {
*/
function getSkillsPage(page) {
return axios.get(`${TC_API_URL}/v5/skills?skillProviderId=${SKILL_PROVIDER_ID}&perPage=${skillPageSize}&orderBy=name&page=${page}`)
-}
\ No newline at end of file
+}
From 89359de54cee8708a16147388b970a7dff5cf58c Mon Sep 17 00:00:00 2001
From: Vigneshkumar Chinnachamy M
Date: Sun, 13 Dec 2020 18:57:18 +0530
Subject: [PATCH 04/23] handle error while loading skills
---
src/api/skills.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/api/skills.js b/src/api/skills.js
index 892c3716a..aa5cc4529 100644
--- a/src/api/skills.js
+++ b/src/api/skills.js
@@ -11,6 +11,7 @@ export function getSkills() {
cachedSkillsAsPromise = cachedSkillsAsPromise || getAllSkills().catch(ex => {
console.error('Error loading skills', ex)
cachedSkillsAsPromise = null
+ return [];
})
return cachedSkillsAsPromise
From 5779223ed10d7150267779dc6502ad0c7d3e822b Mon Sep 17 00:00:00 2001
From: maxceem
Date: Mon, 14 Dec 2020 11:00:56 +0200
Subject: [PATCH 05/23] fix: lint
---
src/api/skills.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/api/skills.js b/src/api/skills.js
index aa5cc4529..5f4ce55f8 100644
--- a/src/api/skills.js
+++ b/src/api/skills.js
@@ -11,7 +11,7 @@ export function getSkills() {
cachedSkillsAsPromise = cachedSkillsAsPromise || getAllSkills().catch(ex => {
console.error('Error loading skills', ex)
cachedSkillsAsPromise = null
- return [];
+ return []
})
return cachedSkillsAsPromise
From 5ae825c62dccb1c782671ef87e79b660fedaf42a Mon Sep 17 00:00:00 2001
From: maxceem
Date: Mon, 14 Dec 2020 11:01:43 +0200
Subject: [PATCH 06/23] chore: deploy 'feature/taas-jobs-2' to TEST01
---
.circleci/config.yml | 4 ++--
config/constants/dev.js | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index e9b9fb9e5..a32f2f31f 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -128,7 +128,7 @@ workflows:
- build-dev
filters:
branches:
- only: ['dev', 'feature/taas-jobs-2']
+ only: ['dev']
- deployTest01:
context : org-global
@@ -136,7 +136,7 @@ workflows:
- build-dev
filters:
branches:
- only: ['feature/unified-permissions', 'feature/accept-reject-terms-in-profile']
+ only: ['feature/taas-jobs-2']
- deployProd:
context : org-global
diff --git a/config/constants/dev.js b/config/constants/dev.js
index 77511f506..17bb03fbc 100644
--- a/config/constants/dev.js
+++ b/config/constants/dev.js
@@ -30,8 +30,8 @@ module.exports = {
TCO17_URL : 'https://tco17.topcoder-dev.com',
TCO_HOME_URL : 'https://www.topcoder-dev.com/tco',
- ACCOUNTS_APP_URL : 'https://accounts-auth0.topcoder-dev.com',
- ACCOUNTS_APP_CONNECTOR_URL : 'https://accounts-auth0.topcoder-dev.com',
+ ACCOUNTS_APP_URL : 'http://localhost:5000',
+ ACCOUNTS_APP_CONNECTOR_URL : 'http://localhost:5000',
FILE_PICKER_API_KEY: process.env.FILE_PICKER_API_KEY_DEV,
FILE_PICKER_SUBMISSION_CONTAINER_NAME: 'submission-staging-dev',
From 68aebd6ee6c0eef4a0f5195636bedd7a00b52eb0 Mon Sep 17 00:00:00 2001
From: maxceem
Date: Tue, 15 Dec 2020 18:43:47 +0200
Subject: [PATCH 07/23] fix: update TaaS URL
---
config/constants/dev.js | 2 +-
config/constants/master.js | 2 +-
config/constants/qa.js | 2 +-
src/config/constants.js | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/config/constants/dev.js b/config/constants/dev.js
index 17bb03fbc..cd777e241 100644
--- a/config/constants/dev.js
+++ b/config/constants/dev.js
@@ -56,5 +56,5 @@ module.exports = {
CONTENTFUL_SPACE_ID : process.env.CONTENTFUL_SPACE_ID,
SKILL_PROVIDER_ID: '9cc0795a-6e12-4c84-9744-15858dba1861',
- TAAS_APP_URL: 'https://mfe.topcoder-dev.com/taas'
+ TAAS_APP_URL: 'https://platform.topcoder-dev.com/taas'
}
diff --git a/config/constants/master.js b/config/constants/master.js
index 96b9f8a47..5301b61ad 100644
--- a/config/constants/master.js
+++ b/config/constants/master.js
@@ -56,5 +56,5 @@ module.exports = {
CONTENTFUL_SPACE_ID : process.env.CONTENTFUL_SPACE_ID,
SKILL_PROVIDER_ID: 'e8467a61-7e20-4ed2-a839-c6340d90f408',
- TAAS_APP_URL: 'https://mfe.topcoder.com/taas'
+ TAAS_APP_URL: 'https://platform.topcoder.com/taas'
}
diff --git a/config/constants/qa.js b/config/constants/qa.js
index b46a3ca89..13b16c3e9 100644
--- a/config/constants/qa.js
+++ b/config/constants/qa.js
@@ -51,5 +51,5 @@ module.exports = {
TC_CDN_URL: process.env.TC_CDN_URL,
SKILL_PROVIDER_ID: '9cc0795a-6e12-4c84-9744-15858dba1861',
- TAAS_APP_URL: 'https://mfe.topcoder-dev.com/taas'
+ TAAS_APP_URL: 'https://platform.topcoder-dev.com/taas'
}
diff --git a/src/config/constants.js b/src/config/constants.js
index 54a553bba..3a534d4cb 100644
--- a/src/config/constants.js
+++ b/src/config/constants.js
@@ -1103,4 +1103,4 @@ export const PROJECT_TYPE_TALENT_AS_A_SERVICE = 'talent-as-a-service'
/**
* URL to the Topcoder TaaS App
*/
-export const TAAS_APP_URL = process.env.TAAS_APP_URL || 'https://mfe.topcoder-dev.com/taas'
+export const TAAS_APP_URL = process.env.TAAS_APP_URL || 'https://platform.topcoder-dev.com/taas'
From 75ffc0ac146fee30543b837d31a3e98437728703 Mon Sep 17 00:00:00 2001
From: maxceem
Date: Wed, 6 Jan 2021 18:57:33 +0200
Subject: [PATCH 08/23] fix use DEV auth instead of local
---
config/constants/dev.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/config/constants/dev.js b/config/constants/dev.js
index eaf37c6e4..495577f40 100644
--- a/config/constants/dev.js
+++ b/config/constants/dev.js
@@ -30,8 +30,8 @@ module.exports = {
TCO17_URL : 'https://tco17.topcoder-dev.com',
TCO_HOME_URL : 'https://www.topcoder-dev.com/tco',
- ACCOUNTS_APP_URL : 'http://localhost:5000',
- ACCOUNTS_APP_CONNECTOR_URL : 'http://localhost:5000',
+ ACCOUNTS_APP_URL : 'https://accounts-auth0.topcoder-dev.com',
+ ACCOUNTS_APP_CONNECTOR_URL : 'https://accounts-auth0.topcoder-dev.com',
FILE_PICKER_API_KEY: process.env.FILE_PICKER_API_KEY_DEV,
FILE_PICKER_SUBMISSION_CONTAINER_NAME: 'submission-staging-dev',
From 3051ef4c250bca7c42c209d648a259fae35a46a0 Mon Sep 17 00:00:00 2001
From: maxceem
Date: Wed, 6 Jan 2021 22:47:46 +0200
Subject: [PATCH 09/23] fix: showing all the skills
---
config/constants/dev.js | 1 -
config/constants/master.js | 1 -
config/constants/qa.js | 1 -
src/api/skills.js | 4 ++--
.../detail/components/SkillsQuestion/SkillsQuestionBase.jsx | 4 ++++
5 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/config/constants/dev.js b/config/constants/dev.js
index 495577f40..4c84dad0a 100644
--- a/config/constants/dev.js
+++ b/config/constants/dev.js
@@ -56,6 +56,5 @@ module.exports = {
CONTENTFUL_DELIVERY_KEY : process.env.CONTENTFUL_DELIVERY_KEY,
CONTENTFUL_SPACE_ID : process.env.CONTENTFUL_SPACE_ID,
- SKILL_PROVIDER_ID: '9cc0795a-6e12-4c84-9744-15858dba1861',
TAAS_APP_URL: 'https://platform.topcoder-dev.com/taas'
}
diff --git a/config/constants/master.js b/config/constants/master.js
index e11157537..12d635aa3 100644
--- a/config/constants/master.js
+++ b/config/constants/master.js
@@ -56,6 +56,5 @@ module.exports = {
CONTENTFUL_DELIVERY_KEY : process.env.CONTENTFUL_DELIVERY_KEY,
CONTENTFUL_SPACE_ID : process.env.CONTENTFUL_SPACE_ID,
- SKILL_PROVIDER_ID: 'e8467a61-7e20-4ed2-a839-c6340d90f408',
TAAS_APP_URL: 'https://platform.topcoder.com/taas'
}
diff --git a/config/constants/qa.js b/config/constants/qa.js
index 40b0e6062..5cf3c2ea9 100644
--- a/config/constants/qa.js
+++ b/config/constants/qa.js
@@ -51,6 +51,5 @@ module.exports = {
TC_CDN_URL: process.env.TC_CDN_URL,
- SKILL_PROVIDER_ID: '9cc0795a-6e12-4c84-9744-15858dba1861',
TAAS_APP_URL: 'https://platform.topcoder-dev.com/taas'
}
diff --git a/src/api/skills.js b/src/api/skills.js
index 5f4ce55f8..cdb90e2ef 100644
--- a/src/api/skills.js
+++ b/src/api/skills.js
@@ -1,4 +1,4 @@
-import { TC_API_URL, SKILL_PROVIDER_ID } from '../config/constants'
+import { TC_API_URL } from '../config/constants'
import { axiosInstance as axios } from './requestInterceptor'
const skillPageSize = 100
@@ -45,5 +45,5 @@ function getAllSkills() {
* @param {number} page The page number to load
*/
function getSkillsPage(page) {
- return axios.get(`${TC_API_URL}/v5/skills?skillProviderId=${SKILL_PROVIDER_ID}&perPage=${skillPageSize}&orderBy=name&page=${page}`)
+ return axios.get(`${TC_API_URL}/v5/taas-teams/skills?perPage=${skillPageSize}&orderBy=name&page=${page}`)
}
diff --git a/src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx b/src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx
index 69ddb48e1..96cf1acc6 100644
--- a/src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx
+++ b/src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx
@@ -18,6 +18,9 @@ import { getSkills } from '../../../../api/skills'
* @returns {Array} available options
*/
const getAvailableOptions = (categoriesMapping, selectedCategories, skillsCategories, options) => {
+ // NOTE:
+ // Disable filtering skills by categories for now, because V5 Skills API doesn't have categories for now.
+ /*
let mappedCategories
if (categoriesMapping) {
mappedCategories = _.map(selectedCategories, (category) => categoriesMapping[category] ? categoriesMapping[category].toLowerCase() : null)
@@ -28,6 +31,7 @@ const getAvailableOptions = (categoriesMapping, selectedCategories, skillsCatego
if (mappedCategories) {
return options.filter(option => _.intersection((option.categories || []).map(c => c.toLowerCase()), mappedCategories).length > 0)
}
+ */
return options
}
From 8e883e28eeb8169cf993d72512737dfaeceb0c64 Mon Sep 17 00:00:00 2001
From: maxceem
Date: Wed, 6 Jan 2021 23:24:26 +0200
Subject: [PATCH 10/23] Revert "Revert "Merge pull request #4204 from
appirio-tech/feature/taas-jobs""
This reverts commit 676ac05dae20eb2a430c43621ff68cdf4b7cadb5.
# Conflicts:
# config/constants/dev.js
# config/constants/master.js
# config/constants/qa.js
# src/config/constants.js
# src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx
# src/projects/detail/containers/DashboardContainer.jsx
---
src/config/constants.js | 2 +-
.../create/components/ProjectSubmitted.jsx | 34 +++--
.../create/components/ProjectWizard.jsx | 3 -
.../create/containers/CreateContainer.jsx | 3 +-
.../SkillsQuestion/SkillsQuestionBase.jsx | 13 +-
.../TaasProjectWelcome/TaasProjectWelcome.jsx | 14 +++
.../TaasProjectWelcome.scss | 15 +++
.../components/TaasProjectWelcome/index.js | 2 +
.../TalentPickerQuestionV2.jsx | 6 +-
.../detail/containers/DashboardContainer.jsx | 118 ++++++++++--------
10 files changed, 134 insertions(+), 76 deletions(-)
create mode 100644 src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.jsx
create mode 100644 src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.scss
create mode 100644 src/projects/detail/components/TaasProjectWelcome/index.js
diff --git a/src/config/constants.js b/src/config/constants.js
index 9eb69d37a..490ac76f1 100644
--- a/src/config/constants.js
+++ b/src/config/constants.js
@@ -729,7 +729,7 @@ export const SEGMENT_KEY = process.env.CONNECT_SEGMENT_KEY
*/
export const DOMAIN = process.env.domain || 'topcoder.com'
export const CONNECT_DOMAIN = `connect.${DOMAIN}`
-export const CONNECT_MAIN_PAGE_URL = `http://connect.${DOMAIN}`
+export const CONNECT_MAIN_PAGE_URL = `https://connect.${DOMAIN}`
export const ACCOUNTS_APP_CONNECTOR_URL = process.env.ACCOUNTS_APP_CONNECTOR_URL
export const ACCOUNTS_APP_LOGIN_URL = process.env.ACCOUNTS_APP_LOGIN_URL || `https://accounts-auth0.${DOMAIN}`
export const ACCOUNTS_APP_REGISTER_URL = process.env.ACCOUNTS_APP_REGISTER_URL || `https://accounts-auth0.${DOMAIN}`
diff --git a/src/projects/create/components/ProjectSubmitted.jsx b/src/projects/create/components/ProjectSubmitted.jsx
index 130007de3..9bde26a51 100644
--- a/src/projects/create/components/ProjectSubmitted.jsx
+++ b/src/projects/create/components/ProjectSubmitted.jsx
@@ -1,25 +1,40 @@
import React from 'react'
import PT from 'prop-types'
+import qs from 'query-string'
require('./ProjectSubmitted.scss')
import {
- CONNECT_DOMAIN
+ CONNECT_MAIN_PAGE_URL, PROJECT_TYPE_TALENT_AS_A_SERVICE, TAAS_APP_URL
} from '../../../config/constants'
+/**
+ * Build project URL based on the `type` query param in URL.
+ *
+ * @param {String} projectId project id
+ */
+const formatProjectURL = (projectId) => {
+ const { type } = qs.parse(window.location.search)
+
+ const url = type === PROJECT_TYPE_TALENT_AS_A_SERVICE
+ // if the project type is TaaS, then use link to TaaS App
+ ? `${TAAS_APP_URL}/myteams/${projectId}`
+ // otherwise use link inside Connect App
+ : `${CONNECT_MAIN_PAGE_URL}/projects/${projectId}`
+
+ return url
+}
+
class ProjectSubmitted extends React.Component {
constructor(props) {
super(props)
this.copyToClipboard = this.copyToClipboard.bind(this)
- this.state = {
- domain: `${CONNECT_DOMAIN}/`,
- url: `projects/${props.params.status || props.projectId}`
- }
}
copyToClipboard() {
+ const url = formatProjectURL(this.props.params.status || this.props.projectId)
const textField = document.createElement('textarea')
- textField.innerText = `${this.state.domain}${this.state.url}`
+ textField.innerText = url
document.body.appendChild(textField)
textField.select()
document.execCommand('copy')
@@ -27,6 +42,8 @@ class ProjectSubmitted extends React.Component {
}
render() {
+ const url = formatProjectURL(this.props.params.status || this.props.projectId)
+
return (
@@ -39,11 +56,11 @@ class ProjectSubmitted extends React.Component {
Use the link below to share your project with members of your team. You can also access all your Topcoder projects in one place from your Connect project dashboard.
@@ -52,7 +69,6 @@ class ProjectSubmitted extends React.Component {
}
ProjectSubmitted.defaultProps = {
- vm: {},
params: {},
}
diff --git a/src/projects/create/components/ProjectWizard.jsx b/src/projects/create/components/ProjectWizard.jsx
index 0ca419fdc..b05edf01a 100644
--- a/src/projects/create/components/ProjectWizard.jsx
+++ b/src/projects/create/components/ProjectWizard.jsx
@@ -605,9 +605,6 @@ class ProjectWizard extends Component {
/>
diff --git a/src/projects/create/containers/CreateContainer.jsx b/src/projects/create/containers/CreateContainer.jsx
index 0ee63d074..5e687c758 100644
--- a/src/projects/create/containers/CreateContainer.jsx
+++ b/src/projects/create/containers/CreateContainer.jsx
@@ -124,11 +124,12 @@ class CreateContainer extends React.Component {
projectId: nextProjectId,
isProjectDirty: false
}, () => {
+ const type = _.get(this.state, 'updatedProject.type')
// go to submitted state
console.log('go to submitted state')
window.localStorage.removeItem(LS_INCOMPLETE_PROJECT)
window.localStorage.removeItem(LS_INCOMPLETE_WIZARD)
- this.props.history.push('/new-project/submitted/' + nextProjectId)
+ this.props.history.push('/new-project/submitted/' + nextProjectId + (type ? `?type=${type}` : ''))
})
} else if (this.state.creatingProject !== nextProps.processing) {
diff --git a/src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx b/src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx
index 96cf1acc6..9ed46d17f 100644
--- a/src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx
+++ b/src/projects/detail/components/SkillsQuestion/SkillsQuestionBase.jsx
@@ -74,7 +74,7 @@ class SkillsQuestion extends React.PureComponent {
this.setState({ options })
this.updateAvailableOptions(this.props, options)
if (onSkillsLoaded) {
- onSkillsLoaded(options.map((option) => _.pick(option, ['id', 'name'])))
+ onSkillsLoaded(options)
}
}
@@ -90,7 +90,6 @@ class SkillsQuestion extends React.PureComponent {
// if have a mapping for categories, then filter options, otherwise use all options
const availableOptions = getAvailableOptions(categoriesMapping, selectedCategories, skillsCategories, options)
- .map(option => _.pick(option, ['id', 'name']))
this.setState({ availableOptions })
}
@@ -179,17 +178,17 @@ class SkillsQuestion extends React.PureComponent {
const selectedCategories = _.get(currentProjectData, categoriesField, [])
let currentValues = getValue() || []
- // remove from currentValues not available options but still keep created custom options without id
- currentValues = currentValues.filter(skill => _.some(availableOptions, skill) || !skill.id)
+ // remove from currentValues not available options but still keep created custom options without skillId
+ currentValues = currentValues.filter(skill => _.some(availableOptions, skill) || !skill.skillId)
const questionDisabled = isFormDisabled() || disabled || (selectedCategories.length === 0 && _.isUndefined(skillsCategories))
const hasError = !isPristine() && !isValid()
const errorMessage = getErrorMessage() || validationError
- const checkboxGroupOptions = availableOptions.filter(option => frequentSkills.indexOf(option.id) > -1)
- const checkboxGroupValues = currentValues.filter(val => _.some(checkboxGroupOptions, option => option.id === val.id ))
+ const checkboxGroupOptions = availableOptions.filter(option => frequentSkills.indexOf(option.skillId) > -1)
+ const checkboxGroupValues = currentValues.filter(val => _.some(checkboxGroupOptions, option => option.skillId === val.skillId ))
- const selectGroupOptions = availableOptions.filter(option => frequentSkills.indexOf(option.id) === -1)
+ const selectGroupOptions = availableOptions.filter(option => frequentSkills.indexOf(option.skillId) === -1)
if (customOptionValue) {
selectGroupOptions.unshift({ name: customOptionValue })
}
diff --git a/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.jsx b/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.jsx
new file mode 100644
index 000000000..28217e0f3
--- /dev/null
+++ b/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.jsx
@@ -0,0 +1,14 @@
+import React from 'react'
+import { TAAS_APP_URL } from '../../../../../config/constants/dev'
+import './TaasProjectWelcome.scss'
+
+const TaasProjectWelcome = ({ projectId }) => {
+ const url = `${TAAS_APP_URL}/myteams/${projectId}`
+ return (
+
+ )
+}
+
+export default TaasProjectWelcome
diff --git a/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.scss b/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.scss
new file mode 100644
index 000000000..e0ed62c21
--- /dev/null
+++ b/src/projects/detail/components/TaasProjectWelcome/TaasProjectWelcome.scss
@@ -0,0 +1,15 @@
+@import '~tc-ui/src/styles/tc-includes';
+@import '../../../../styles/includes';
+
+.container {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+ height: 400px;
+
+ :global(.tc-btn-lg) {
+ height: 70px;
+ line-height: 68px;
+ font-size: 30px;
+ }
+}
diff --git a/src/projects/detail/components/TaasProjectWelcome/index.js b/src/projects/detail/components/TaasProjectWelcome/index.js
new file mode 100644
index 000000000..96117cea1
--- /dev/null
+++ b/src/projects/detail/components/TaasProjectWelcome/index.js
@@ -0,0 +1,2 @@
+import TaasProjectWelcome from './TaasProjectWelcome'
+export default TaasProjectWelcome
diff --git a/src/projects/detail/components/TalentPickerQuestion/TalentPickerQuestionV2.jsx b/src/projects/detail/components/TalentPickerQuestion/TalentPickerQuestionV2.jsx
index 5a65a60c9..a37755209 100644
--- a/src/projects/detail/components/TalentPickerQuestion/TalentPickerQuestionV2.jsx
+++ b/src/projects/detail/components/TalentPickerQuestion/TalentPickerQuestionV2.jsx
@@ -70,6 +70,7 @@ class TalentPickerQuestionV2 extends Component {
getDefaultValue() {
const { options } = this.props
return options.map((o) => ({
+ roleTitle: o.roleTitle,
role: o.role,
people: '0',
duration: '0',
@@ -96,13 +97,16 @@ class TalentPickerQuestionV2 extends Component {
}
insertRole(index, role) {
- const { getValue } = this.props
+ const { getValue, options } = this.props
let values = getValue() || this.getDefaultValue()
+ const roleOption = _.find(options, { role })
+
values = [
...values.slice(0, index),
{
role,
+ roleTitle: roleOption.roleTitle,
people: '0',
duration: '0',
skills: [],
diff --git a/src/projects/detail/containers/DashboardContainer.jsx b/src/projects/detail/containers/DashboardContainer.jsx
index 4555b96f7..693fee77d 100644
--- a/src/projects/detail/containers/DashboardContainer.jsx
+++ b/src/projects/detail/containers/DashboardContainer.jsx
@@ -40,6 +40,7 @@ import SystemFeed from '../../../components/Feed/SystemFeed'
import ProjectScopeDrawer from '../components/ProjectScopeDrawer'
import ProjectStages from '../components/ProjectStages'
import ProjectPlanEmpty from '../components/ProjectPlanEmpty'
+import TaasProjectWelcome from '../components/TaasProjectWelcome'
import NotificationsReader from '../../../components/NotificationsReader'
import { hasPermission } from '../../../helpers/permissions'
import { getProjectTemplateById } from '../../../helpers/templates'
@@ -60,6 +61,7 @@ import {
PHASE_STATUS_DRAFT,
SCREEN_BREAKPOINT_MD,
CODER_BOT_USERID,
+ PROJECT_TYPE_TALENT_AS_A_SERVICE,
PHASE_PRODUCT_TEMPLATE_ID
} from '../../../config/constants'
@@ -179,6 +181,8 @@ class DashboardContainer extends React.Component {
const isProjectLive = project.status !== PROJECT_STATUS_COMPLETED && project.status !== PROJECT_STATUS_CANCELLED
+ const isTaasProject = project.type === PROJECT_TYPE_TALENT_AS_A_SERVICE
+
const leftArea = (
- {unreadProjectUpdate.length > 0 &&
-
- }
- {/* Toggle drawer */}
- {!!estimationQuestion &&
-
- }
- {/* The following containerStyle and overlayStyle are needed for shrink drawer and overlay size for not
- covering sidebar and topbar
- */}
- this.setState({open})}
- project={project}
- template={template}
- updateProject={updateProject}
- processing={isProcessing}
- fireProjectDirty={fireProjectDirty}
- fireProjectDirtyUndo= {fireProjectDirtyUndo}
- addProjectAttachment={addProjectAttachment}
- updateProjectAttachment={updateProjectAttachment}
- removeProjectAttachment={removeProjectAttachment}
- productTemplates={productTemplates}
- productCategories={productCategories}
- />
-
- {visiblePhases && visiblePhases.length > 0 ? (
-
+ {isTaasProject ? (
+
) : (
-
- )}
- {isCreatingPhase? : null}
- {isProjectLive && !isCreatingPhase && hasPermission(PERMISSIONS.MANAGE_PROJECT_PLAN) && !isLoadingPhases && (
-
+
+ {unreadProjectUpdate.length > 0 &&
+
+ }
+ {/*
Toggle drawer */}
+ {!!estimationQuestion &&
+
+ }
+ {/* The following containerStyle and overlayStyle are needed for shrink drawer and overlay size for not
+ covering sidebar and topbar
+ */}
+
this.setState({open})}
+ project={project}
+ template={template}
+ updateProject={updateProject}
+ processing={isProcessing}
+ fireProjectDirty={fireProjectDirty}
+ fireProjectDirtyUndo= {fireProjectDirtyUndo}
+ addProjectAttachment={addProjectAttachment}
+ updateProjectAttachment={updateProjectAttachment}
+ removeProjectAttachment={removeProjectAttachment}
+ productTemplates={productTemplates}
+ productCategories={productCategories}
+ />
+
+ {visiblePhases && visiblePhases.length > 0 ? (
+
+ ) : (
+
+ )}
+ {isCreatingPhase? : null}
+ {isProjectLive && !isCreatingPhase && hasPermission(PERMISSIONS.MANAGE_PROJECT_PLAN) && !isLoadingPhases && (
+
+ )}
+
)}
From dd7b0f715ce210e6b368b0a3aa7b7313c62ab4b2 Mon Sep 17 00:00:00 2001
From: maxceem
Date: Wed, 6 Jan 2021 23:34:16 +0200
Subject: [PATCH 11/23] fix: lint
---
.../detail/containers/DashboardContainer.jsx | 22 +++++++++----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/projects/detail/containers/DashboardContainer.jsx b/src/projects/detail/containers/DashboardContainer.jsx
index 693fee77d..43420918e 100644
--- a/src/projects/detail/containers/DashboardContainer.jsx
+++ b/src/projects/detail/containers/DashboardContainer.jsx
@@ -270,17 +270,17 @@ class DashboardContainer extends React.Component {
productCategories={productCategories}
/>
- {visiblePhases && visiblePhases.length > 0 ? (
-
- ) : (
-
- )}
+ {visiblePhases && visiblePhases.length > 0 ? (
+
+ ) : (
+
+ )}
{isCreatingPhase? : null}
{isProjectLive && !isCreatingPhase && hasPermission(PERMISSIONS.MANAGE_PROJECT_PLAN) && !isLoadingPhases && (
Date: Wed, 6 Jan 2021 09:39:33 +0800
Subject: [PATCH 12/23] fix: #4206
---
.../components/JobPickerRow/JobPickerRow.jsx | 285 ++++++++++++++++++
.../components/JobPickerRow/JobPickerRow.scss | 146 +++++++++
.../JobsPickerQuestion/JobsPickerQuestion.jsx | 146 +++++++++
.../JobsPickerQuestion.scss | 8 +
.../detail/components/SpecQuestions.jsx | 6 +-
5 files changed, 590 insertions(+), 1 deletion(-)
create mode 100644 src/projects/detail/components/JobPickerRow/JobPickerRow.jsx
create mode 100644 src/projects/detail/components/JobPickerRow/JobPickerRow.scss
create mode 100644 src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx
create mode 100644 src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.scss
diff --git a/src/projects/detail/components/JobPickerRow/JobPickerRow.jsx b/src/projects/detail/components/JobPickerRow/JobPickerRow.jsx
new file mode 100644
index 000000000..0d8b1b324
--- /dev/null
+++ b/src/projects/detail/components/JobPickerRow/JobPickerRow.jsx
@@ -0,0 +1,285 @@
+import React from 'react'
+import PT from 'prop-types'
+import cn from 'classnames'
+
+import IconX from '../../../../assets/icons/ui-16px-1_bold-remove.svg'
+import IconAdd from '../../../../assets/icons/ui-16px-1_bold-add.svg'
+import SkillsQuestion from '../SkillsQuestion/SkillsQuestionBase'
+import PositiveNumberInput from '../../../../components/PositiveNumberInput/PositiveNumberInput'
+import SelectDropdown from 'appirio-tech-react-components/components/SelectDropdown/SelectDropdown'
+
+import styles from './JobPickerRow.scss'
+
+const always = () => true
+const never = () => false
+const emptyError = () => ''
+
+class JobPickerRow extends React.PureComponent {
+ constructor(props) {
+ super(props)
+
+ this.handlePeopleChange = this.handlePeopleChange.bind(this)
+ this.handleDurationChange = this.handleDurationChange.bind(this)
+ this.handleSkillChange = this.handleSkillChange.bind(this)
+ this.handleJobNameChange = this.handleJobNameChange.bind(this)
+ this.handleRoleChange = this.handleRoleChange.bind(this)
+ this.handleWorkloadChange = this.handleWorkloadChange.bind(this)
+ this.handleJobDescriptionChange = this.handleJobDescriptionChange.bind(this)
+
+ this.resetPeople = this.resetPeople.bind(this)
+ this.resetDuration = this.resetDuration.bind(this)
+
+ this.onAddRow = this.onAddRow.bind(this)
+ this.onDeleteRow = this.onDeleteRow.bind(this)
+
+ this.workloadOptions = [
+ { value: null, title: 'Select Workload'},
+ { value: 'fulltime', title: 'Full-Time'},
+ { value: 'fractional', title: 'Fractional'}
+ ]
+
+ this.roleOptions = [
+ { value: null, title: 'Select Role'},
+ { value: 'designer', title: 'Designer'},
+ { value: 'software-developer', title: 'Software Developer'},
+ { value: 'data-scientist', title: 'Data Scientist'},
+ { value: 'data-engineer', title: 'Data Engineer'},
+ { value: 'qa', title: 'QA Tester'},
+ { value: 'qa-engineer', title: 'QA Engineer'}
+ ]
+ }
+ handleJobNameChange(evt) {
+ this.props.onChange(this.props.rowIndex, 'name', evt.target.value)
+ }
+ handlePeopleChange(evt) {
+ this.props.onChange(this.props.rowIndex, 'people', evt.target.value)
+ }
+
+ handleDurationChange(evt) {
+ this.props.onChange(this.props.rowIndex, 'duration', evt.target.value)
+ }
+
+ handleSkillChange(value) {
+ this.props.onChange(this.props.rowIndex, 'skills', value)
+ }
+
+ handleWorkloadChange(evt) {
+ this.props.onChange(this.props.rowIndex, 'workLoad', evt)
+ }
+
+ handleRoleChange(evt) {
+ this.props.onChange(this.props.rowIndex, 'role', evt)
+ }
+
+ handleJobDescriptionChange(evt) {
+ this.props.onChange(this.props.rowIndex, 'jobDescription', evt.target.value)
+ }
+
+ resetDuration() {
+ const { rowIndex, onChange, value } = this.props
+ if (!value.duration) {
+ onChange(rowIndex, 'duration', '0')
+ }
+ }
+
+ resetPeople() {
+ const { rowIndex, onChange, value } = this.props
+ if (!value.people) {
+ onChange(rowIndex, 'people', '0')
+ }
+ }
+
+ onAddRow() {
+ const { rowIndex, value, onAddRow: addRowHandler } = this.props
+ addRowHandler(rowIndex + 1, value.role)
+ }
+
+ onDeleteRow() {
+ const { rowIndex, onDeleteRow: deleteRowHandler } = this.props
+ deleteRowHandler(rowIndex)
+ }
+
+ render() {
+ const { value, rowIndex } = this.props
+ const isRowIncomplete = value.name.length > 0 || value.people > 0 || value.duration > 0 || (value.skills && value.skills.length)
+ ||(value.role && value.role.value !== null) ||(value.workLoad && value.workLoad.value !== null) || (value.jobDescription.length > 0)
+
+ /* Different columns are defined here and used in componsing mobile/desktop views below */
+ const titleColumn = (
+
+
+
+ Job {rowIndex +1}
+
+
+
+
+ )
+
+ const actionsColumn = (
+
+
+
+
+
+ { rowIndex > 0 && (
+
+
+
+ )}
+
+
+ )
+
+ const peopleColumn = (
+
+
+ Number Of People
+
+
+
+ )
+
+ const durationColumn = (
+
+
+ Duration (months)
+
+
+
+ )
+
+ const skillSelectionColumn = (
+
+
+ Skills
+
+ {/*
+ Please do not refactor getValue prop's value to a binded function with constant reference.
+ SkillsQuestion is a pure component. If all the props are constant across renders, SkillsQuestion cannot detect the change in value.skills.
+ So, it'll break the functionality of the component.
+ "getValue" prop is left as inline arrow function to trigger re rendering of the SkillsQuestion component whenever the parent rerenders.
+ */}
+ value.skills}
+ onChange={_.noop}
+ selectWrapperClass={cn(styles.noMargin, {[styles.skillHasError]: isRowIncomplete && !(value.skills && value.skills.length)})}
+ />
+
+ )
+
+ const workLoadColumn = (
+
+
+ Workload
+
+
+
+ )
+
+ const roleColumn = (
+
+
+ Role
+
+
+
+ )
+ const jobDescriptionColumn = (
+
+
+ Job Description
+
+
+
+
+
+ )
+
+ return (
+
+
+ {titleColumn}
+ {actionsColumn}
+
+
+
+ {peopleColumn}
+ {roleColumn}
+
+
+ {durationColumn}
+ {workLoadColumn}
+
+
+ {jobDescriptionColumn}
+
+
+
{skillSelectionColumn}
+
+ )
+ }
+}
+
+JobPickerRow.propTypes = {
+ rowIndex: PT.number.isRequired,
+ onChange: PT.func.isRequired,
+ onAddRow: PT.func.isRequired,
+ onDeleteRow: PT.func.isRequired,
+ value: PT.shape({
+ people: PT.string.isRequired,
+ name: PT.string,
+ duration: PT.string.isRequired,
+ skills: PT.array,
+ }),
+}
+
+JobPickerRow.defaultProps = {}
+
+export default JobPickerRow
diff --git a/src/projects/detail/components/JobPickerRow/JobPickerRow.scss b/src/projects/detail/components/JobPickerRow/JobPickerRow.scss
new file mode 100644
index 000000000..04143f860
--- /dev/null
+++ b/src/projects/detail/components/JobPickerRow/JobPickerRow.scss
@@ -0,0 +1,146 @@
+@import "~tc-ui/src/styles/tc-includes";
+@import "../../../../styles/includes";
+
+.action-btn {
+ cursor: pointer;
+ margin: 0 2px;
+ background-color: $tc-gray-neutral-dark;
+ height: 23px;
+ width: 23px;
+ text-align: center;
+ line-height: 25px;
+ border-radius: 12px;
+
+ svg {
+ fill: $tc-gray-50;
+ height: 10px;
+ }
+}
+
+.action-btn-remove {
+ margin-left: 8px;
+}
+
+.d-flex {
+ display: flex;
+}
+
+.row {
+ border: 1px solid $tc-gray-neutral-dark;
+ border-top-width: 0;
+ white-space: nowrap;
+ padding: 4px;
+ line-height: 20px;
+ font-size: 13px;
+ vertical-align: top;
+
+ &:first-child {
+ border-top-width: 1px;
+ }
+}
+
+.inner-row {
+ width: 100%;
+ display: flex;
+}
+
+.col {
+ padding: 4px 7.5px;
+ flex-grow: 0;
+ flex-shrink: 0;
+
+ &.col-duration,
+ &.col-people {
+ width: 50%;
+ }
+
+ &.col-skill-selection {
+ flex-grow: 1;
+ flex-shrink: 1;
+ margin-bottom: 4px;
+
+ // Prevents the column from expanding beyond parent due to flex-grow:1
+ min-width: 0;
+ }
+
+ &.col-role {
+ flex-grow: 1;
+
+ // Prevents the column from expanding beyond parent due to flex-grow:1
+ min-width: 0;
+ }
+
+ &.col-actions {
+ width: 76px;
+ }
+
+ // Resets standard margins applied by tc-file-field__inputs elements
+ .noMargin {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 0;
+ margin-right: 0;
+ }
+
+ .label {
+ display: block;
+ }
+
+ .job-description textarea,
+ .job-textarea[type="text"] {
+ &.empty {
+ color: $tc-gray-30;
+ }
+ min-height : 90px;
+
+ @include placeholder {
+ @include roboto;
+ color: $tc-gray-30;
+ text-transform: none;
+ font-style: italic;
+ font-size: $base-unit*3;
+ line-height: $base-unit*4;
+ }
+ }
+}
+
+.col-role-container {
+ display: flex;
+ align-items: center;
+}
+
+.col-job-name-container {
+ display: flex;
+ align-items: center;
+ label {
+ flex: 40px 0 0;
+ }
+}
+
+.col-actions-container {
+ justify-content: flex-end;
+ margin-top: 5px;
+}
+
+.col-role {
+ svg {
+ width: 22.5px;
+ margin-right: 11px;
+ flex-grow: 0;
+ flex-shrink: 0;
+ }
+}
+
+.role-text {
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+
+.skillHasError {
+ :global {
+ .react-select__control {
+ border-color: $tc-red-70;
+ }
+ }
+}
diff --git a/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx b/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx
new file mode 100644
index 000000000..2039de454
--- /dev/null
+++ b/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx
@@ -0,0 +1,146 @@
+import React, { Component, PropTypes } from 'react'
+import _ from 'lodash'
+import { HOC as hoc } from 'formsy-react'
+import cn from 'classnames'
+
+import JobPickerRow from '../JobPickerRow/JobPickerRow.jsx'
+import './JobsPickerQuestion.scss'
+
+class JobsPickerQuestion extends Component {
+
+ constructor(props) {
+ super(props)
+
+ this.getDefaultValue = this.getDefaultValue.bind(this)
+ this.handleValueChange = this.handleValueChange.bind(this)
+
+ this.insertJob = this.insertJob.bind(this)
+ this.removeJob = this.removeJob.bind(this)
+ this.setValidator(props)
+ }
+
+ componentWillReceiveProps(nextProps) {
+ this.setValidator(nextProps)
+ }
+
+ setValidator(props) {
+ const { setValidations, required } = props
+ const validations = {
+ oneRowHaveValidValue: (formValues, value) => {
+ if (!required) {
+ return true
+ }
+ return _.some(value, (v) => {
+ return v.name.length && v.people !== '0' && v.duration !== '0' && v.skills.length > 0 && v.workLoad.value !== null && v.role.value !== null && v.jobDescription.length
+ }) // validation body
+ },
+ noPartialFillsExist: (formValues, value) => {
+ return _.every(value, v => {
+
+ const isOneValueFilled = v.name.length > 0 || v.people > 0 || v.duration > 0 || (v.skills && v.skills.length) || (v.jobDescription && v.jobDescription.length) || (v.workLoad && v.workLoad.value !== null) || (v.role && v.role.value !== null)
+ const isAllValuesFilled = v.name.length > 0 && v.people > 0 && v.duration > 0 && v.skills && v.skills.length && v.jobDescription.length && v.workLoad.value !== null && v.role.value !== null
+ // If one value is filled, all values should be filled to make this row valid. Partial fill is not valid
+ const isRowValid = !isOneValueFilled || isAllValuesFilled
+ return isRowValid
+ })
+ }
+ }
+ setValidations(validations)
+ }
+
+ getDefaultValue() {
+ return [{
+ name: '',
+ role: { value: null, title: 'Select Role'},
+ people: '0',
+ duration: '0',
+ skills: [],
+ workLoad: { value: null, title: 'Select Workload'},
+ jobDescription: '',
+ _key: Date.now()
+ }
+ ]
+ }
+
+ onChange(value) {
+ const {setValue, name} = this.props
+
+ setValue(value)
+ this.props.onChange(name, value)
+ }
+
+ handleValueChange(index, field, value) {
+ const { getValue } = this.props
+ let values = getValue() || this.getDefaultValue()
+ values = [...values.slice(0, index), { ...values[index], [field]: value }, ...values.slice(index + 1)]
+
+ this.onChange(values)
+ }
+
+ insertJob(index) {
+ const { getValue } = this.props
+ let values = getValue() || this.getDefaultValue()
+
+ values = [
+ ...values.slice(0, index),
+ {
+ name: '',
+ role: { value: null, title: 'Select Role'},
+ people: '0',
+ duration: '0',
+ skills: [],
+ workLoad: { value: null, title: 'Select Workload'},
+ jobDescription: '',
+ _key: Date.now()
+ },
+ ...values.slice(index)
+ ]
+ this.onChange(values)
+ }
+
+ removeJob(index) {
+ const { getValue } = this.props
+ let values = getValue() || this.getDefaultValue()
+ values = [...values.slice(0, index), ...values.slice(index + 1)]
+ this.onChange(values)
+ }
+
+ render() {
+ const { wrapperClass, getValue } = this.props
+ const errorMessage =
+ this.props.getErrorMessage() || this.props.validationError
+ const hasError = !this.props.isPristine() && !this.props.isValid()
+
+ const values = getValue() || this.getDefaultValue()
+
+ return (
+
+
+ {values.map((v, jobIndex) => {
+ return (
+
+ )
+ })}
+
+ {hasError ?
{errorMessage}
: null}
+
+ )
+ }
+}
+
+JobsPickerQuestion.PropTypes = {
+ onChange: PropTypes.func,
+}
+
+JobsPickerQuestion.defaultProps = {
+ onChange: _.noop
+}
+
+export default hoc(JobsPickerQuestion)
diff --git a/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.scss b/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.scss
new file mode 100644
index 000000000..436c84d58
--- /dev/null
+++ b/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.scss
@@ -0,0 +1,8 @@
+@import '~tc-ui/src/styles/tc-includes';
+@import '../../../../styles/includes';
+
+.container {
+ font-size: 15px;
+ text-align: left;
+ margin-top: 5px;
+}
diff --git a/src/projects/detail/components/SpecQuestions.jsx b/src/projects/detail/components/SpecQuestions.jsx
index aa4afd86b..4958acecf 100644
--- a/src/projects/detail/components/SpecQuestions.jsx
+++ b/src/projects/detail/components/SpecQuestions.jsx
@@ -12,6 +12,7 @@ import SpecQuestionIcons from './SpecQuestionList/SpecQuestionIcons'
import SkillsQuestion from './SkillsQuestion/SkillsQuestion'
import TalentPickerQuestion from './TalentPickerQuestion/TalentPickerQuestion'
import TalentPickerQuestionV2 from './TalentPickerQuestion/TalentPickerQuestionV2'
+import JobsPickerQuestion from './JobsPickerQuestion/JobsPickerQuestion'
import SpecFeatureQuestion from './SpecFeatureQuestion'
import ColorSelector from './../../../components/ColorSelector/ColorSelector'
import SelectDropdown from './../../../components/SelectDropdown/SelectDropdown'
@@ -389,6 +390,9 @@ class SpecQuestions extends React.Component {
options: q.options,
})
break
+ case 'jobs-picker':
+ ChildElem = JobsPickerQuestion
+ break
default:
ChildElem = () => (
@@ -459,7 +463,7 @@ class SpecQuestions extends React.Component {
!(question.type === 'estimation' && template.hideEstimation)
).map((q, index) => {
return (
- _.includes(['checkbox', 'checkbox-group', 'radio-group', 'add-ons', 'textinput', 'textbox', 'numberinput', 'skills', 'slide-radiogroup', 'slider-standard', 'select-dropdown', 'talent-picker', 'talent-picker-v2'], q.type) && q.visibilityForRendering === STEP_VISIBILITY.READ_OPTIMIZED ? (
+ _.includes(['checkbox', 'checkbox-group', 'radio-group', 'add-ons', 'textinput', 'textbox', 'numberinput', 'skills', 'slide-radiogroup', 'slider-standard', 'select-dropdown', 'talent-picker', 'talent-picker-v2', 'jobs-picker'], q.type) && q.visibilityForRendering === STEP_VISIBILITY.READ_OPTIMIZED ? (
Date: Thu, 7 Jan 2021 13:22:37 +0200
Subject: [PATCH 13/23] feat: jobs form improvements
rename "name" -> "title"
rename "jobDescription" -> "description"
fix showing Jobs in readOnly mode inside accordion
---
.../detail/components/Accordion/Accordion.jsx | 4 ++
.../components/JobPickerRow/JobPickerRow.jsx | 39 ++++++++++---------
.../JobsPickerQuestion/JobsPickerQuestion.jsx | 17 ++++----
3 files changed, 32 insertions(+), 28 deletions(-)
diff --git a/src/projects/detail/components/Accordion/Accordion.jsx b/src/projects/detail/components/Accordion/Accordion.jsx
index 3b64f6543..3fb3d9c2b 100644
--- a/src/projects/detail/components/Accordion/Accordion.jsx
+++ b/src/projects/detail/components/Accordion/Accordion.jsx
@@ -33,6 +33,7 @@ const TYPE = {
SELECT_DROPDOWN: 'select-dropdown',
TALENT_PICKER: 'talent-picker',
TALENT_PICKER_V2: 'talent-picker-v2',
+ JOBS_PICKER: 'jobs-picker',
}
/**
@@ -180,6 +181,9 @@ class Accordion extends React.Component {
const totalPeoplePerRole = _.mapValues(_.groupBy(value, v => v.role), valuesUnderGroup => _.sumBy(valuesUnderGroup, v => Number(v.people)))
return _.toPairs(totalPeoplePerRole).filter(([, people]) => people > 0).map(([role, people]) => `${getRoleName(role)}: ${people}`).join(', ')
}
+ case TYPE.JOBS_PICKER: {
+ return _.map(value, 'title').join(', ')
+ }
default: return value
}
}
diff --git a/src/projects/detail/components/JobPickerRow/JobPickerRow.jsx b/src/projects/detail/components/JobPickerRow/JobPickerRow.jsx
index 0d8b1b324..2188843af 100644
--- a/src/projects/detail/components/JobPickerRow/JobPickerRow.jsx
+++ b/src/projects/detail/components/JobPickerRow/JobPickerRow.jsx
@@ -21,10 +21,10 @@ class JobPickerRow extends React.PureComponent {
this.handlePeopleChange = this.handlePeopleChange.bind(this)
this.handleDurationChange = this.handleDurationChange.bind(this)
this.handleSkillChange = this.handleSkillChange.bind(this)
- this.handleJobNameChange = this.handleJobNameChange.bind(this)
+ this.handleJobTitleChange = this.handleJobTitleChange.bind(this)
this.handleRoleChange = this.handleRoleChange.bind(this)
this.handleWorkloadChange = this.handleWorkloadChange.bind(this)
- this.handleJobDescriptionChange = this.handleJobDescriptionChange.bind(this)
+ this.handleDescriptionChange = this.handleDescriptionChange.bind(this)
this.resetPeople = this.resetPeople.bind(this)
this.resetDuration = this.resetDuration.bind(this)
@@ -48,8 +48,8 @@ class JobPickerRow extends React.PureComponent {
{ value: 'qa-engineer', title: 'QA Engineer'}
]
}
- handleJobNameChange(evt) {
- this.props.onChange(this.props.rowIndex, 'name', evt.target.value)
+ handleJobTitleChange(evt) {
+ this.props.onChange(this.props.rowIndex, 'title', evt.target.value)
}
handlePeopleChange(evt) {
this.props.onChange(this.props.rowIndex, 'people', evt.target.value)
@@ -71,8 +71,8 @@ class JobPickerRow extends React.PureComponent {
this.props.onChange(this.props.rowIndex, 'role', evt)
}
- handleJobDescriptionChange(evt) {
- this.props.onChange(this.props.rowIndex, 'jobDescription', evt.target.value)
+ handleDescriptionChange(evt) {
+ this.props.onChange(this.props.rowIndex, 'description', evt.target.value)
}
resetDuration() {
@@ -101,8 +101,8 @@ class JobPickerRow extends React.PureComponent {
render() {
const { value, rowIndex } = this.props
- const isRowIncomplete = value.name.length > 0 || value.people > 0 || value.duration > 0 || (value.skills && value.skills.length)
- ||(value.role && value.role.value !== null) ||(value.workLoad && value.workLoad.value !== null) || (value.jobDescription.length > 0)
+ const isRowIncomplete = value.title.length > 0 || value.people > 0 || value.duration > 0 || (value.skills && value.skills.length)
+ ||(value.role && value.role.value !== null) ||(value.workLoad && value.workLoad.value !== null) || (value.description.length > 0)
/* Different columns are defined here and used in componsing mobile/desktop views below */
const titleColumn = (
@@ -114,10 +114,11 @@ class JobPickerRow extends React.PureComponent {
@@ -214,7 +215,7 @@ class JobPickerRow extends React.PureComponent {
const roleColumn = (
- Role
+ Role
)
- const jobDescriptionColumn = (
+ const descriptionColumn = (
@@ -258,7 +259,7 @@ class JobPickerRow extends React.PureComponent {
{workLoadColumn}
- {jobDescriptionColumn}
+ {descriptionColumn}
{skillSelectionColumn}
@@ -274,7 +275,7 @@ JobPickerRow.propTypes = {
onDeleteRow: PT.func.isRequired,
value: PT.shape({
people: PT.string.isRequired,
- name: PT.string,
+ title: PT.string,
duration: PT.string.isRequired,
skills: PT.array,
}),
diff --git a/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx b/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx
index 2039de454..123e35692 100644
--- a/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx
+++ b/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx
@@ -31,14 +31,14 @@ class JobsPickerQuestion extends Component {
return true
}
return _.some(value, (v) => {
- return v.name.length && v.people !== '0' && v.duration !== '0' && v.skills.length > 0 && v.workLoad.value !== null && v.role.value !== null && v.jobDescription.length
+ return v.title.length && v.people !== '0' && v.duration !== '0' && v.skills.length > 0 && v.workLoad.value !== null && v.role.value !== null && v.description.length
}) // validation body
},
noPartialFillsExist: (formValues, value) => {
return _.every(value, v => {
- const isOneValueFilled = v.name.length > 0 || v.people > 0 || v.duration > 0 || (v.skills && v.skills.length) || (v.jobDescription && v.jobDescription.length) || (v.workLoad && v.workLoad.value !== null) || (v.role && v.role.value !== null)
- const isAllValuesFilled = v.name.length > 0 && v.people > 0 && v.duration > 0 && v.skills && v.skills.length && v.jobDescription.length && v.workLoad.value !== null && v.role.value !== null
+ const isOneValueFilled = v.title.length > 0 || v.people > 0 || v.duration > 0 || (v.skills && v.skills.length) || (v.description && v.description.length) || (v.workLoad && v.workLoad.value !== null) || (v.role && v.role.value !== null)
+ const isAllValuesFilled = v.title.length > 0 && v.people > 0 && v.duration > 0 && v.skills && v.skills.length && v.description.length && v.workLoad.value !== null && v.role.value !== null
// If one value is filled, all values should be filled to make this row valid. Partial fill is not valid
const isRowValid = !isOneValueFilled || isAllValuesFilled
return isRowValid
@@ -50,16 +50,15 @@ class JobsPickerQuestion extends Component {
getDefaultValue() {
return [{
- name: '',
+ title: '',
role: { value: null, title: 'Select Role'},
people: '0',
duration: '0',
skills: [],
workLoad: { value: null, title: 'Select Workload'},
- jobDescription: '',
+ description: '',
_key: Date.now()
- }
- ]
+ }]
}
onChange(value) {
@@ -84,13 +83,13 @@ class JobsPickerQuestion extends Component {
values = [
...values.slice(0, index),
{
- name: '',
+ title: '',
role: { value: null, title: 'Select Role'},
people: '0',
duration: '0',
skills: [],
workLoad: { value: null, title: 'Select Workload'},
- jobDescription: '',
+ description: '',
_key: Date.now()
},
...values.slice(index)
From 5a74c4217533792d17840d00e486f968c3f82b89 Mon Sep 17 00:00:00 2001
From: maxceem
Date: Thu, 7 Jan 2021 13:27:53 +0200
Subject: [PATCH 14/23] refactor: use unique id for key
---
.../components/JobsPickerQuestion/JobsPickerQuestion.jsx | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx b/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx
index 123e35692..5f55459d1 100644
--- a/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx
+++ b/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx
@@ -57,7 +57,8 @@ class JobsPickerQuestion extends Component {
skills: [],
workLoad: { value: null, title: 'Select Workload'},
description: '',
- _key: Date.now()
+ // we need unique key for proper rendering of the component list
+ _key: _.uniqueId('job_key_')
}]
}
@@ -90,7 +91,8 @@ class JobsPickerQuestion extends Component {
skills: [],
workLoad: { value: null, title: 'Select Workload'},
description: '',
- _key: Date.now()
+ // we need unique key for proper rendering of the component list
+ _key: _.uniqueId('job_key_')
},
...values.slice(index)
]
From 40fa2197a526c38988e2f5ff2c925241450f00ae Mon Sep 17 00:00:00 2001
From: sanju singh
Date: Fri, 8 Jan 2021 20:46:39 +0530
Subject: [PATCH 15/23] Add error message when comments doesn't render properly
---
src/components/Feed/FeedComments.jsx | 17 ++++++++++++++++-
src/components/Feed/FeedComments.scss | 8 ++++++++
src/helpers/markdownToState.js | 9 +++------
3 files changed, 27 insertions(+), 7 deletions(-)
diff --git a/src/components/Feed/FeedComments.jsx b/src/components/Feed/FeedComments.jsx
index 6cbf2a63d..15b517201 100644
--- a/src/components/Feed/FeedComments.jsx
+++ b/src/components/Feed/FeedComments.jsx
@@ -176,6 +176,21 @@ class FeedComments extends React.Component {
}
}
+ convertMdToHtml(markdown) {
+ try {
+ return (
)
+ } catch (e) {
+ return (
+
+
{markdown}
+
+ This message could not be rendered properly, please contact Topcoder Support.
+
+
+ );
+ }
+ }
+
render() {
const {
currentUser, onLoadMoreComments, isLoadingComments, hasMoreComments, onAddNewComment,
@@ -325,7 +340,7 @@ class FeedComments extends React.Component {
canDelete={comments && (idx !== comments.length - 1)} // cannot delete the first post which is now shown as a last one
commentAnchorPrefix={commentAnchorPrefix}
>
-
+ { this.convertMdToHtml(itemContent) }
)
})
diff --git a/src/components/Feed/FeedComments.scss b/src/components/Feed/FeedComments.scss
index e97eef98b..54d4e34ee 100644
--- a/src/components/Feed/FeedComments.scss
+++ b/src/components/Feed/FeedComments.scss
@@ -32,6 +32,14 @@
padding-bottom: 2 * $base-unit;
}
+.comment-render-error {
+ border: 1px dashed $tc-orange-70;
+ color: $tc-orange-70;
+ text-align: center;
+ padding: 2px;
+ margin-top: 5px;
+}
+
.load-more {
background-color: $tc-white;
padding: 2 * $base-unit 0 $base-unit;
diff --git a/src/helpers/markdownToState.js b/src/helpers/markdownToState.js
index 5295fad58..213d567be 100644
--- a/src/helpers/markdownToState.js
+++ b/src/helpers/markdownToState.js
@@ -1,6 +1,5 @@
import {convertFromRaw} from 'draft-js'
import sanitizeHtml from 'sanitize-html'
-import Alert from 'react-s-alert'
const Remarkable = require('remarkable')
// Block level items, key is Remarkable's key for them, value returned is
@@ -353,7 +352,7 @@ function markdownToState(markdown, options = {}) {
}, DefaultBlockType)
}
- let result;
+ let result
try {
result = convertFromRaw({
entityMap,
@@ -361,18 +360,16 @@ function markdownToState(markdown, options = {}) {
});
} catch(error) {
// If any error occurs set value to plain text
- const plainTextBlock = getNewBlock(BlockTypes['paragraph_open']());
+ const plainTextBlock = getNewBlock(BlockTypes['paragraph_open']())
plainTextBlock.text = markdown;
result = convertFromRaw({
entityMap: [],
blocks: [plainTextBlock],
});
-
- Alert.warning('Some message could not be rendered properly, please contact Topcoder Support')
}
- return result;
+ return result
}
export default markdownToState
From 752a698db41a63d0092c1f0702b5fdeaab330822 Mon Sep 17 00:00:00 2001
From: sanju singh
Date: Fri, 8 Jan 2021 20:49:21 +0530
Subject: [PATCH 16/23] Fix: lint error
---
src/components/Feed/FeedComments.jsx | 2 +-
src/helpers/markdownToState.js | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/components/Feed/FeedComments.jsx b/src/components/Feed/FeedComments.jsx
index 15b517201..28a71adec 100644
--- a/src/components/Feed/FeedComments.jsx
+++ b/src/components/Feed/FeedComments.jsx
@@ -187,7 +187,7 @@ class FeedComments extends React.Component {
This message could not be rendered properly, please contact Topcoder Support.
- );
+ )
}
}
diff --git a/src/helpers/markdownToState.js b/src/helpers/markdownToState.js
index b20fe0f92..ddf8180c9 100644
--- a/src/helpers/markdownToState.js
+++ b/src/helpers/markdownToState.js
@@ -361,12 +361,12 @@ function markdownToState(markdown, options = {}) {
} catch(error) {
// If any error occurs set value to plain text
const plainTextBlock = getNewBlock(BlockTypes['paragraph_open']())
- plainTextBlock.text = markdown;
+ plainTextBlock.text = markdown
result = convertFromRaw({
entityMap: [],
blocks: [plainTextBlock],
- });
+ })
}
return result
From 1b93f39f6b69df6710b02fdc742804bdca7e7158 Mon Sep 17 00:00:00 2001
From: yoution
Date: Sat, 9 Jan 2021 11:19:49 +0800
Subject: [PATCH 17/23] fix:issue #4254
---
.../create/components/ProjectSubmitted.jsx | 113 +++++++++++++-----
1 file changed, 81 insertions(+), 32 deletions(-)
diff --git a/src/projects/create/components/ProjectSubmitted.jsx b/src/projects/create/components/ProjectSubmitted.jsx
index a9bb554aa..cd246f8f8 100644
--- a/src/projects/create/components/ProjectSubmitted.jsx
+++ b/src/projects/create/components/ProjectSubmitted.jsx
@@ -7,49 +7,98 @@ import {
CONNECT_MAIN_PAGE_URL, PROJECT_TYPE_TALENT_AS_A_SERVICE, TAAS_APP_URL
} from '../../../config/constants'
-/**
- * Build project URL based on the `type` query param in URL.
- *
- * @param {String} projectId project id
- */
-const formatProjectURL = (projectId = '') => {
- const { type } = qs.parse(window.location.search)
+class ProjectSubmitted extends React.Component {
+ /**
+ * Build project URL based on the `type` query param in URL.
+ *
+ * @param {boolean} isTaas
+ * @param {String} projectId project id
+ */
+ getProjectUrl(isTaas, projectId = '') {
+ const url = isTaas
+ // if the project type is TaaS, then use link to TaaS App
+ ? `${TAAS_APP_URL}/myteams/${projectId}`
+ // otherwise use link inside Connect App
+ : `${CONNECT_MAIN_PAGE_URL}/projects/${projectId}`
- const url = type === PROJECT_TYPE_TALENT_AS_A_SERVICE
- // if the project type is TaaS, then use link to TaaS App
- ? `${TAAS_APP_URL}/myteams/${projectId}`
- // otherwise use link inside Connect App
- : `${CONNECT_MAIN_PAGE_URL}/projects/${projectId}`
+ return url
+ }
- return url
-}
+ getPageConfiguration() {
+ const { type } = qs.parse(window.location.search)
+ const isTaas = type === PROJECT_TYPE_TALENT_AS_A_SERVICE
+
+ const projectId = this.props.params.status || this.props.projectId
+
+ const project = {
+ headerSubTitle: 'Your project has been created',
+ textBody: (
+
+ Topcoder will be contacting you soon to discuss your project proposal.
+
+
+
+In the meantime, get a jump on the process by inviting your coworkers to your project and securely share any detailed requirements documents you have inside your project.
+
+
+ ),
+ leftButton: {
+ header: 'Go to Project',
+ subText: 'Invite your team members and share requirements',
+ url: this.getProjectUrl(isTaas, projectId)
+ },
+ rightButton: {
+ header: 'All Projects',
+ subText: 'View all of your projects',
+ url: this.getProjectUrl(isTaas)
+ },
+ }
+
+ const taas = {
+ headerSubTitle: 'Your talent request has been created',
+ textBody: (
+
+ Topcoder will be contacting you soon to discuss your talent needs.
+
+ ),
+ leftButton: {
+ header: 'View Talent Request',
+ subText: 'Modify your request and track fulfillment',
+ url: this.getProjectUrl(isTaas, projectId)
+ },
+ rightButton: {
+ header: 'All Projects',
+ subText: 'View all of your projects',
+ url: this.getProjectUrl(isTaas)
+ },
+ }
+
+ return isTaas? taas: project
+ }
-class ProjectSubmitted extends React.Component {
render() {
- const projectUrl = formatProjectURL(this.props.params.status || this.props.projectId)
- const projectsListUrl = formatProjectURL()
+
+ const {
+ headerSubTitle,
+ textBody,
+ leftButton,
+ rightButton
+ } = this.getPageConfiguration()
return (
Congratulations!
-
Your project has been created
-
- Topcoder will be contacting you soon to discuss your project proposal.
-
-
-
-In the meantime, get a jump on the process by inviting your coworkers to your project and securely share any detailed requirements documents you have inside your project.
-
-
+
{headerSubTitle}
+ {textBody}
From 53a8e4033c715215ea21088901c0891c1feae23e Mon Sep 17 00:00:00 2001
From: yoution
Date: Sat, 9 Jan 2021 17:44:23 +0800
Subject: [PATCH 18/23] fix:issue-4206
---
.../JobsPickerQuestion/JobsPickerQuestion.jsx | 61 +++++++++++--------
1 file changed, 37 insertions(+), 24 deletions(-)
diff --git a/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx b/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx
index 5f55459d1..5719ddcb8 100644
--- a/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx
+++ b/src/projects/detail/components/JobsPickerQuestion/JobsPickerQuestion.jsx
@@ -17,6 +17,24 @@ class JobsPickerQuestion extends Component {
this.insertJob = this.insertJob.bind(this)
this.removeJob = this.removeJob.bind(this)
this.setValidator(props)
+
+ const { getValue } = props
+ let values = getValue()
+ if (values) {
+ values = _.map(values, (v) => {
+ return {
+ ...v,
+ // we need unique key for proper rendering of the component list
+ _key: _.uniqueId('job_key_')
+ }
+ })
+ }else {
+ values = this.getDefaultValue()
+ }
+
+ this.state = {
+ values
+ }
}
componentWillReceiveProps(nextProps) {
@@ -62,57 +80,52 @@ class JobsPickerQuestion extends Component {
}]
}
- onChange(value) {
+ onChange(values) {
const {setValue, name} = this.props
- setValue(value)
- this.props.onChange(name, value)
+ this.setState({values})
+ // remove unique _key
+ const newValues = _.map(values, (v) => {
+ const cloneV = {...v}
+ delete cloneV['_key']
+ return cloneV
+ })
+ setValue(newValues)
+ this.props.onChange(name, newValues)
}
handleValueChange(index, field, value) {
- const { getValue } = this.props
- let values = getValue() || this.getDefaultValue()
- values = [...values.slice(0, index), { ...values[index], [field]: value }, ...values.slice(index + 1)]
-
+ let {values} = this.state
+ const currentValue = values[index]
+ currentValue[field] = value
+ values = [...values.slice(0, index), {...currentValue}, ...values.slice(index + 1)]
this.onChange(values)
}
insertJob(index) {
- const { getValue } = this.props
- let values = getValue() || this.getDefaultValue()
+ let {values} = this.state
values = [
...values.slice(0, index),
- {
- title: '',
- role: { value: null, title: 'Select Role'},
- people: '0',
- duration: '0',
- skills: [],
- workLoad: { value: null, title: 'Select Workload'},
- description: '',
- // we need unique key for proper rendering of the component list
- _key: _.uniqueId('job_key_')
- },
+ ...this.getDefaultValue(),
...values.slice(index)
]
this.onChange(values)
}
removeJob(index) {
- const { getValue } = this.props
- let values = getValue() || this.getDefaultValue()
+ let {values} = this.state
values = [...values.slice(0, index), ...values.slice(index + 1)]
this.onChange(values)
}
render() {
- const { wrapperClass, getValue } = this.props
+ const { wrapperClass } = this.props
const errorMessage =
this.props.getErrorMessage() || this.props.validationError
const hasError = !this.props.isPristine() && !this.props.isValid()
- const values = getValue() || this.getDefaultValue()
+ const {values} = this.state
return (
From c3abca6c83536cd8319bc11eed747799faf13229 Mon Sep 17 00:00:00 2001
From: maxceem
Date: Sun, 10 Jan 2021 10:55:18 +0200
Subject: [PATCH 19/23] fix: make "All Projects" button lead to Connect
ref issue #4254
---
src/projects/create/components/ProjectSubmitted.jsx | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/projects/create/components/ProjectSubmitted.jsx b/src/projects/create/components/ProjectSubmitted.jsx
index cd246f8f8..5a0e4819f 100644
--- a/src/projects/create/components/ProjectSubmitted.jsx
+++ b/src/projects/create/components/ProjectSubmitted.jsx
@@ -11,11 +11,11 @@ class ProjectSubmitted extends React.Component {
/**
* Build project URL based on the `type` query param in URL.
*
- * @param {boolean} isTaas
+ * @param {boolean} isTaas
* @param {String} projectId project id
*/
getProjectUrl(isTaas, projectId = '') {
- const url = isTaas
+ const url = isTaas
// if the project type is TaaS, then use link to TaaS App
? `${TAAS_APP_URL}/myteams/${projectId}`
// otherwise use link inside Connect App
@@ -28,7 +28,7 @@ class ProjectSubmitted extends React.Component {
const { type } = qs.parse(window.location.search)
const isTaas = type === PROJECT_TYPE_TALENT_AS_A_SERVICE
- const projectId = this.props.params.status || this.props.projectId
+ const projectId = this.props.params.status || this.props.projectId
const project = {
headerSubTitle: 'Your project has been created',
@@ -69,7 +69,7 @@ In the meantime, get a jump on the process by inviting your coworkers to your pr
rightButton: {
header: 'All Projects',
subText: 'View all of your projects',
- url: this.getProjectUrl(isTaas)
+ url: this.getProjectUrl(false) // also showing link to Connect App Project List
},
}
@@ -79,7 +79,7 @@ In the meantime, get a jump on the process by inviting your coworkers to your pr
render() {
const {
- headerSubTitle,
+ headerSubTitle,
textBody,
leftButton,
rightButton
From 5e229b1a53357787ce0eb9ad3526a509151d7497 Mon Sep 17 00:00:00 2001
From: maxceem
Date: Mon, 11 Jan 2021 22:47:50 +0200
Subject: [PATCH 20/23] feat: project submitted buttons change
switch primary and secondary buttons
---
.../create/components/ProjectSubmitted.jsx | 24 +++++++++----------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/src/projects/create/components/ProjectSubmitted.jsx b/src/projects/create/components/ProjectSubmitted.jsx
index 5a0e4819f..ccf6afcb8 100644
--- a/src/projects/create/components/ProjectSubmitted.jsx
+++ b/src/projects/create/components/ProjectSubmitted.jsx
@@ -43,15 +43,15 @@ In the meantime, get a jump on the process by inviting your coworkers to your pr
),
leftButton: {
- header: 'Go to Project',
- subText: 'Invite your team members and share requirements',
- url: this.getProjectUrl(isTaas, projectId)
- },
- rightButton: {
header: 'All Projects',
subText: 'View all of your projects',
url: this.getProjectUrl(isTaas)
},
+ rightButton: {
+ header: 'Go to Project',
+ subText: 'Invite your team members and share requirements',
+ url: this.getProjectUrl(isTaas, projectId)
+ },
}
const taas = {
@@ -62,15 +62,15 @@ In the meantime, get a jump on the process by inviting your coworkers to your pr
),
leftButton: {
- header: 'View Talent Request',
- subText: 'Modify your request and track fulfillment',
- url: this.getProjectUrl(isTaas, projectId)
- },
- rightButton: {
header: 'All Projects',
subText: 'View all of your projects',
url: this.getProjectUrl(false) // also showing link to Connect App Project List
},
+ rightButton: {
+ header: 'View Talent Request',
+ subText: 'Modify your request and track fulfillment',
+ url: this.getProjectUrl(isTaas, projectId)
+ },
}
return isTaas? taas: project
@@ -92,11 +92,11 @@ In the meantime, get a jump on the process by inviting your coworkers to your pr
{headerSubTitle}
{textBody}
-
+
{leftButton.header}
{leftButton.subText}
-
+
{rightButton.header}
{rightButton.subText}
From 31bed5ebd5ca8f122ea38c7e7ded4869ef9af084 Mon Sep 17 00:00:00 2001
From: yoution
Date: Tue, 12 Jan 2021 18:30:02 +0800
Subject: [PATCH 21/23] fix: #4206 add trim()
---
.../detail/components/JobPickerRow/JobPickerRow.jsx | 8 ++++----
.../components/JobsPickerQuestion/JobsPickerQuestion.jsx | 6 +++---
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/projects/detail/components/JobPickerRow/JobPickerRow.jsx b/src/projects/detail/components/JobPickerRow/JobPickerRow.jsx
index 2188843af..6b3b08bf2 100644
--- a/src/projects/detail/components/JobPickerRow/JobPickerRow.jsx
+++ b/src/projects/detail/components/JobPickerRow/JobPickerRow.jsx
@@ -101,8 +101,8 @@ class JobPickerRow extends React.PureComponent {
render() {
const { value, rowIndex } = this.props
- const isRowIncomplete = value.title.length > 0 || value.people > 0 || value.duration > 0 || (value.skills && value.skills.length)
- ||(value.role && value.role.value !== null) ||(value.workLoad && value.workLoad.value !== null) || (value.description.length > 0)
+ const isRowIncomplete = value.title.trim().length > 0 || value.people > 0 || value.duration > 0 || (value.skills && value.skills.length)
+ ||(value.role && value.role.value !== null) ||(value.workLoad && value.workLoad.value !== null) || (value.description.trim().length > 0)
/* Different columns are defined here and used in componsing mobile/desktop views below */
const titleColumn = (
@@ -115,7 +115,7 @@ class JobPickerRow extends React.PureComponent {
type="text"
maxLength={100}
value={value.title}
- className={cn('tc-file-field__inputs', { error: isRowIncomplete && !value.title })}
+ className={cn('tc-file-field__inputs', { error: isRowIncomplete && !value.title.trim() })}
name="title"
onChange={this.handleJobTitleChange}
placeholder="Job Title"
@@ -233,7 +233,7 @@ class JobPickerRow extends React.PureComponent {