Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI 2 #1255

Closed
wants to merge 16 commits into from
Closed

UI 2 #1255

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions packages_rs/nextclade-web/src/components/Main/DatasetSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ export function DatasetSelector() {
<Container>
<Header>
<Title>{t('Select dataset')}</Title>

<SearchBox searchTitle={t('Search datasets')} searchTerm={searchTerm} onSearchTermChange={setSearchTerm} />
</Header>
<Header>
<SuggestionPanel />
</Header>

<Main>
{!isBusy && (
Expand All @@ -42,10 +44,6 @@ export function DatasetSelector() {
</SpinnerWrapper>
)}
</Main>

<Footer>
<SuggestionPanel />
</Footer>
</Container>
)
}
Expand All @@ -62,7 +60,6 @@ const Container = styled.div`
const Header = styled.div`
display: flex;
flex: 0;
padding-left: 10px;
margin-top: 10px;
margin-bottom: 3px;
`
Expand All @@ -74,11 +71,6 @@ const Main = styled.div`
overflow: hidden;
`

const Footer = styled.div`
display: flex;
flex: 0;
`

const Title = styled.h4`
flex: 1;
margin: auto 0;
Expand Down
111 changes: 91 additions & 20 deletions packages_rs/nextclade-web/src/components/Main/DatasetSelectorList.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import { get, isNil, sortBy } from 'lodash'
import { lighten } from 'polished'
import React, { forwardRef, useCallback, useEffect, useMemo, useRef } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil'
import { Button } from 'reactstrap'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { ListGenericCss } from 'src/components/Common/List'
import { DatasetInfo } from 'src/components/Main/DatasetInfo'
import { search } from 'src/helpers/search'
import { useTranslationSafe } from 'src/helpers/useTranslationSafe'
import { useRunAnalysis } from 'src/hooks/useRunAnalysis'
import { useRunSeqAutodetect } from 'src/hooks/useRunSeqAutodetect'
import { AlgorithmInputDefault } from 'src/io/AlgorithmInput'
import {
autodetectResultsAtom,
AutodetectRunState,
autodetectRunStateAtom,
groupByDatasets,
} from 'src/state/autodetect.state'
import { datasetCurrentAtom } from 'src/state/dataset.state'
import { hasInputErrorsAtom } from 'src/state/error.state'
import { hasRequiredInputsAtom, useQuerySeqInputs } from 'src/state/inputs.state'
import { canRunAtom } from 'src/state/results.state'
import { shouldRunAutomaticallyAtom, shouldSuggestDatasetsAtom } from 'src/state/settings.state'
import type { Dataset } from 'src/types'
import { areDatasetsEqual } from 'src/types'
import styled from 'styled-components'
Expand All @@ -29,7 +39,12 @@ export function DatasetSelectorList({
datasetHighlighted,
onDatasetHighlighted,
}: DatasetSelectorListProps) {
const onItemClick = useCallback((dataset: Dataset) => () => onDatasetHighlighted(dataset), [onDatasetHighlighted])
const onItemClick = useCallback(
(_dataset: Dataset) => () => {
/* onDatasetHighlighted(dataset) */
},
[],
)

const autodetectResults = useRecoilValue(autodetectResultsAtom)
const [autodetectRunState, setAutodetectRunState] = useRecoilState(autodetectRunStateAtom)
Expand Down Expand Up @@ -73,24 +88,10 @@ export function DatasetSelectorList({

const itemsRef = useRef<Map<string, HTMLLIElement>>(new Map())

function scrollToId(itemId: string) {
const node = itemsRef.current.get(itemId)
node?.scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'center',
})
}

if (datasetHighlighted) {
scrollToId(datasetHighlighted.path)
}

useEffect(() => {
const topSuggestion = autodetectResult.itemsInclude[0]
if (autodetectRunState === AutodetectRunState.Done) {
onDatasetHighlighted(topSuggestion)
setAutodetectRunState(AutodetectRunState.Idle)
}
}, [autodetectRunState, autodetectResult.itemsInclude, onDatasetHighlighted, setAutodetectRunState])

Expand Down Expand Up @@ -145,12 +146,12 @@ export const Ul = styled.ul`
${ListGenericCss};
flex: 1;
overflow: auto;
padding: 5px 5px;
border-radius: 0 !important;
`

export const Li = styled.li<{ $active?: boolean; $isDimmed?: boolean }>`
cursor: pointer;
position: relative;

opacity: ${(props) => props.$isDimmed && 0.4};
background-color: transparent;

Expand All @@ -176,11 +177,81 @@ interface DatasetSelectorListItemProps {
}

const DatasetSelectorListItem = forwardRef<HTMLLIElement, DatasetSelectorListItemProps>(
function DatasetSelectorListItemWithRef({ dataset, isCurrent, isDimmed, onClick }, ref) {
function DatasetSelectorListItemWithRef({ dataset, isDimmed, onClick }, ref) {
const { t } = useTranslationSafe()

const setDatasetCurrent = useSetRecoilState(datasetCurrentAtom)
const shouldRunAutomatically = useRecoilValue(shouldRunAutomaticallyAtom)
const shouldSuggestDatasets = useRecoilValue(shouldSuggestDatasetsAtom)
const { addQryInputs } = useQuerySeqInputs()
const canRun = useRecoilValue(canRunAtom)
const hasRequiredInputs = useRecoilValue(hasRequiredInputsAtom)
const hasInputErrors = useRecoilValue(hasInputErrorsAtom)

const runAnalysis = useRunAnalysis()
const runSuggestions = useRunSeqAutodetect()
const run = useCallback(() => {
setDatasetCurrent(dataset)
runAnalysis()
}, [dataset, runAnalysis, setDatasetCurrent])

const { isRunButtonDisabled, runButtonColor, runButtonTooltip } = useMemo(() => {
const isRunButtonDisabled = !(canRun && hasRequiredInputs) || hasInputErrors
return {
isRunButtonDisabled,
runButtonColor: isRunButtonDisabled ? 'secondary' : 'success',
runButtonTooltip: isRunButtonDisabled
? t('Please provide sequence data for the algorithm')
: t('Launch the algorithm!'),
}
}, [canRun, hasInputErrors, hasRequiredInputs, t])

const setExampleSequences = useCallback(() => {
addQryInputs([new AlgorithmInputDefault(dataset)])
if (shouldSuggestDatasets) {
runSuggestions()
}
if (shouldRunAutomatically) {
runAnalysis()
}
}, [addQryInputs, dataset, runAnalysis, runSuggestions, shouldRunAutomatically, shouldSuggestDatasets])

return (
<Li ref={ref} $isDimmed={isDimmed} aria-current={isCurrent} $active={isCurrent} onClick={onClick}>
<Li ref={ref} $isDimmed={isDimmed} onClick={onClick}>
<DatasetInfo dataset={dataset} />

<ButtonLoadExample color="link" onClick={setExampleSequences}>
{t('Load example')}
</ButtonLoadExample>

<ButtonRunStyled disabled={isRunButtonDisabled} color={runButtonColor} onClick={run} title={runButtonTooltip}>
{t('Run')}
</ButtonRunStyled>
</Li>
)
},
)

const ButtonRunStyled = styled(Button)`
position: absolute;
bottom: 10px;
right: 10px;
min-width: 120px;
min-height: 30px;
`

const ButtonLoadExample = styled(Button)`
position: absolute;
bottom: 45px;
right: 2px;
min-width: 120px;
min-height: 30px;
`

export const FlexRight = styled.div`
position: absolute;
`

export const FlexLeft = styled.div`
margin-right: auto;
`
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useUpdatedDatasetIndex } from 'src/io/fetchDatasets'
import { DatasetSelector } from 'src/components/Main/DatasetSelector'

const Container = styled.div`
max-width: ${(props) => props.theme.containerMaxWidths.twoxl};
margin: 0 auto;
height: 100%;
overflow: hidden;
Expand All @@ -28,12 +29,12 @@ export function MainInputForm() {

return (
<Container>
<Row noGutters className="flex-column-reverse flex-lg-row">
<Row noGutters className="flex-column flex-lg-row">
<Col lg={6} className="">
<DatasetSelector />
<QuerySequenceFilePicker />
</Col>
<Col lg={6} className="">
<QuerySequenceFilePicker />
<DatasetSelector />
</Col>
</Row>
</Container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useRecoilValue } from 'recoil'
import styled from 'styled-components'
import type { AlgorithmInput } from 'src/types'
import { QuerySequenceList } from 'src/components/Main/QuerySequenceList'
import { RunPanel } from 'src/components/Main/RunPanel'
import { useRunAnalysis } from 'src/hooks/useRunAnalysis'
import { useRunSeqAutodetect } from 'src/hooks/useRunSeqAutodetect'
import { useRecoilToggle } from 'src/hooks/useToggle'
Expand Down Expand Up @@ -67,10 +66,6 @@ export function QuerySequenceFilePicker() {
<Main>
<QuerySequenceList />
</Main>

<Footer>
<RunPanel />
</Footer>
</Container>
)
}
Expand All @@ -97,8 +92,3 @@ const Main = styled.div`
flex-direction: column;
overflow: hidden;
`

const Footer = styled.div`
display: flex;
flex: 0;
`
Loading