diff --git a/config/index.js b/config/index.js index c17873ef..4cbf464b 100644 --- a/config/index.js +++ b/config/index.js @@ -1,7 +1,7 @@ /* global process */ module.exports = (() => { - const env = process.env.APPENV || "prod"; + const env = process.env.APPENV || "dev"; console.info(`APPENV: "${env}"`); diff --git a/src/components/DateInput/index.jsx b/src/components/DateInput/index.jsx index 3bb3c89e..4f0192d3 100644 --- a/src/components/DateInput/index.jsx +++ b/src/components/DateInput/index.jsx @@ -16,6 +16,7 @@ const DateInput = (props) => { dateFormat="MM/dd/yyyy" placeholderText={props.placeholder} selected={props.value} + disabled={props.disabled} onChange={props.onChange} onBlur={props.onBlur} onCalendarClose={props.onBlur} @@ -28,6 +29,7 @@ const DateInput = (props) => { DateInput.propTypes = { value: PT.string, onChange: PT.func.isRequired, + disabled: PT.bool, placeholder: PT.string, onBlur: PT.func, onFocus: PT.func, diff --git a/src/components/DateInput/styles.module.scss b/src/components/DateInput/styles.module.scss index 10670205..e5472845 100644 --- a/src/components/DateInput/styles.module.scss +++ b/src/components/DateInput/styles.module.scss @@ -9,6 +9,10 @@ border-color: #fe665d; } } + + input:disabled:not(:focus) { + border: 1px solid #ddd; + } } .datepicker-wrapper > div:nth-child(2) > div:nth-child(2) { diff --git a/src/components/FormField/index.jsx b/src/components/FormField/index.jsx index 733d1d27..f43d48fc 100644 --- a/src/components/FormField/index.jsx +++ b/src/components/FormField/index.jsx @@ -37,6 +37,7 @@ const FormField = ({ field }) => { { value={input?.value ?? ""} isRequired={field.isRequired} type="number" + disabled={field.disabled} minValue={field.minValue} onChange={input.onChange} onBlur={input.onBlur} @@ -64,6 +66,7 @@ const FormField = ({ field }) => { { placeholder={field.placeholder} value={input?.value ?? ""} onChange={input.onChange} + disabled={field.disabled} onBlur={input.onBlur} onFocus={input.onFocus} className={meta.error && meta.touched ? "error" : ""} diff --git a/src/components/MarkdownEditor/index.jsx b/src/components/MarkdownEditor/index.jsx index bc967281..6c38b851 100644 --- a/src/components/MarkdownEditor/index.jsx +++ b/src/components/MarkdownEditor/index.jsx @@ -8,7 +8,6 @@ import cn from "classnames"; import TuiEditor from "../TuiEditor"; import MarkdownEditorViewer from "../MarkdownEditorViewer"; import styles from "./styles.module.scss"; -import { DISABLED_DESCRIPTION_MESSAGE } from "constants"; const MarkdownEditor = (props) => { const editorElement = useRef(null); @@ -21,7 +20,9 @@ const MarkdownEditor = (props) => { return (
-
{DISABLED_DESCRIPTION_MESSAGE}
+ {props.errorMessage && ( +
{props.errorMessage}
+ )}
); } @@ -34,21 +35,21 @@ const MarkdownEditor = (props) => { onChange={onChange} initialValue={props.value} toolbarItems={[ - 'heading', - 'bold', - 'italic', - 'strike', - 'code', - 'divider', - 'quote', - 'codeblock', - 'hr', - 'divider', - 'ul', - 'ol', - 'divider', - 'image', - 'link', + "heading", + "bold", + "italic", + "strike", + "code", + "divider", + "quote", + "codeblock", + "hr", + "divider", + "ul", + "ol", + "divider", + "image", + "link", ]} plugins={[]} /> @@ -59,6 +60,7 @@ const MarkdownEditor = (props) => { MarkdownEditor.propTypes = { value: PropTypes.string, disabled: PropTypes.bool, + errorMessage: PropTypes.string, className: PropTypes.string, onChange: PropTypes.func, onFocus: PropTypes.func, diff --git a/src/components/MarkdownEditor/styles.module.scss b/src/components/MarkdownEditor/styles.module.scss index 5392c803..a901cd13 100644 --- a/src/components/MarkdownEditor/styles.module.scss +++ b/src/components/MarkdownEditor/styles.module.scss @@ -1,14 +1,16 @@ @import "styles/include"; +// we use viewer mode to show editor when it's "disabled" .editor-viewer { > div:first-child { - border: 1px solid #aaaaab; + border: 1px solid #ddd; border-radius: 4px; overflow: hidden; box-sizing: border-box; padding: 16px 25px 0px 25px; height: 280px; overflow-y: auto; + background: #fafafb; } .message { @include font-roboto; diff --git a/src/components/ReactSelect/index.jsx b/src/components/ReactSelect/index.jsx index 1101fe59..29cf6298 100644 --- a/src/components/ReactSelect/index.jsx +++ b/src/components/ReactSelect/index.jsx @@ -14,9 +14,11 @@ const ReactSelect = (props) => { control: (provided, state) => ({ ...provided, minHeight: "40px", - border: "1px solid #aaaaab", + border:state.isDisabled ? "1px solid #ddd" : "1px solid #aaaaab", borderColor: state.isFocused ? "#55a5ff" : "#aaaaab", boxShadow: state.isFocused ? "0 0 2px 1px #cee6ff" : provided.boxShadow, + backgroundColor: state.isDisabled ? "#fafafb" : provided.backgroundColor, + color: state.isDisabled ? "#6b6b6b" : provided.color, }), menu: (provided) => ({ ...provided, @@ -53,16 +55,21 @@ const ReactSelect = (props) => { textAlign: "left", fontWeight: "400", }), - multiValue: (provided) => ({ + multiValue: (provided, state) => ({ ...provided, margin: "3px 3px", - color: "#AAAAAA", + color: state.isDisabled ? "#808080" : "#AAAAAA", + paddingRight: state.isDisabled ? "6px" : "0", fontFamily: "Roboto", fontSize: "14px", lineHeight: "22px", textAlign: "left", borderRadius: "5px", }), + multiValueRemove: (provided, state) => ({ + ...provided, + display: state.isDisabled ? "none" : provided.display, + }), dropdownIndicator: () => ({ display: "none", }), diff --git a/src/components/TextInput/index.jsx b/src/components/TextInput/index.jsx index 58d92d7c..bc634a30 100644 --- a/src/components/TextInput/index.jsx +++ b/src/components/TextInput/index.jsx @@ -14,6 +14,7 @@ function TextInput(props) { styleName={cn("TextInput", props.className, { readonly: props.readonly })} maxLength={props.maxLength} min={props.minValue} + disabled={props.disabled} onChange={(event) => { if (props.type === "number") { if (event.target.value >= props.minValue) { @@ -47,6 +48,7 @@ TextInput.defaultProps = { maxLength: Number.MAX_VALUE, placeholder: "", minValue: 0, + disabled: false, step: null, }; @@ -58,6 +60,7 @@ TextInput.propTypes = { onFocus: PT.func, placeholder: PT.string, value: PT.string.isRequired, + disabled: PT.bool, type: PT.string.isRequired, readonly: PT.bool, minValue: PT.number, diff --git a/src/components/TextInput/styles.module.scss b/src/components/TextInput/styles.module.scss index 197d304a..0e984af7 100644 --- a/src/components/TextInput/styles.module.scss +++ b/src/components/TextInput/styles.module.scss @@ -24,3 +24,7 @@ box-shadow: none !important; } } + +input.TextInput:not([type="checkbox"]):disabled { + border: 1px solid #ddd; +} diff --git a/src/routes/JobForm/index.jsx b/src/routes/JobForm/index.jsx index 622188e9..05bc0a29 100644 --- a/src/routes/JobForm/index.jsx +++ b/src/routes/JobForm/index.jsx @@ -108,6 +108,11 @@ const JobForm = ({ teamId, jobId }) => { configuration={getEditJobConfig( options, job.isApplicationPageActive, + isEdit + ? job.status === "assigned" || + job.status === "closed" || + job.status === "cancelled" + : false, onSubmit )} initialValue={job} diff --git a/src/routes/JobForm/utils.js b/src/routes/JobForm/utils.js index feb9ca82..cc6743ae 100644 --- a/src/routes/JobForm/utils.js +++ b/src/routes/JobForm/utils.js @@ -3,6 +3,7 @@ */ import { PERMISSIONS } from "constants/permissions"; import { hasPermission } from "utils/permissions"; +import { DISABLED_DESCRIPTION_MESSAGE } from "constants"; import { RATE_TYPE_OPTIONS, STATUS_OPTIONS, @@ -28,11 +29,13 @@ const EDIT_JOB_ROWS = [ * return edit job configuration * @param {any} skillOptions skill options * @param {boolean} isMarkdownEditorDisabled is markedownEditor disabled + * @param {onlyEnableStatus} only can select status field * @param {func} onSubmit submit callback */ export const getEditJobConfig = ( skillOptions, isMarkdownEditorDisabled, + onlyEnableStatus, onSubmit ) => { return { @@ -44,13 +47,15 @@ export const getEditJobConfig = ( validationMessage: "Please, enter Job Name", name: "title", maxLength: 128, + disabled: onlyEnableStatus, placeholder: "Job Name", }, { label: "Job Description", type: FORM_FIELD_TYPE.MARKDOWNEDITOR, name: "description", - disabled: isMarkdownEditorDisabled, + disabled: isMarkdownEditorDisabled || onlyEnableStatus, + errorMessage: isMarkdownEditorDisabled && DISABLED_DESCRIPTION_MESSAGE, placeholder: "Job Description", }, { @@ -61,6 +66,7 @@ export const getEditJobConfig = ( name: "numPositions", minValue: 1, placeholder: "Number Of Opening", + disabled: onlyEnableStatus, step: 1, }, { @@ -68,12 +74,14 @@ export const getEditJobConfig = ( type: FORM_FIELD_TYPE.SELECT, isMulti: true, name: "skills", + disabled: onlyEnableStatus, selectOptions: skillOptions, }, { label: "Start Date", type: FORM_FIELD_TYPE.DATE, name: "startDate", + disabled: onlyEnableStatus, placeholder: "Start Date", }, { @@ -82,24 +90,28 @@ export const getEditJobConfig = ( name: "duration", minValue: 1, placeholder: "Duration", + disabled: onlyEnableStatus, step: 1, }, { label: "Resource Type", type: FORM_FIELD_TYPE.SELECT, name: "resourceType", + disabled: onlyEnableStatus, selectOptions: RESOURCE_TYPE_OPTIONS, }, { label: "Resource Rate Frequency", type: FORM_FIELD_TYPE.SELECT, name: "rateType", + disabled: onlyEnableStatus, selectOptions: RATE_TYPE_OPTIONS, }, { label: "Workload", type: FORM_FIELD_TYPE.SELECT, name: "workload", + disabled: onlyEnableStatus, selectOptions: WORKLOAD_OPTIONS, }, { diff --git a/src/services/teams.js b/src/services/teams.js index 659ebce2..b8053cb6 100644 --- a/src/services/teams.js +++ b/src/services/teams.js @@ -15,7 +15,8 @@ import config from "../../config"; export const getMyTeams = (name, page = 1, perPage) => { let query = `page=${page}&perPage=${perPage}`; if (name) { - query += `&name=*${name}*`; // wrap with asterisks to search by substrings + // wrap with quotes to fix issue https://github.com/topcoder-platform/taas-app/issues/46 + query += `&name="${name}"`; } return axios.get(`${config.API.V5}/taas-teams?${query}`); diff --git a/webpack.config.js b/webpack.config.js index ec47620d..72e7b561 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -77,6 +77,11 @@ module.exports = (webpackConfigEnv) => { // ignore moment locales to reduce bundle size by 64kb gzipped // see solution details https://stackoverflow.com/questions/25384360/how-to-prevent-moment-js-from-loading-locales-with-webpack/25426019#25426019 new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + new webpack.DefinePlugin({ + 'process.env': { + APPENV: JSON.stringify(process.env.APPENV), + }, + }), ], }); };