diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index ffef972ab..75d4dad2e 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -145,6 +145,8 @@ export const en = { startWith: 'Start with', prevWorkSection: 'In this section your previous work will be displayed', prevWorkWith: 'You previously worked with', + candidateIsUnavailable: 'Existing candidates are unavailable', + genomeIsUnavailable: 'Whole genome/exome is unavailable', }, buildFlow: { candidateSet: 'Existing candidate sets', @@ -152,6 +154,9 @@ export const en = { whatsNext: "What's next?", relevantPresets: 'Relevant presets', additionalPresetFilter: 'Additional preset filters', + simpleFilter: 'Simple Filter', + inclusionExclusion: 'Inclusion/Exclusion Criteria', + viewVariants: 'View Variants', }, }, ds: { diff --git a/src/pages/main/components/selected-dataset/build-flow/components/build-flow-left-column.tsx b/src/pages/main/components/selected-dataset/build-flow/components/build-flow-left-column.tsx deleted file mode 100644 index 54218b01d..000000000 --- a/src/pages/main/components/selected-dataset/build-flow/components/build-flow-left-column.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import styles from '../build-flow.module.css' - -import { ReactElement } from 'react' -import cn from 'classnames' -import { observer } from 'mobx-react-lite' - -import wizardStore from './wizard/wizard.store' - -export const BuildFlowLeftColumn = observer((): ReactElement => { - const { wizardScenario } = wizardStore - - return ( -
- {wizardScenario.map((scenario, index) => { - const Component = () => - scenario.component({ - id: scenario.id, - continueDisabled: scenario.continueDisabled, - editDisabled: scenario.editDisabled, - contentDisabled: scenario.contentDisabled, - selectedValue: scenario.value, - title: scenario.title, - maxHeight: scenario.maxHeight, - }) - return ( - index < 2 && !scenario.hidden && - ) - })} -
- ) -}) diff --git a/src/pages/main/components/selected-dataset/build-flow/components/build-flow-right-column.tsx b/src/pages/main/components/selected-dataset/build-flow/components/build-flow-right-column.tsx deleted file mode 100644 index 18befeee2..000000000 --- a/src/pages/main/components/selected-dataset/build-flow/components/build-flow-right-column.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import styles from '../build-flow.module.css' - -import { ReactElement, useRef } from 'react' -import { observer } from 'mobx-react-lite' - -import wizardStore from './wizard/wizard.store' - -export const BuildFlowRightColumn = observer((): ReactElement => { - const { wizardScenario } = wizardStore - const divRef = useRef(null) - - return ( -
- {wizardScenario.map((scenario, index) => { - const Component = () => - scenario.component({ - id: scenario.id, - continueDisabled: scenario.continueDisabled, - editDisabled: scenario.editDisabled, - contentDisabled: scenario.contentDisabled, - selectedValue: scenario.value, - title: scenario.title, - maxHeight: scenario.maxHeight, - }) - return ( - index > 1 && !scenario.hidden && - ) - })} -
- ) -}) diff --git a/src/pages/main/components/selected-dataset/build-flow/components/cards/components/card-radio-list.interface.ts b/src/pages/main/components/selected-dataset/build-flow/components/cards/components/card-radio-list.interface.ts index 78dba5687..9baa31e79 100644 --- a/src/pages/main/components/selected-dataset/build-flow/components/cards/components/card-radio-list.interface.ts +++ b/src/pages/main/components/selected-dataset/build-flow/components/cards/components/card-radio-list.interface.ts @@ -3,4 +3,12 @@ export interface ICardRadioItem { value: T } -export type TDisabledOptions = Record +export interface IDisabledOption { + isDisabled: boolean + placeholder: () => JSX.Element +} + +export type TDisabledOptions = Record< + T, + boolean | IDisabledOption +> diff --git a/src/pages/main/components/selected-dataset/build-flow/components/cards/components/card-radio-list.tsx b/src/pages/main/components/selected-dataset/build-flow/components/cards/components/card-radio-list.tsx index bd7a581fb..6c3d12ee7 100644 --- a/src/pages/main/components/selected-dataset/build-flow/components/cards/components/card-radio-list.tsx +++ b/src/pages/main/components/selected-dataset/build-flow/components/cards/components/card-radio-list.tsx @@ -1,4 +1,5 @@ import { Radio } from '@ui/radio' +import { disabledOptionIsObject } from './card-radio.utils' import { ICardRadioItem, TDisabledOptions } from './card-radio-list.interface' interface ICardRadioListProps { @@ -18,18 +19,37 @@ export const CardRadioList = function ({ }: ICardRadioListProps) { return ( <> - {data.map(({ label, value }) => ( -
- onChange(value)} - disabled={isOptionsDisabled || disabledOptions?.[value]} - > -
{label}
-
-
- ))} + {data.map(({ label, value }) => { + const disabledOption = disabledOptions?.[value] + if ( + disabledOptionIsObject(disabledOption) && + disabledOption.isDisabled + ) { + return ( +
+ {disabledOption.placeholder()} +
+ ) + } else { + return ( +
+ onChange(value)} + disabled={ + !!isOptionsDisabled || + (disabledOptionIsObject(disabledOption) + ? disabledOption.isDisabled + : disabledOption) + } + > +
{label}
+
+
+ ) + } + })} ) } diff --git a/src/pages/main/components/selected-dataset/build-flow/components/cards/components/card-radio.utils.ts b/src/pages/main/components/selected-dataset/build-flow/components/cards/components/card-radio.utils.ts new file mode 100644 index 000000000..f9525d206 --- /dev/null +++ b/src/pages/main/components/selected-dataset/build-flow/components/cards/components/card-radio.utils.ts @@ -0,0 +1,7 @@ +import { IDisabledOption } from './card-radio-list.interface' + +export const disabledOptionIsObject = ( + value: boolean | IDisabledOption | undefined, +): value is IDisabledOption => { + return typeof value === 'object' +} diff --git a/src/pages/main/components/selected-dataset/build-flow/components/cards/description-card/description-card.tsx b/src/pages/main/components/selected-dataset/build-flow/components/cards/description-card/description-card.tsx index 7b46cb4d9..2b1e63e16 100644 --- a/src/pages/main/components/selected-dataset/build-flow/components/cards/description-card/description-card.tsx +++ b/src/pages/main/components/selected-dataset/build-flow/components/cards/description-card/description-card.tsx @@ -34,6 +34,7 @@ export const DescriptionCard = observer( continueDisabled, contentDisabled, editDisabled, + position, } = props const history = useHistory() const ds = title || datasetStore.datasetName @@ -60,7 +61,6 @@ export const DescriptionCard = observer( } useEffect(() => { - wizardStore.wizardScenario[id].title = ds wizardStore.updateSelectedDataset(ds) setDsName(ds) // eslint-disable-next-line react-hooks/exhaustive-deps @@ -73,16 +73,17 @@ export const DescriptionCard = observer( return ( wizardStore.editCard(id)} />
- +
Description
-
- ) -}) +
+
+
+ ) + }, +) diff --git a/src/pages/main/components/selected-dataset/build-flow/components/cards/start-card.tsx b/src/pages/main/components/selected-dataset/build-flow/components/cards/start-card.tsx index 18f00f6e0..a3d5024b0 100644 --- a/src/pages/main/components/selected-dataset/build-flow/components/cards/start-card.tsx +++ b/src/pages/main/components/selected-dataset/build-flow/components/cards/start-card.tsx @@ -1,22 +1,26 @@ +import { + ExploreKeys, + ExploreTypesDictionary, + TExploreKeys, +} from '@core/enum/explore-types-enum' import { datasetStore } from '@store/dataset' import { Button } from '@ui/button' import { Card } from '@ui/card' -import { Radio } from '@ui/radio' -import { startFlowOptionsList } from '../wizard/wizard.data' import { ICardProps } from '../wizard/wizard.interface' import wizardStore from '../wizard/wizard.store' import { CardTitleWithEdit } from './components/card-edit-title' +import { useRadioListData } from './components/card-radio.hooks' +import { CardRadioList } from './components/card-radio-list' -export const StartCard = (props: ICardProps) => { - const { - title, - id, - selectedValue, - contentDisabled, - continueDisabled, - editDisabled, - } = props - +export const StartCard = ({ + title, + id, + selectedValue, + contentDisabled, + continueDisabled, + editDisabled, + position, +}: ICardProps) => { const isExploreGenomeDisabled = !datasetStore.isXL const isExploreCandidateDisabled = !wizardStore.secondaryDatasets && datasetStore.isXL @@ -26,30 +30,29 @@ export const StartCard = (props: ICardProps) => { const isEditShown = !isEditionProhibited && !editDisabled + const radioListData = useRadioListData(ExploreTypesDictionary) + return ( wizardStore.editCard(id)} /> -
- {startFlowOptionsList.map(option => ( -
- wizardStore.setStartWithOption(option, id)} - disabled={contentDisabled} - > -
{option}
-
-
- ))} + + data={radioListData} + onChange={value => wizardStore.setStartWithOption(value, id)} + selectedOption={selectedValue!} + disabledOptions={{ + [ExploreKeys.Genome]: isExploreGenomeDisabled || contentDisabled, + [ExploreKeys.Candidate]: + isExploreCandidateDisabled || contentDisabled, + }} + /> {!isEditShown && (
diff --git a/src/pages/main/components/selected-dataset/build-flow/components/cards/whats-next-card.tsx b/src/pages/main/components/selected-dataset/build-flow/components/cards/whats-next-card.tsx index 5ef9f8f15..38110a7c9 100644 --- a/src/pages/main/components/selected-dataset/build-flow/components/cards/whats-next-card.tsx +++ b/src/pages/main/components/selected-dataset/build-flow/components/cards/whats-next-card.tsx @@ -30,6 +30,7 @@ export const WhatsNextCard = observer( contentDisabled, continueDisabled, editDisabled, + position, } = props const openNextPage = () => { @@ -61,7 +62,7 @@ export const WhatsNextCard = observer( return ( <> , - id: 0, + component: (props: ICardProps) => , + id: WizardCardIds.StartFull, hidden: false, continueDisabled: true, editDisabled: false, - contentDisabled: true, - value: ExploreTypesDictionary.Candidate, + contentDisabled: false, + selectedValue: '', title: t('home.startFlow.startWith'), - }, - { - component: (props: ICardProps) => , - id: 1, - hidden: false, - continueDisabled: true, - editDisabled: false, - contentDisabled: true, - value: '', - title: t('home.buildFlow.candidateSet'), - maxHeight: 'calc(100vh - 285px)', + position: 'stretch', + nextCard: WizardCardIds.ExistingCandidate, }, { component: (props: ICardProps) => ( )} /> ), - id: 2, + id: WizardCardIds.Description, hidden: false, continueDisabled: false, editDisabled: true, contentDisabled: false, - value: ExploreCandidateKeys.ViewAllVariants, + selectedValue: ExploreCandidateKeys.ViewAllVariants, title: '', + position: 'right', + nextCard: WizardCardIds.Presets, + }, + { + component: (props: ICardProps) => , + id: WizardCardIds.ExistingCandidate, + hidden: true, + continueDisabled: true, + editDisabled: false, + contentDisabled: true, + selectedValue: '', + title: t('home.buildFlow.candidateSet'), + maxHeight: 'calc(100vh - 285px)', + position: 'left', + nextCard: WizardCardIds.Description, }, { component: (props: ICardProps) => , - id: 3, + id: WizardCardIds.Presets, hidden: true, continueDisabled: false, editDisabled: true, contentDisabled: false, - value: '', + selectedValue: '', title: t('home.buildFlow.additionalPresetFilter'), maxHeight: 'calc(100vh - 585px)', + position: 'right', + nextCard: null, }, ] diff --git a/src/pages/main/components/selected-dataset/build-flow/components/wizard/scenarios/ws-short-candidate-set.tsx b/src/pages/main/components/selected-dataset/build-flow/components/wizard/scenarios/ws-short-candidate-set.tsx index c48aa7d11..967cf7057 100644 --- a/src/pages/main/components/selected-dataset/build-flow/components/wizard/scenarios/ws-short-candidate-set.tsx +++ b/src/pages/main/components/selected-dataset/build-flow/components/wizard/scenarios/ws-short-candidate-set.tsx @@ -1,43 +1,51 @@ import { ExploreCandidateKeys } from '@core/enum/explore-candidate-types-enum' import { TExploreGenomeKeys } from '@core/enum/explore-genome-types-enum' -import { ExploreTypesDictionary } from '@core/enum/explore-types-enum' +import { ExploreKeys } from '@core/enum/explore-types-enum' import { t } from '@i18n' -import { DescriptionCard, PresetsCard, StartCard } from '../../cards' +import { CardExploreType } from '@pages/main/components/selected-dataset/components/card-explore/card-explore-type' +import { DescriptionCard, PresetsCard } from '../../cards' import { ICardProps, IWizardScenario } from '.././wizard.interface' +import { WizardCardIds } from './wizard-scenarios.constants' export const wsShortCandidateSet: IWizardScenario[] = [ { - component: (props: ICardProps) => , - id: 0, + component: (props: ICardProps) => , + id: WizardCardIds.StartFull, hidden: false, continueDisabled: true, editDisabled: false, contentDisabled: true, - value: ExploreTypesDictionary.Candidate, + selectedValue: ExploreKeys.Candidate, title: t('home.startFlow.startWith'), + position: 'stretch', + nextCard: WizardCardIds.Description, }, { component: (props: ICardProps) => ( )} /> ), - id: 1, + id: WizardCardIds.Description, hidden: false, continueDisabled: false, editDisabled: true, contentDisabled: false, - value: ExploreCandidateKeys.ViewAllVariants, + selectedValue: ExploreCandidateKeys.ViewAllVariants, title: '', + position: 'right', + nextCard: WizardCardIds.Presets, }, { component: (props: ICardProps) => , - id: 2, + id: WizardCardIds.Presets, hidden: true, continueDisabled: false, editDisabled: true, contentDisabled: false, - value: '', + selectedValue: '', title: t('home.buildFlow.additionalPresetFilter'), maxHeight: 'calc(100vh - 285px)', + position: 'right', + nextCard: null, }, ] diff --git a/src/pages/main/components/selected-dataset/build-flow/components/wizard/scenarios/xl-candidate-set.tsx b/src/pages/main/components/selected-dataset/build-flow/components/wizard/scenarios/xl-candidate-set.tsx index f6a70f5a9..1a0fe1094 100644 --- a/src/pages/main/components/selected-dataset/build-flow/components/wizard/scenarios/xl-candidate-set.tsx +++ b/src/pages/main/components/selected-dataset/build-flow/components/wizard/scenarios/xl-candidate-set.tsx @@ -9,51 +9,60 @@ import { StartCard, } from '../../cards' import { ICardProps, IWizardScenario } from '../wizard.interface' +import { WizardCardIds } from './wizard-scenarios.constants' export const xlCandidateSet: IWizardScenario[] = [ { component: (props: ICardProps) => , - id: 0, + id: WizardCardIds.Start, hidden: false, continueDisabled: true, editDisabled: false, contentDisabled: true, - value: ExploreKeys.Candidate, + selectedValue: ExploreKeys.Candidate, title: t('home.startFlow.startWith'), - }, - { - component: (props: ICardProps) => , - id: 1, - hidden: false, - continueDisabled: false, - editDisabled: true, - contentDisabled: false, - value: '', - title: t('home.buildFlow.candidateSet'), - maxHeight: 'calc(100vh - 285px)', + position: 'left', + nextCard: WizardCardIds.ExistingCandidate, }, { component: (props: ICardProps) => ( )} /> ), - id: 2, + id: WizardCardIds.Description, hidden: true, continueDisabled: false, editDisabled: true, contentDisabled: false, - value: ExploreCandidateKeys.ViewAllVariants, + selectedValue: ExploreCandidateKeys.ViewAllVariants, title: '', + position: 'right', + nextCard: WizardCardIds.Presets, + }, + { + component: (props: ICardProps) => , + id: WizardCardIds.ExistingCandidate, + hidden: false, + continueDisabled: false, + editDisabled: true, + contentDisabled: false, + selectedValue: '', + title: t('home.buildFlow.candidateSet'), + maxHeight: 'calc(100vh - 285px)', + position: 'left', + nextCard: WizardCardIds.Description, }, { component: (props: ICardProps) => , - id: 3, + id: WizardCardIds.Presets, hidden: true, continueDisabled: false, editDisabled: true, contentDisabled: false, - value: '', + selectedValue: '', title: t('home.buildFlow.additionalPresetFilter'), maxHeight: 'calc(100vh - 577px)', + position: 'right', + nextCard: null, }, ] diff --git a/src/pages/main/components/selected-dataset/build-flow/components/wizard/scenarios/xl-whole-genome.tsx b/src/pages/main/components/selected-dataset/build-flow/components/wizard/scenarios/xl-whole-genome.tsx index 42312e864..83892d8b0 100644 --- a/src/pages/main/components/selected-dataset/build-flow/components/wizard/scenarios/xl-whole-genome.tsx +++ b/src/pages/main/components/selected-dataset/build-flow/components/wizard/scenarios/xl-whole-genome.tsx @@ -2,43 +2,50 @@ import { ExploreGenomeKeys, TExploreGenomeKeys, } from '@core/enum/explore-genome-types-enum' -import { ExploreTypesDictionary } from '@core/enum/explore-types-enum' +import { ExploreKeys } from '@core/enum/explore-types-enum' import { t } from '@i18n' import { PresetsCard, StartCard, WhatsNextCard } from '../../cards' import { ICardProps, IWizardScenario } from '../wizard.interface' +import { WizardCardIds } from './wizard-scenarios.constants' export const xlWholeGenome: IWizardScenario[] = [ { component: (props: ICardProps) => , - id: 0, + id: WizardCardIds.Start, hidden: false, continueDisabled: true, editDisabled: false, contentDisabled: true, - value: ExploreTypesDictionary.Genome, + selectedValue: ExploreKeys.Genome, title: t('home.startFlow.startWith'), + position: 'left', + nextCard: WizardCardIds.WhatsNext, }, { - component: (props: ICardProps) => ( - )} /> - ), - id: 1, - hidden: false, + component: (props: ICardProps) => , + id: WizardCardIds.Presets, + hidden: true, continueDisabled: false, editDisabled: true, contentDisabled: false, - value: ExploreGenomeKeys.ACMGSecondary, - title: t('home.buildFlow.whatsNext'), + selectedValue: '', + title: t('home.buildFlow.relevantPresets'), + maxHeight: 'calc(100vh - 285px)', + position: 'right', + nextCard: null, }, { - component: (props: ICardProps) => , - id: 2, - hidden: true, + component: (props: ICardProps) => ( + )} /> + ), + id: WizardCardIds.WhatsNext, + hidden: false, continueDisabled: false, editDisabled: true, contentDisabled: false, - value: '', - title: t('home.buildFlow.relevantPresets'), - maxHeight: 'calc(100vh - 285px)', + selectedValue: ExploreGenomeKeys.ACMGSecondary, + title: t('home.buildFlow.whatsNext'), + position: 'left', + nextCard: WizardCardIds.Presets, }, ] diff --git a/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.data.ts b/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.data.ts index 0d17b6c8c..028ea1595 100644 --- a/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.data.ts +++ b/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.data.ts @@ -6,9 +6,6 @@ import { ExploreGenomeKeys, TExploreGenomeKeys, } from '@core/enum/explore-genome-types-enum' -import { ExploreTypesDictionary } from '@core/enum/explore-types-enum' - -export const startFlowOptionsList = Object.values(ExploreTypesDictionary) export const optionsForOpenButton: ( | TExploreGenomeKeys diff --git a/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.interface.ts b/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.interface.ts index 0ff5206d8..c25300d0a 100644 --- a/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.interface.ts +++ b/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.interface.ts @@ -1,27 +1,25 @@ import { TExploreCandidateKeys } from '@core/enum/explore-candidate-types-enum' import { TExploreGenomeKeys } from '@core/enum/explore-genome-types-enum' import { GlbPagesNames } from '@glb/glb-names' +import { WizardCardIds } from './scenarios/wizard-scenarios.constants' + +export type TCardPosition = 'left' | 'right' | 'stretch' export interface ICardProps { - id: number + id: WizardCardIds title: string selectedValue: SelectedValue contentDisabled: boolean continueDisabled: boolean editDisabled: boolean maxHeight?: string + position?: TCardPosition } -export interface IWizardScenario { +export interface IWizardScenario extends ICardProps { component: (props: ICardProps) => JSX.Element - id: number hidden: boolean - value: string - title: string - contentDisabled: boolean - continueDisabled: boolean - editDisabled: boolean - maxHeight?: string + nextCard: WizardCardIds | null } export interface IWizardRoute { diff --git a/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.store.ts b/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.store.ts index 6fd149161..9bb0b3625 100644 --- a/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.store.ts +++ b/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.store.ts @@ -2,22 +2,25 @@ import cloneDeep from 'lodash/cloneDeep' import { makeAutoObservable, reaction } from 'mobx' import { TExploreGenomeKeys } from '@core/enum/explore-genome-types-enum' -import { ExploreTypesDictionary } from '@core/enum/explore-types-enum' +import { ExploreKeys, TExploreKeys } from '@core/enum/explore-types-enum' import { ActionsHistoryStore } from '@store/actions-history' import { createHistoryObserver } from '@store/common' import { datasetStore } from '@store/dataset' import dirinfoStore from '@store/dirinfo' import { ISolutionWithKind } from '../cards/presets-card/utils/add-solution-kind' +import { WizardCardIds } from './scenarios/wizard-scenarios.constants' import { wizardScenarios } from './scenarios/wizard-scenarious' import { IWizardScenario } from './wizard.interface' +import { getActiveCardIds } from './wizard.utils' class WizardStore { public isWizardVisible: boolean = false private prevWizardScenario: IWizardScenario[] = [] public wizardScenario: IWizardScenario[] = [] - public startWithOption = '' + public startWithOption: TExploreKeys = ExploreKeys.Genome public whatsNextOption?: TExploreGenomeKeys public descriptionOption = '' + public descriptionTitle = '' public selectedPreset?: ISolutionWithKind public selectedDataset = '' public needToChangeScenario: boolean = false @@ -28,11 +31,11 @@ class WizardStore { ) private get scenarioActiveCards() { - return this.wizardScenario.filter(card => !card.hidden).length + return getActiveCardIds(this.wizardScenario) } private get prevScenarioActiveCards() { - return this.prevWizardScenario.filter(card => !card.hidden).length + return getActiveCardIds(this.prevWizardScenario) } readonly observeHistory = createHistoryObserver({ @@ -74,6 +77,13 @@ class WizardStore { } }, ) + + reaction( + () => datasetStore.datasetName, + () => { + this.defineAndSetNewScenario() + }, + ) } public toggleIsWizardVisible(value: boolean) { @@ -95,112 +105,164 @@ class WizardStore { public defineAndSetNewScenario() { this.prevWizardScenario = [] - if (this.startWithOption === ExploreTypesDictionary.Genome) { + if (datasetStore.isXL && this.startWithOption === ExploreKeys.Genome) { this.setScenario(wizardScenarios.XlWholeGenome) - } - - if (this.startWithOption === ExploreTypesDictionary.Candidate) { + } else if ( + datasetStore.isXL && + this.startWithOption === ExploreKeys.Candidate + ) { this.setScenario(wizardScenarios.XlCandidateSet) + } else if (!this.secondaryDatasets?.length) { + this.setScenario(wizardScenarios.WsShortCandidateSet) + } else { + this.setScenario(wizardScenarios.WsCandidateSet) } this.needToChangeScenario = false } - public setStartWithOption(startWithOption: string, index: number) { + private enableContinue(id: WizardCardIds) { + const clonedWizard = cloneDeep(this.wizardScenario) + const card = this.findCardById(id, clonedWizard) + + if (card) { + card.continueDisabled = false + this.setScenario(clonedWizard) + } + } + + public setStartWithOption(startWithOption: TExploreKeys, id: WizardCardIds) { this.startWithOption = startWithOption - this.changeCardValue(index, startWithOption) - this.needToChangeScenario = true + this.changeCardValue(id, startWithOption) + this.enableContinue(id) + + if (datasetStore.isXL) { + this.needToChangeScenario = true + } } public setWhatsNextOption( whatsNextOption: TExploreGenomeKeys, - index: number, + id: WizardCardIds, ) { this.whatsNextOption = whatsNextOption - this.changeCardValue(index, whatsNextOption) + this.changeCardValue(id, whatsNextOption) } - public setDescriptionOption(descriptionOption: string, index: number) { + public setDescriptionOption(descriptionOption: string, id: WizardCardIds) { this.descriptionOption = descriptionOption - this.changeCardValue(index, descriptionOption) + this.changeCardValue(id, descriptionOption) } - public setSelectedPreset(selectedPreset: ISolutionWithKind, index: number) { + public setSelectedPreset( + selectedPreset: ISolutionWithKind, + id: WizardCardIds, + ) { this.selectedPreset = selectedPreset - this.changeCardValue(index, selectedPreset.name) + this.changeCardValue(id, selectedPreset.name) } - public setSelectedDataset(selectedDataset: string, index: number) { + public setSelectedDataset(selectedDataset: string, id: WizardCardIds) { this.selectedDataset = selectedDataset const clonedWizard = cloneDeep(this.wizardScenario) - clonedWizard[index].value = selectedDataset - clonedWizard[index + 1].title = selectedDataset - - if (clonedWizard[index + 1]) { - clonedWizard[index + 1].continueDisabled = false - clonedWizard[index + 1].contentDisabled = false - clonedWizard[index + 1].editDisabled = true - clonedWizard[index + 1].hidden = false + const card = this.findCardById(id, clonedWizard) + if (card) { + card.selectedValue = selectedDataset + if (card.nextCard) { + const nextCard = this.findCardById(card.nextCard, clonedWizard) + + if (nextCard) { + nextCard.title = selectedDataset + + if (nextCard) { + nextCard.continueDisabled = false + nextCard.contentDisabled = false + nextCard.editDisabled = true + nextCard.hidden = false + } + + this.setScenario(clonedWizard) + } + } } - - this.setScenario(clonedWizard) } public updateSelectedDataset(ds: string) { this.selectedDataset = ds } - public showNextCard(index: number) { - if (this.wizardScenario[index + 1]) { - this.wizardScenario[index + 1].hidden = false + public showNextCard(id: WizardCardIds, scenario: IWizardScenario[]) { + const card = this.findCardById(id, scenario) + if (card?.nextCard) { + const nextCard = this.findCardById(card.nextCard, scenario) + + if (nextCard) { + nextCard.hidden = false + } } } - private hideNextCards(index: number, wizard: IWizardScenario[]) { - return wizard.map((scenario, currIndex) => { - scenario.hidden = currIndex > index - return scenario - }) + private hideNextCards(id: WizardCardIds, scenario: IWizardScenario[]) { + const card = this.findCardById(id, scenario) + + if (card?.nextCard) { + const nextCard = this.findCardById(card.nextCard, scenario) + if (nextCard) { + nextCard.hidden = true + this.hideNextCards(nextCard.id, scenario) + } + } } - public editCard(index: number) { - let clonedWizard = cloneDeep(this.wizardScenario) - clonedWizard[index].continueDisabled = false - clonedWizard[index].contentDisabled = false - clonedWizard[index].editDisabled = true - clonedWizard = this.hideNextCards(index, clonedWizard) - this.wizardScenario = clonedWizard - this.prevWizardScenario = clonedWizard - this.actionHistory.addHistory(clonedWizard) + public editCard(id: WizardCardIds) { + const clonedWizard = cloneDeep(this.wizardScenario) + const card = this.findCardById(id, clonedWizard) + if (card) { + card.continueDisabled = false + card.contentDisabled = false + card.editDisabled = true + + this.hideNextCards(id, clonedWizard) + this.wizardScenario = clonedWizard + this.prevWizardScenario = clonedWizard + this.actionHistory.addHistory(clonedWizard) + } } - public finishEditCard(index: number) { + public finishEditCard(id: WizardCardIds) { if (this.needToChangeScenario) { this.defineAndSetNewScenario() return } const clonedWizard = cloneDeep(this.wizardScenario) - clonedWizard[index].continueDisabled = true - clonedWizard[index].contentDisabled = true - clonedWizard[index].editDisabled = false - - if (clonedWizard[index + 1]) { - clonedWizard[index + 1].continueDisabled = false - clonedWizard[index + 1].contentDisabled = false - clonedWizard[index + 1].editDisabled = true + const card = this.findCardById(id, clonedWizard) + if (card) { + card.continueDisabled = true + card.contentDisabled = true + card.editDisabled = false + + const nextCard = this.findCardById(card.nextCard, clonedWizard) + if (nextCard) { + nextCard.continueDisabled = false + nextCard.contentDisabled = false + nextCard.editDisabled = true + } + this.showNextCard(card.id, clonedWizard) + + this.wizardScenario = clonedWizard + this.actionHistory.addHistory(clonedWizard) } - - this.wizardScenario = clonedWizard - this.actionHistory.addHistory(clonedWizard) - - this.showNextCard(index) } - public changeCardValue(index: number, value: string) { + public changeCardValue(id: WizardCardIds, value: string) { const clonedWizard = cloneDeep(this.wizardScenario) - clonedWizard[index].value = value - this.setScenario(clonedWizard) + const card = this.findCardById(id, clonedWizard) + + if (card) { + card.selectedValue = value + this.setScenario(clonedWizard) + } } public openWizardForWsDatasets(hasSecondaryDs: boolean) { @@ -229,15 +291,22 @@ class WizardStore { this.datasetKind = '' } - public isNeedToAnimateCard(id: number) { - if (this.wizardScenario.length === 1) { - return true - } + public isNeedToAnimateCard(id: WizardCardIds) { + const scenariosDiff = this.scenarioActiveCards.reduce((acc, addedId) => { + if (!this.prevScenarioActiveCards.includes(addedId)) { + acc.push(addedId) + } + return acc + }, [] as WizardCardIds[]) - return ( - this.scenarioActiveCards > this.prevScenarioActiveCards && - id + 1 === this.scenarioActiveCards - ) + return scenariosDiff.includes(id) + } + + private findCardById(id: WizardCardIds | null, scenario: IWizardScenario[]) { + if (id) { + return scenario.find(card => card.id === id) + } + return undefined } } diff --git a/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.utils.ts b/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.utils.ts index d821473fd..d5eea752b 100644 --- a/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.utils.ts +++ b/src/pages/main/components/selected-dataset/build-flow/components/wizard/wizard.utils.ts @@ -10,7 +10,12 @@ import { LocalStoreManager } from '@core/storage-management/local-store-manager' import { datasetStore } from '@store/dataset' import { Routes } from '@router/routes.enum' import { GlbPagesNames } from '@glb/glb-names' -import { IWizardRoute, TRouteDictionary } from './wizard.interface' +import { WizardCardIds } from './scenarios/wizard-scenarios.constants' +import { + IWizardRoute, + IWizardScenario, + TRouteDictionary, +} from './wizard.interface' export const PREVIOUS_WORK_LOCATION = 'prevWorkLocation' @@ -77,3 +82,12 @@ export const memorizeLocation = (location: string) => { LocalStoreManager.write(PREVIOUS_WORK_LOCATION, locations || [location]) } + +export const getActiveCardIds = (scenario: IWizardScenario[]) => { + return scenario.reduce((acc, card) => { + if (!card.hidden) { + acc.push(card.id) + } + return acc + }, [] as WizardCardIds[]) +} diff --git a/src/pages/main/components/selected-dataset/build-flow/selected-dataset-build-flow.tsx b/src/pages/main/components/selected-dataset/build-flow/selected-dataset-build-flow.tsx index a9323d4b9..a61a3399c 100644 --- a/src/pages/main/components/selected-dataset/build-flow/selected-dataset-build-flow.tsx +++ b/src/pages/main/components/selected-dataset/build-flow/selected-dataset-build-flow.tsx @@ -4,8 +4,6 @@ import { ReactElement } from 'react' import { observer } from 'mobx-react-lite' import { BuildFlowHeader } from './components/build-flow-header' -import { BuildFlowLeftColumn } from './components/build-flow-left-column' -import { BuildFlowRightColumn } from './components/build-flow-right-column' import wizardStore from './components/wizard/wizard.store' export const SelectedDatasetBuildFlow = observer( @@ -20,10 +18,14 @@ export const SelectedDatasetBuildFlow = observer(
-
- - - +
+ {wizardStore.wizardScenario.map(({ component, ...rest }) => { + const Component = () => + component({ + ...rest, + }) + return !rest.hidden && + })}
diff --git a/src/pages/main/components/selected-dataset/components/card-explore/card-explore-type.tsx b/src/pages/main/components/selected-dataset/components/card-explore/card-explore-type.tsx new file mode 100644 index 000000000..de787e7e3 --- /dev/null +++ b/src/pages/main/components/selected-dataset/components/card-explore/card-explore-type.tsx @@ -0,0 +1,27 @@ +import { FC, ReactElement } from 'react' +import { observer } from 'mobx-react-lite' + +import { TExploreKeys } from '@core/enum/explore-types-enum' +import { Card } from '@ui/card' +import { ICardProps } from '../../build-flow/components/wizard/wizard.interface' +import { CardPreviousExploreSection } from './card-previous-explore-section' +import { CardStartExploreSection } from './card-start-explore-section' + +export const CardExploreType: FC> = observer( + (props): ReactElement => { + const { position = 'stretch' } = props + + return ( + +
+ )} /> + + +
+
+ ) + }, +) diff --git a/src/pages/main/components/selected-dataset/start-flow/components/card-sections/card-previous-explore-section.tsx b/src/pages/main/components/selected-dataset/components/card-explore/card-previous-explore-section.tsx similarity index 89% rename from src/pages/main/components/selected-dataset/start-flow/components/card-sections/card-previous-explore-section.tsx rename to src/pages/main/components/selected-dataset/components/card-explore/card-previous-explore-section.tsx index 67c9bc979..c1d0bff67 100644 --- a/src/pages/main/components/selected-dataset/start-flow/components/card-sections/card-previous-explore-section.tsx +++ b/src/pages/main/components/selected-dataset/components/card-explore/card-previous-explore-section.tsx @@ -4,7 +4,7 @@ import { useHistory } from 'react-router' import { LocalStoreManager } from '@core/storage-management' import { t } from '@i18n' import { CardTitle } from '@ui/card' -import { PREVIOUS_WORK_LOCATION } from '../../../build-flow/components/wizard/wizard.utils' +import { PREVIOUS_WORK_LOCATION } from '../../build-flow/components/wizard/wizard.utils' import { parseLocation } from './card-sections.utils' export const CardPreviousExploreSection = (): ReactElement => { @@ -28,7 +28,7 @@ export const CardPreviousExploreSection = (): ReactElement => { return ( onClickLocation(location)} > {parseLocation(location)} diff --git a/src/pages/main/components/selected-dataset/start-flow/components/card-sections/card-sections.utils.ts b/src/pages/main/components/selected-dataset/components/card-explore/card-sections.utils.ts similarity index 52% rename from src/pages/main/components/selected-dataset/start-flow/components/card-sections/card-sections.utils.ts rename to src/pages/main/components/selected-dataset/components/card-explore/card-sections.utils.ts index 9f60d3761..89bba4b1a 100644 --- a/src/pages/main/components/selected-dataset/start-flow/components/card-sections/card-sections.utils.ts +++ b/src/pages/main/components/selected-dataset/components/card-explore/card-sections.utils.ts @@ -1,25 +1,30 @@ +import { t } from '@i18n' import { Routes } from '@router/routes.enum' export const parseLocation = (location: string) => { const addDelimeter = (str: string) => { return str + ' | ' } + const { + location: { protocol, host }, + } = window - const url = new URL( - `${window.location.protocol}${window.location.host}${location}`, - ) + const url = new URL(`${protocol}${host}${location}`) let result = '' - const isFilter = url.pathname === Routes.Refiner - const isDtree = url.pathname === Routes.Dtree - const isWs = url.pathname === Routes.WS - - if (isFilter) { - result += 'Simple Filter' - } else if (isDtree) { - result += 'Include/Exclude Criteria' - } else if (isWs) { - result += 'Table' + switch (url.pathname) { + case Routes.Refiner: { + result += t('home.buildFlow.simpleFilter') + break + } + case Routes.Dtree: { + result += t('home.buildFlow.inclusionExclusion') + break + } + case Routes.WS: { + result += t('home.buildFlow.viewVariants') + break + } } result = addDelimeter(result) diff --git a/src/pages/main/components/selected-dataset/components/card-explore/card-start-explore-section.tsx b/src/pages/main/components/selected-dataset/components/card-explore/card-start-explore-section.tsx new file mode 100644 index 000000000..58f9ed423 --- /dev/null +++ b/src/pages/main/components/selected-dataset/components/card-explore/card-start-explore-section.tsx @@ -0,0 +1,101 @@ +import { FC, ReactElement } from 'react' +import noop from 'lodash/noop' +import { observer } from 'mobx-react-lite' + +import { + ExploreKeys, + ExploreTypesDictionary, + TExploreKeys, +} from '@core/enum/explore-types-enum' +import { t } from '@i18n' +import { datasetStore } from '@store/dataset' +import { Button } from '@ui/button' +import { Loader } from '@ui/loader' +import { CardTitleWithEdit } from '../../build-flow/components/cards/components/card-edit-title' +import { useRadioListData } from '../../build-flow/components/cards/components/card-radio.hooks' +import { CardRadioList } from '../../build-flow/components/cards/components/card-radio-list' +import { ICardProps } from '../../build-flow/components/wizard/wizard.interface' +import wizardStore from '../../build-flow/components/wizard/wizard.store' + +export const CardStartExploreSection: FC> = observer( + ({ + id, + continueDisabled, + title, + editDisabled, + selectedValue, + }): ReactElement => { + const onChange = (exploreType: TExploreKeys) => { + wizardStore.setStartWithOption(exploreType, id) + } + + const onContinue = () => { + if (datasetStore.isXL) { + wizardStore.toggleIsWizardVisible(true) + wizardStore.defineAndSetNewScenario() + } else { + wizardStore.finishEditCard(id) + } + } + + const isExploreGenomeDisabled = !datasetStore.isXL + const isExploreCandidateDisabled = !wizardStore.secondaryDatasets?.length + + const isEditionProhibited = + isExploreGenomeDisabled || isExploreCandidateDisabled + + const isEditShown = !isEditionProhibited && !editDisabled + + const radioListData = useRadioListData(ExploreTypesDictionary) + + return datasetStore.isLoading ? ( + + ) : ( +
+ <> +
+ (id ? wizardStore.editCard(id) : noop)} + /> +
+ +
+ + data={radioListData} + onChange={onChange} + selectedOption={selectedValue!} + disabledOptions={{ + [ExploreKeys.Genome]: { + isDisabled: isExploreGenomeDisabled, + placeholder: () => ( + + {t('home.startFlow.genomeIsUnavailable')} + + ), + }, + [ExploreKeys.Candidate]: { + isDisabled: isExploreCandidateDisabled, + placeholder: () => ( + + {t('home.startFlow.candidateIsUnavailable')} + + ), + }, + }} + /> + +
+
+
+ +
+ ) + }, +) diff --git a/src/pages/main/components/selected-dataset/components/dataset-info/dataset-info.tsx b/src/pages/main/components/selected-dataset/components/dataset-info/dataset-info.tsx index 0486ba611..a94e8a3be 100644 --- a/src/pages/main/components/selected-dataset/components/dataset-info/dataset-info.tsx +++ b/src/pages/main/components/selected-dataset/components/dataset-info/dataset-info.tsx @@ -43,7 +43,11 @@ export const DatasetInfo: FC = observer(({ className }) => { ) return ( - +
{ - return ( - -
- - - -
-
- ) -}) diff --git a/src/pages/main/components/selected-dataset/start-flow/components/card-sections/card-start-explore-section.tsx b/src/pages/main/components/selected-dataset/start-flow/components/card-sections/card-start-explore-section.tsx deleted file mode 100644 index 9eb6b21a4..000000000 --- a/src/pages/main/components/selected-dataset/start-flow/components/card-sections/card-start-explore-section.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { ReactElement, useState } from 'react' -import { observer } from 'mobx-react-lite' - -import { - ExploreKeys, - ExploreTypesDictionary, - TExploreKeys, -} from '@core/enum/explore-types-enum' -import { datasetStore } from '@store/dataset' -import { Button } from '@ui/button' -import { CardTitle } from '@ui/card' -import { useRadioListData } from '../../../build-flow/components/cards/components/card-radio.hooks' -import { CardRadioList } from '../../../build-flow/components/cards/components/card-radio-list' -import { wizardScenarios } from '../../../build-flow/components/wizard/scenarios/wizard-scenarious' -import wizardStore from '../../../build-flow/components/wizard/wizard.store' - -export const CardStartExploreSection = observer((): ReactElement => { - const [selectedValue, setSelectedValue] = useState( - ExploreKeys.Genome, - ) - const onChange = (exploreType: TExploreKeys) => { - setSelectedValue(exploreType) - } - - const onContinue = () => { - wizardStore.toggleIsWizardVisible(true) - const scenario = - selectedValue === ExploreKeys.Genome - ? wizardScenarios.XlWholeGenome - : wizardScenarios.XlCandidateSet - - wizardStore.setScenario(scenario) - } - - const isExploreGenomeDisabled = !datasetStore.isXL - const isExploreCandidateDisabled = - !wizardStore.secondaryDatasets && datasetStore.isXL - - const startExploreData = useRadioListData( - ExploreTypesDictionary, - ) - - return ( -
- <> -
- -
- -
- - data={startExploreData} - onChange={value => onChange(value)} - selectedOption={selectedValue} - disabledOptions={{ - [ExploreKeys.Candidate]: isExploreCandidateDisabled, - [ExploreKeys.Genome]: isExploreGenomeDisabled, - }} - /> - -
-
-
- -
- ) -}) diff --git a/src/pages/main/components/selected-dataset/start-flow/components/dataset-fields-list/components/info-details.tsx b/src/pages/main/components/selected-dataset/start-flow/components/dataset-fields-list/components/info-details.tsx index c7f9e7042..f92617e76 100644 --- a/src/pages/main/components/selected-dataset/start-flow/components/dataset-fields-list/components/info-details.tsx +++ b/src/pages/main/components/selected-dataset/start-flow/components/dataset-fields-list/components/info-details.tsx @@ -36,7 +36,7 @@ export const InfoDetails = observer((): ReactElement => { }, []) return ( - +
}
- +
diff --git a/src/ui/card/card.module.css b/src/ui/card/card.module.css index fd9073196..94741f6ce 100644 --- a/src/ui/card/card.module.css +++ b/src/ui/card/card.module.css @@ -1,11 +1,15 @@ .card { - border-radius: theme("spacing.2"); - box-shadow: theme("boxShadow.card"); - padding: theme("spacing.4"); + display: flex; + flex-direction: column; + border-radius: theme('spacing.2'); + box-shadow: theme('boxShadow.card'); + padding: theme('spacing.4'); + width: calc(50% - 8px); &_title { font-weight: 700 !important; - color: theme("colors.blue.dark"); + color: theme('colors.blue.dark'); + margin-bottom: 8px; &_md { @apply typography-l; @@ -27,4 +31,20 @@ opacity: 0; transform: translateY(40px); } + + &_position-right { + margin-top: 16px; + float: right; + clear: right; + } + + &_position-left { + margin-top: 16px; + float: left; + clear: left; + } + + &_position-stretch { + width: 100%; + } } diff --git a/src/ui/card/card.tsx b/src/ui/card/card.tsx index d6311ba81..2bb3acc44 100644 --- a/src/ui/card/card.tsx +++ b/src/ui/card/card.tsx @@ -13,7 +13,7 @@ import { import { Transition } from 'react-transition-group' import cn, { Argument } from 'classnames' -import { useForkRef } from '@core/hooks/use-fork-ref' +import { TCardPosition } from '@pages/main/components/selected-dataset/build-flow/components/wizard/wizard.interface' interface ICardProps { children?: ReactElement | ReactNode @@ -21,6 +21,7 @@ interface ICardProps { innerRef?: Ref isNeedToAnimate?: boolean style?: CSSProperties + position?: TCardPosition } const TRANSITION_DURATION = 400 @@ -31,10 +32,10 @@ export const Card = forwardRef( children, className, isNeedToAnimate, + position, }: ICardProps): ReactElement => { const [isMounted, setIsMounted] = useState(false) const cardRef = useRef(null) - const ref = useForkRef(cardRef, innerRef) useEffect(() => { window.setTimeout(() => setIsMounted(true), 0) @@ -42,8 +43,13 @@ export const Card = forwardRef( const renderCard = (state = '') => (
{state => { return renderCard(state)