diff --git a/src/__tests__/integration/app.test.js b/src/__tests__/integration/app.test.js index 15cfd1c9..c1966089 100644 --- a/src/__tests__/integration/app.test.js +++ b/src/__tests__/integration/app.test.js @@ -1,4 +1,4 @@ -import { integrationTest } from './index'; +import { integrationTest, toggleSettingsCheckbox } from './index'; import Loading from '../../components/layouts/pages/loading/Loading'; const { REACT_APP_VERSION } = process.env; @@ -24,4 +24,17 @@ describe('App', () => { } ) ); + + it( + 'Turn settings on and off', + integrationTest((store, component) => { + expect(component.find('.MuiStepLabel-root')).toHaveLength(3); + + toggleSettingsCheckbox(component, true); + expect(component.find('.MuiStepLabel-root')).toHaveLength(4); + + toggleSettingsCheckbox(component, false); + expect(component.find('.MuiStepLabel-root')).toHaveLength(3); + }) + ); }); diff --git a/src/__tests__/integration/index.js b/src/__tests__/integration/index.js index 642b55c1..ea24672f 100644 --- a/src/__tests__/integration/index.js +++ b/src/__tests__/integration/index.js @@ -7,6 +7,7 @@ import fs from 'mz/fs'; import App from '../../components/App'; import configureStore from '../../store/rootStore'; +import Checkbox from '@material-ui/core/Checkbox'; import { getInfo as getFileServiceInfo, uploadFile, getFileContent } from '../../services/fileService'; import { getInfo as getJobServiceInfo, createJob, updateJob, executeJob, getJob } from '../../services/jobService'; import { getList as getProfilesList } from '../../services/profiles'; @@ -242,8 +243,8 @@ export const navigateWithHeaderLink = (component, linkSelector) => { component.update(); }; -export const getNextStepButton = component => component.find('.page-navigation__end button'); -export const getPrevStepButton = component => component.find('.page-navigation__start button'); +export const getNextStepButton = component => component.find('.page-navigation > .nav-button_forward'); +export const getPrevStepButton = component => component.find('.page-navigation > .nav-button_back'); export const moveBack = component => { getPrevStepButton(component).simulate('click', { button: 0 }); @@ -262,3 +263,13 @@ export const skipLoadingPage = async (store, component) => { export const isFileStored = state => state.pdfFiles.length; export const stepFinished = key => state => getProgress(state).steps.find(({ stepKey }) => stepKey === key)?.completed; + +export const toggleSettingsCheckbox = (component, checked) => { + expect(component.find(Checkbox)).toHaveLength(1); + component + .find(Checkbox) + .props() + .onChange({ target: { checked } }); + component.update(); + expect(component.find(Checkbox).props().checked).toBe(checked); +}; diff --git a/src/__tests__/integration/settings.test.js b/src/__tests__/integration/settings.test.js index 0c8b46c9..0eb812a2 100644 --- a/src/__tests__/integration/settings.test.js +++ b/src/__tests__/integration/settings.test.js @@ -1,4 +1,11 @@ -import { DEFAULT_STARTUP_RESPONSES, TEST_FILE, integrationTest, storeFile, moveNext } from './index'; +import { + DEFAULT_STARTUP_RESPONSES, + TEST_FILE, + integrationTest, + storeFile, + moveNext, + toggleSettingsCheckbox, +} from './index'; import MaterialSelect from '@material-ui/core/Select'; import Settings from '../../components/layouts/pages/settings/Settings'; @@ -20,6 +27,7 @@ describe('Settings', () => { integrationTest( async (store, component) => { await storeFile(component, store); + toggleSettingsCheckbox(component, true); moveNext(component); expect(component.find(Settings)).toHaveLength(1); @@ -39,6 +47,7 @@ describe('Settings', () => { 'Profiles list loaded', integrationTest(async (store, component) => { await storeFile(component, store); + toggleSettingsCheckbox(component, true); moveNext(component); expect(component.find(Settings)).toHaveLength(1); @@ -57,6 +66,7 @@ describe('Settings', () => { integrationTest( async (store, component) => { await storeFile(component, store); + toggleSettingsCheckbox(component, true); moveNext(component); expect(component.find(Settings)).toHaveLength(1); expect(getProfileSelectError(component).text()).toBe( @@ -76,6 +86,7 @@ describe('Settings', () => { 'Profile changed', integrationTest(async (store, component) => { await storeFile(component, store, TEST_FILE); + toggleSettingsCheckbox(component, true); moveNext(component); expect(getProfileValue(store)).toEqual(PROFILE_VALUES[0]); diff --git a/src/__tests__/integration/upload.test.js b/src/__tests__/integration/upload.test.js index 378b3145..f77c50a4 100644 --- a/src/__tests__/integration/upload.test.js +++ b/src/__tests__/integration/upload.test.js @@ -1,4 +1,12 @@ -import { TEST_FILE, integrationTest, getNextStepButton, storeFile, moveBack, moveNext } from './index'; +import { + TEST_FILE, + integrationTest, + getNextStepButton, + storeFile, + moveBack, + moveNext, + toggleSettingsCheckbox, +} from './index'; const EMPTY_DROPZONE_TEXT = 'Drop a PDF file, or click to select a file'; const FAILED_FILE = { @@ -29,7 +37,7 @@ describe('Upload', () => { integrationTest(async (store, component) => { await storeFile(component, store); - expect(getDropzoneText(component)).toEqual(`${TEST_FILE.name} - ${TEST_FILE.size}`); + expect(getDropzoneText(component)).toEqual(`${TEST_FILE.name}${TEST_FILE.size}`); expect(getNextStepButton(component).props().disabled).toBeFalsy(); }) ); @@ -58,11 +66,12 @@ describe('Upload', () => { 'File still attached after going back from next step', integrationTest(async (store, component) => { await storeFile(component, store); + toggleSettingsCheckbox(component, true); moveNext(component); moveBack(component); - expect(getDropzoneText(component)).toEqual(`${TEST_FILE.name} - ${TEST_FILE.size}`); + expect(getDropzoneText(component)).toEqual(`${TEST_FILE.name}${TEST_FILE.size}`); }) ); }); diff --git a/src/__tests__/integration/validation.test.js b/src/__tests__/integration/validation.test.js index da87d12e..3c218c3c 100644 --- a/src/__tests__/integration/validation.test.js +++ b/src/__tests__/integration/validation.test.js @@ -21,9 +21,6 @@ describe('Validation', () => { integrationTest(async (store, component) => { await storeFile(component, store); - // Move to settings - moveNext(component); - // Click validate button moveNext(component); expect(createJob).toHaveBeenCalledTimes(1); diff --git a/src/components/layouts/pages/results/Results.js b/src/components/layouts/pages/results/Results.js index 58c2ef37..2c2c09fc 100644 --- a/src/components/layouts/pages/results/Results.js +++ b/src/components/layouts/pages/results/Results.js @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React, { useCallback } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { Redirect, useHistory, useParams } from 'react-router-dom'; @@ -7,32 +7,18 @@ import _ from 'lodash'; import AppPages from '../../../AppPages'; import { JOB_STATUS, TASK_STATUS } from '../../../../store/constants'; import { getJobStatus, getTaskStatus } from '../../../../store/job/selectors'; +import { isCompliant } from '../../../../store/job/result/selectors'; import { reset } from '../../../../store/application/actions'; +import Button from '../../../shared/button/Button'; import WizardStep from '../../wizardStep/WizardStep'; import Summary from './summary/Summary'; import PageNavigation from '../../../shared/pageNavigation/PageNavigation'; -import { isCompliant } from '../../../../store/job/result/selectors'; +import LinkButton from '../../../shared/linkButton/LinkButton'; -function Results({ jobStatus, taskStatus, compliant, onBackClick }) { +function Results({ jobStatus, taskStatus, compliant, resetApp }) { const { id: jobId } = useParams(); const history = useHistory(); - - const backButton = useMemo( - () => ({ - label: 'Validate another file', - onClick: () => onBackClick(history), - }), - [history, onBackClick] - ); - - const forwardButton = useMemo( - () => ({ - label: 'Inspect errors', - to: AppPages.INSPECT.url(jobId), - disabled: compliant, - }), - [compliant, jobId] - ); + const onBackClick = useCallback(() => resetApp(history), [history, resetApp]); if (jobStatus === JOB_STATUS.NOT_FOUND) { return ; @@ -44,7 +30,19 @@ function Results({ jobStatus, taskStatus, compliant, onBackClick }) { return ( - + + + + Inspect errors + + ); } @@ -53,7 +51,7 @@ Results.propTypes = { jobStatus: PropTypes.oneOf(_.values(JOB_STATUS)), taskStatus: PropTypes.oneOf(_.values(TASK_STATUS)), compliant: PropTypes.bool.isRequired, - onBackClick: PropTypes.func.isRequired, + resetApp: PropTypes.func.isRequired, }; function mapStateToProps(state) { @@ -66,7 +64,7 @@ function mapStateToProps(state) { function mapDispatchToProps(dispatch) { return { - onBackClick: history => dispatch(reset(history)), + resetApp: history => dispatch(reset(history)), }; } diff --git a/src/components/layouts/pages/results/summary/Summary.js b/src/components/layouts/pages/results/summary/Summary.js index 0e978d5e..555d127e 100644 --- a/src/components/layouts/pages/results/summary/Summary.js +++ b/src/components/layouts/pages/results/summary/Summary.js @@ -23,7 +23,7 @@ function Summary({ fileInfo, resultSummary }) { const compliancePercent = useMemo(() => calculateCompliance(resultSummary), [resultSummary]); return ( -

{fileInfo.name}

+

{fileInfo.name}

({ - label: 'Validate', - disabled: !allServicesAvailable, - onClick: () => onValidateClick(), - }), - [allServicesAvailable, onValidateClick] - ); + const onForwardClick = useCallback(() => onValidateClick(), [onValidateClick]); if (jobId) { // Once job is initialized and we know its ID redirect to status page to track its progress @@ -42,7 +31,20 @@ function Settings(props) {
- + + + Upload files + + + ); } diff --git a/src/components/layouts/pages/upload/Upload.js b/src/components/layouts/pages/upload/Upload.js index ad269b36..5c5176f6 100644 --- a/src/components/layouts/pages/upload/Upload.js +++ b/src/components/layouts/pages/upload/Upload.js @@ -1,39 +1,73 @@ import React, { useMemo } from 'react'; import PropTypes from 'prop-types'; -import { hasFilesAttached } from '../../../../store/pdfFiles/selectors'; import { connect } from 'react-redux'; +import { Redirect, useHistory } from 'react-router-dom'; + import AppPages from '../../../AppPages'; +import { validate } from '../../../../store/job/actions'; +import { hasFilesAttached } from '../../../../store/pdfFiles/selectors'; +import { getUseSettings } from '../../../../store/application/selectors'; +import { getJobId } from '../../../../store/job/selectors'; import Dropzone from './dropzone/Dropzone'; import WizardStep from '../../wizardStep/WizardStep'; import PageNavigation from '../../../shared/pageNavigation/PageNavigation'; +import SettingsCheckbox from './settingsCheckbox/SettingsCheckbox'; +import Button from '../../../shared/button/Button'; -function Upload(props) { - const { filesAttached } = props; - const forwardButton = useMemo( - () => ({ - label: 'Configure job', - to: AppPages.SETTINGS, - disabled: !filesAttached, - }), - [filesAttached] - ); +function Upload({ filesAttached, isUseSettings, jobId, onValidateClick }) { + const history = useHistory(); + const forwardLabel = useMemo(() => (isUseSettings ? 'Configure' : 'Validate'), [isUseSettings]); + const onForwardClick = useMemo(() => { + if (isUseSettings) { + return () => history.push(AppPages.SETTINGS); + } + + return onValidateClick; + }, [history, isUseSettings, onValidateClick]); + + if (!isUseSettings && jobId) { + // Once job is initialized and we know its ID redirect to status page to track its progress + return ; + } return ( - + + + + ); } Upload.propTypes = { + jobId: PropTypes.string, + isUseSettings: PropTypes.bool.isRequired, filesAttached: PropTypes.bool.isRequired, + onValidateClick: PropTypes.func.isRequired, }; const mapStateToProps = state => { return { filesAttached: hasFilesAttached(state), + isUseSettings: getUseSettings(state), + jobId: getJobId(state), + }; +}; + +const mapDispatchToProps = dispatch => { + return { + onValidateClick: () => dispatch(validate()), }; }; -export default connect(mapStateToProps)(Upload); +export default connect(mapStateToProps, mapDispatchToProps)(Upload); diff --git a/src/components/layouts/pages/upload/dropzone/Dropzone.scss b/src/components/layouts/pages/upload/dropzone/Dropzone.scss index ceb47fea..2af8ce19 100644 --- a/src/components/layouts/pages/upload/dropzone/Dropzone.scss +++ b/src/components/layouts/pages/upload/dropzone/Dropzone.scss @@ -10,8 +10,7 @@ flex-direction: column; &__container { - width: 70%; - max-width: 700px; + width: 80%; height: 100px; margin: auto; padding: 20px; diff --git a/src/components/layouts/pages/upload/dropzone/DropzoneText.js b/src/components/layouts/pages/upload/dropzone/DropzoneText.js index ea969ba0..bc262f86 100644 --- a/src/components/layouts/pages/upload/dropzone/DropzoneText.js +++ b/src/components/layouts/pages/upload/dropzone/DropzoneText.js @@ -12,7 +12,7 @@ function DropzoneText(props) { {files.length ? ( <> {files[0].name} - - {formatFileSize(files[0])} + {formatFileSize(files[0])} ) : ( DROPZONE_TEXT diff --git a/src/components/layouts/pages/upload/dropzone/DropzoneText.scss b/src/components/layouts/pages/upload/dropzone/DropzoneText.scss index ec55d883..583e594c 100644 --- a/src/components/layouts/pages/upload/dropzone/DropzoneText.scss +++ b/src/components/layouts/pages/upload/dropzone/DropzoneText.scss @@ -2,8 +2,15 @@ .dropzone-text { color: $color-black--75; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + + display: flex; + flex-direction: column; &__file-size { + text-align: center; color: $color-black--50; font-size: $font-size--basic; } diff --git a/src/components/layouts/pages/upload/settingsCheckbox/SettingsCheckbox.js b/src/components/layouts/pages/upload/settingsCheckbox/SettingsCheckbox.js new file mode 100644 index 00000000..1594b5af --- /dev/null +++ b/src/components/layouts/pages/upload/settingsCheckbox/SettingsCheckbox.js @@ -0,0 +1,93 @@ +import React, { useCallback, useState } from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; + +import { getUseSettings } from '../../../../../store/application/selectors'; +import { getProfile } from '../../../../../store/job/settings/selectors'; +import { getDefaultProfileLabel, getDefaultProfileName } from '../../../../../store/validationProfiles/selectors'; +import { toggleUseSettings } from '../../../../../store/application/actions'; +import { resetProfile } from '../../../../../store/job/settings/actions'; +import Checkbox from '../../../../shared/checkbox/Checkbox'; +import Dialog from '../../../../shared/dialog/Dialog'; + +const CHECK_SETTINGS = 'Use custom validation settings'; + +function SettingsCheckbox({ + isUseSettings, + toggleSettings, + profile, + defaultProfile, + defaultProfileLabel, + resetProfile, +}) { + const [resetSettingsDialogOpened, setResetSettingsDialogOpened] = useState(false); + const onSettingsToggle = useCallback(() => { + if (profile !== defaultProfile && isUseSettings) { + return setResetSettingsDialogOpened(true); + } + return toggleSettings(); + }, [defaultProfile, profile, toggleSettings, isUseSettings]); + + const onResetSettingsClose = useCallback(() => { + setResetSettingsDialogOpened(false); + }, []); + const dialogActions = [ + { + label: 'Cancel', + color: 'primary', + align: 'start', + onClick: onResetSettingsClose, + }, + { + label: 'Reset settings', + color: 'primary', + variant: 'contained', + onClick: () => { + resetProfile(); + toggleSettings(); + onResetSettingsClose(); + }, + }, + ]; + + return ( +
+ + + Proceed? + +
+ ); +} + +SettingsCheckbox.propTypes = { + isUseSettings: PropTypes.bool.isRequired, + profile: PropTypes.string, + defaultProfile: PropTypes.string, + defaultProfileLabel: PropTypes.string, + toggleSettings: PropTypes.func.isRequired, + resetProfile: PropTypes.func.isRequired, +}; + +const mapStateToProps = state => { + return { + isUseSettings: getUseSettings(state), + profile: getProfile(state), + defaultProfile: getDefaultProfileName(state), + defaultProfileLabel: getDefaultProfileLabel(state), + }; +}; + +const mapDispatchToProps = dispatch => { + return { + toggleSettings: () => dispatch(toggleUseSettings()), + resetProfile: () => dispatch(resetProfile()), + }; +}; + +export default connect(mapStateToProps, mapDispatchToProps)(SettingsCheckbox); diff --git a/src/components/shared/checkbox/Checkbox.js b/src/components/shared/checkbox/Checkbox.js new file mode 100644 index 00000000..431dd23a --- /dev/null +++ b/src/components/shared/checkbox/Checkbox.js @@ -0,0 +1,32 @@ +import React, { useCallback } from 'react'; +import PropTypes from 'prop-types'; + +import MaterialCheckbox from '@material-ui/core/Checkbox'; +import FormControlLabel from '@material-ui/core/FormControlLabel'; + +function Checkbox({ checked, label, disabled, onChange }) { + const handleChange = useCallback(e => onChange(e.target.checked), [onChange]); + + return ( + } + /> + ); +} + +Checkbox.propTypes = { + checked: PropTypes.bool.isRequired, + label: PropTypes.string, + disabled: PropTypes.bool, + onChange: PropTypes.func.isRequired, +}; + +Checkbox.defaultProps = { + label: '', + disabled: false, +}; + +export default Checkbox; diff --git a/src/components/shared/pageNavigation/NavButton.js b/src/components/shared/linkButton/LinkButton.js similarity index 60% rename from src/components/shared/pageNavigation/NavButton.js rename to src/components/shared/linkButton/LinkButton.js index e9d90c14..10142652 100644 --- a/src/components/shared/pageNavigation/NavButton.js +++ b/src/components/shared/linkButton/LinkButton.js @@ -2,16 +2,14 @@ import React from 'react'; import { Link } from 'react-router-dom'; import PropTypes from 'prop-types'; import classNames from 'classnames'; + import Button from '../button/Button'; -function NavButton(props) { - const { to, disabled, type, variant } = props; +function LinkButton(props) { + const { to, disabled, variant, className } = props; return ( - + @@ -19,11 +17,10 @@ function NavButton(props) { ); } -NavButton.propTypes = { +LinkButton.propTypes = { to: PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.func]).isRequired, - type: PropTypes.string.isRequired, variant: PropTypes.string, disabled: PropTypes.bool, }; -export default NavButton; +export default LinkButton; diff --git a/src/components/shared/pageNavigation/PageNavigation.js b/src/components/shared/pageNavigation/PageNavigation.js index 1c9c8f4f..43c5d6a2 100644 --- a/src/components/shared/pageNavigation/PageNavigation.js +++ b/src/components/shared/pageNavigation/PageNavigation.js @@ -1,66 +1,9 @@ import React from 'react'; -import PropTypes from 'prop-types'; -import NavButton from './NavButton'; -import Button from '../button/Button'; -import './PageNavigation.scss'; - -const TYPE = { - BACK: 'back', - CENTER: 'center', - FORWARD: 'forward', -}; -const VARIANTS = { - [TYPE.BACK]: 'outlined', - [TYPE.CENTER]: 'contained', - [TYPE.FORWARD]: 'contained', -}; - -function PageNavigation(props) { - const { back, forward, center } = props; - return ( - - ); -} -function getButton(buttonObject, type) { - if (buttonObject?.to) { - return ( - - {buttonObject.label} - - ); - } - - if (buttonObject?.onClick) { - return ( - - ); - } +import './PageNavigation.scss'; - return null; +function PageNavigation({ children }) { + return ; } -const ButtonInterface = PropTypes.shape({ - to: PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.func]), - label: PropTypes.string.isRequired, - disabled: PropTypes.bool, - onClick: PropTypes.func, -}); - -PageNavigation.propTypes = { - back: ButtonInterface, - forward: ButtonInterface, -}; - export default PageNavigation; diff --git a/src/components/shared/pageNavigation/PageNavigation.scss b/src/components/shared/pageNavigation/PageNavigation.scss index e880dca8..033c3d3c 100644 --- a/src/components/shared/pageNavigation/PageNavigation.scss +++ b/src/components/shared/pageNavigation/PageNavigation.scss @@ -1,16 +1,7 @@ .page-navigation { display: flex; padding: 20px 0 10px 0; - - section { - display: flex; - flex-grow: 1; - flex-basis: 0; - justify-content: center; - - .app-link { - color: inherit; - display: flex; - } - } + justify-content: space-between; + width: 80%; + margin: auto; } diff --git a/src/components/shared/stepper/Stepper.js b/src/components/shared/stepper/Stepper.js index 0af16276..9a47bb4f 100644 --- a/src/components/shared/stepper/Stepper.js +++ b/src/components/shared/stepper/Stepper.js @@ -1,11 +1,16 @@ import React, { useMemo } from 'react'; import PropTypes from 'prop-types'; +import classNames from 'classnames'; +import { connect } from 'react-redux'; import _ from 'lodash'; + +import AppPages from '../../AppPages'; +import { getUseSettings } from '../../../store/application/selectors'; import MaterialStepper from '@material-ui/core/Stepper'; import Step from '@material-ui/core/Step'; import StepLabel from '@material-ui/core/StepLabel'; import StepIcon from './StepIcon'; -import AppPages from '../../AppPages'; + import './Stepper.scss'; const STEPS = [ @@ -15,7 +20,7 @@ const STEPS = [ }, { key: AppPages.SETTINGS, - label: 'Select settings', + label: 'Configuration', }, { key: AppPages.STATUS.route, @@ -23,26 +28,43 @@ const STEPS = [ }, { key: AppPages.RESULTS.route, - label: 'Verification results', + label: 'Results', }, ]; -function Stepper(props) { - const { activeStep } = props; - const activeIndex = useMemo(() => _.findIndex(STEPS, { key: activeStep }), [activeStep]); +function Stepper({ activeStep, customizeConfig }) { + const steps = useMemo(() => (customizeConfig ? STEPS : _.reject(STEPS, { key: AppPages.SETTINGS })), [ + customizeConfig, + ]); + const activeIndex = useMemo(() => _.findIndex(steps, { key: activeStep }), [steps, activeStep]); + return ( - - {STEPS.map(({ label }) => ( - - {label} - - ))} - + <> + + {steps.map(({ label }) => ( + + {label} + + ))} + +

{steps[activeIndex].label}

+ ); } Stepper.propTypes = { activeStep: PropTypes.string.isRequired, + customizeConfig: PropTypes.bool.isRequired, +}; + +const mapStateToProps = state => { + return { + customizeConfig: getUseSettings(state), // TODO: rename selector/reducer + }; }; -export default Stepper; +export default connect(mapStateToProps)(Stepper); diff --git a/src/components/shared/stepper/Stepper.scss b/src/components/shared/stepper/Stepper.scss index 4aeaea04..f25334d0 100644 --- a/src/components/shared/stepper/Stepper.scss +++ b/src/components/shared/stepper/Stepper.scss @@ -7,6 +7,13 @@ div.stepper { background: $bg-color--basic; color: $text-color--secondary; + margin: 0 -10px; + + &.with-config { + padding-left: 5.67%; + padding-right: 5.67%; + } + .MuiSvgIcon-root { font-size: 2rem; opacity: 0.8; @@ -37,3 +44,20 @@ div.stepper { } } } + +h1.active-step { + display: none; +} + +@media (max-width: 500px) { + div.stepper .MuiStepLabel-labelContainer { + display: none; + } + + h1.active-step { + display: block; + text-align: center; + color: $color-black--75; + margin-top: 0; + } +} diff --git a/src/store/application/actions.js b/src/store/application/actions.js index 5987a70d..f0bcde3d 100644 --- a/src/store/application/actions.js +++ b/src/store/application/actions.js @@ -14,6 +14,8 @@ export const unlockApp = createAction('APP_LOCK_SET', () => false); export const resetApp = createAction('APP_RESET'); +export const toggleUseSettings = createAction('USE_SETTINGS_TOGGLE'); + export const reset = () => async (dispatch, getState) => { const file = getFile(getState()); const profile = getDefaultProfileName(getState()); diff --git a/src/store/application/reducer.js b/src/store/application/reducer.js index ed62889c..bbac6192 100644 --- a/src/store/application/reducer.js +++ b/src/store/application/reducer.js @@ -1,8 +1,24 @@ import { handleActions } from 'redux-actions'; +import { USE_SETTINGS_FLAG } from '../constants'; const DEFAULT_STATE = { initialized: false, locked: false, + useSettings: false, +}; + +export const getDefaultState = () => { + let useSettings = sessionStorage.getItem(USE_SETTINGS_FLAG); + + if (!useSettings) { + return DEFAULT_STATE; + } + + useSettings = JSON.parse(useSettings); + return { + ...DEFAULT_STATE, + useSettings, + }; }; export default handleActions( @@ -10,6 +26,11 @@ export default handleActions( APP_RESET: () => DEFAULT_STATE, APP_STARTUP_FINISH: state => ({ ...state, initialized: true }), APP_LOCK_SET: (state, { payload: locked }) => ({ ...state, locked }), + USE_SETTINGS_TOGGLE: state => { + const useSettings = !state.useSettings; + sessionStorage.setItem(USE_SETTINGS_FLAG, useSettings); + return { ...state, useSettings }; + }, }, - DEFAULT_STATE + getDefaultState() ); diff --git a/src/store/application/selectors.js b/src/store/application/selectors.js index d0a42310..d7bbc6b0 100644 --- a/src/store/application/selectors.js +++ b/src/store/application/selectors.js @@ -5,3 +5,5 @@ const getAppState = state => state.appState; export const isInitialized = createSelector(getAppState, ({ initialized }) => initialized); export const isLocked = createSelector(getAppState, ({ locked }) => locked); + +export const getUseSettings = createSelector(getAppState, ({ useSettings }) => useSettings); diff --git a/src/store/constants.js b/src/store/constants.js index e384b53c..88936770 100644 --- a/src/store/constants.js +++ b/src/store/constants.js @@ -1,5 +1,6 @@ export const JOB_FILE = 'JOB_FILE'; export const JOB_SETTINGS = 'JOB_SETTINGS'; +export const USE_SETTINGS_FLAG = 'USE_SETTINGS_FLAG'; export const JOB_STATUS = { CREATED: 'CREATED', diff --git a/src/store/job/settings/actions.js b/src/store/job/settings/actions.js index afbc8b4c..271846fe 100644 --- a/src/store/job/settings/actions.js +++ b/src/store/job/settings/actions.js @@ -1,5 +1,6 @@ import { createAction } from 'redux-actions'; import { JOB_SETTINGS } from '../../constants'; +import { getDefaultProfileName } from '../../validationProfiles/selectors'; const updateSettings = createAction('SETTINGS_UPDATE'); @@ -7,3 +8,8 @@ export const setSetting = (setting, value) => async (dispatch, getState) => { await dispatch(updateSettings({ [setting]: value })); sessionStorage.setItem(JOB_SETTINGS, JSON.stringify(getState().jobSettings)); }; + +export const resetProfile = () => async (dispatch, getState) => { + const profile = getDefaultProfileName(getState()); + dispatch(updateSettings({ profile })); +}; diff --git a/src/store/validationProfiles/selectors.js b/src/store/validationProfiles/selectors.js index 2ba656ba..a484efb9 100644 --- a/src/store/validationProfiles/selectors.js +++ b/src/store/validationProfiles/selectors.js @@ -17,4 +17,6 @@ export const getProfileOptions = createSelector(getProfiles, profiles => { export const getDefaultProfileName = createSelector(getProfiles, profiles => _.first(profiles)?.profileName); +export const getDefaultProfileLabel = createSelector(getProfiles, profiles => _.first(profiles)?.humanReadableName); + export const getProfilesError = createSelector(getProfiles, profiles => _.get(profiles, 'error'));