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

Add new analysis button to all analyses component in map #459

Merged
merged 21 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
003ff2b
Add new analysis button to all analyses component in map
chowington Aug 30, 2023
7e4ca66
Merge branch 'main' into 425-add-new-analysis-button-in-map
chowington Aug 30, 2023
5a9d838
Clean up
chowington Aug 30, 2023
7ab90e6
Move the timeout before redirecting to the dialog component
chowington Aug 30, 2023
fb1d385
Delete comment
chowington Aug 30, 2023
c723caf
Merge branch 'main' into 425-add-new-analysis-button-in-map
chowington Sep 7, 2023
8e3e876
Use subsettingclient from props instead of hook
chowington Sep 7, 2023
966c84b
Merge branch 'main' into 425-add-new-analysis-button-in-map
chowington Sep 11, 2023
31293ab
Render button in panel instead of AllAnalyses
chowington Sep 12, 2023
57ff3f6
Remove remaining new analysis logic from AllAnalyses
chowington Sep 12, 2023
0be83b0
Clean up MapAnalysis
chowington Sep 12, 2023
e26be00
More cleanup
chowington Sep 12, 2023
d06f2da
Merge branch 'main' into 425-add-new-analysis-button-in-map
chowington Sep 12, 2023
e637576
Merge branch 'main' into 425-add-new-analysis-button-in-map
chowington Sep 18, 2023
309e786
Center plus icon in button
chowington Sep 19, 2023
768391c
Merge branch 'main' into 425-add-new-analysis-button-in-map
chowington Sep 25, 2023
df07727
WIP fix for map not rendering new analysis
chowington Sep 25, 2023
8071c9f
Merge branch 'main' into 425-add-new-analysis-button-in-map
chowington Oct 2, 2023
371ca5b
Fix failing to rerender on new analysis bug
chowington Oct 2, 2023
5f9188e
Merge branch 'main' into 425-add-new-analysis-button-in-map
chowington Oct 19, 2023
644b302
Remove uppercase textTransform on button
chowington Oct 19, 2023
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
19 changes: 19 additions & 0 deletions packages/libs/coreui/src/components/icons/Plus.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { SVGProps } from 'react';
import { Add } from '@material-ui/icons';

const Plus = (props: SVGProps<SVGSVGElement>) => {
const { height = '1em', width = '1em' } = props;
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100"
height={height}
width={width}
{...props}
>
<Add />
</svg>
);
};

export default Plus;
1 change: 1 addition & 0 deletions packages/libs/coreui/src/components/icons/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export { default as Filter } from './Filter';
export { default as Loading } from './Loading';
export { default as NoEdit } from './NoEdit';
export { default as Pencil } from './Pencil';
export { default as Plus } from './Plus';
export { default as SampleDetailsDark } from './SampleDetailsDark';
export { default as SampleDetailsLight } from './SampleDetailsLight';
export { default as Share } from './Share';
Expand Down
48 changes: 43 additions & 5 deletions packages/libs/eda/src/lib/map/analysis/MapAnalysis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
NumberVariable,
OverlayConfig,
PromiseResult,
useAnalysis,
useAnalysisClient,
useDataClient,
useDownloadClient,
Expand All @@ -31,8 +30,10 @@ import { DocumentationContainer } from '../../core/components/docs/Documentation
import {
CheckIcon,
Download,
Plus,
FilledButton,
Filter as FilterIcon,
FloatingButton,
H5,
Table,
} from '@veupathdb/coreui';
Expand Down Expand Up @@ -73,9 +74,10 @@ import { useLoginCallbacks } from '../../workspace/sharing/hooks';
import NameAnalysis from '../../workspace/sharing/NameAnalysis';
import NotesTab from '../../workspace/NotesTab';
import ConfirmShareAnalysis from '../../workspace/sharing/ConfirmShareAnalysis';
import { useHistory } from 'react-router';
import { useHistory, useRouteMatch } from 'react-router';

import { uniq } from 'lodash';
import Path from 'path';
import DownloadTab from '../../workspace/DownloadTab';
import { RecordController } from '@veupathdb/wdk-client/lib/Controllers';
import {
Expand Down Expand Up @@ -120,6 +122,7 @@ import { DraggablePanelCoordinatePair } from '@veupathdb/coreui/lib/components/c
import _ from 'lodash';

import EZTimeFilter from './EZTimeFilter';
import AnalysisNameDialog from '../../workspace/AnalysisNameDialog';

enum MapSideNavItemLabels {
Download = 'Download',
Expand Down Expand Up @@ -213,8 +216,7 @@ interface Props {
}

export function MapAnalysis(props: Props) {
const analysisState = useAnalysis(props.analysisId, 'pass');
const appStateAndSetters = useAppState('@@mapApp@@', analysisState);
const appStateAndSetters = useAppState('@@mapApp@@', props.analysisId);
const geoConfigs = useGeoConfig(useStudyEntities());

if (geoConfigs == null || geoConfigs.length === 0)
Expand All @@ -231,7 +233,6 @@ export function MapAnalysis(props: Props) {
<MapAnalysisImpl
{...props}
{...(appStateAndSetters as CompleteAppState)}
analysisState={analysisState}
geoConfigs={geoConfigs}
/>
);
Expand Down Expand Up @@ -747,6 +748,18 @@ function MapAnalysisImpl(props: ImplProps) {

const filteredEntities = uniq(filters?.map((f) => f.entityId));

const [isAnalysisNameDialogOpen, setIsAnalysisNameDialogOpen] =
useState(false);
const { url: urlRouteMatch } = useRouteMatch();
const redirectURL = studyId
? urlRouteMatch.endsWith(studyId)
? `/workspace/${urlRouteMatch}/new`
: Path.resolve(urlRouteMatch, '../new')
: null;
const redirectToNewAnalysis = useCallback(() => {
if (redirectURL) history.push(redirectURL);
}, [history, redirectURL]);

const sideNavigationButtonConfigurationObjects: SideNavigationItemConfigurationObject[] =
[
{
Expand Down Expand Up @@ -1101,6 +1114,31 @@ function MapAnalysisImpl(props: ImplProps) {
maxWidth: '1500px',
}}
>
{analysisId && redirectToNewAnalysis ? (
<div style={{ float: 'right' }}>
<FloatingButton
text="Create new analysis"
icon={Plus}
onPress={
analysisState.analysis?.displayName ===
DEFAULT_ANALYSIS_NAME
? () => setIsAnalysisNameDialogOpen(true)
: redirectToNewAnalysis
}
/>
</div>
) : (
<></>
)}
{analysisState.analysis && (
<AnalysisNameDialog
isOpen={isAnalysisNameDialogOpen}
setIsOpen={setIsAnalysisNameDialogOpen}
initialAnalysisName={analysisState.analysis.displayName}
setAnalysisName={analysisState.setName}
redirectToNewAnalysis={redirectToNewAnalysis}
/>
)}
<AllAnalyses
analysisClient={analysisClient}
activeAnalysisId={
Expand Down
37 changes: 24 additions & 13 deletions packages/libs/eda/src/lib/map/analysis/appState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@ import { getOrElseW } from 'fp-ts/lib/Either';
import { pipe } from 'fp-ts/lib/function';
import * as t from 'io-ts';
import { isEqual } from 'lodash';
import { useCallback, useEffect, useMemo, useRef } from 'react';
import {
AnalysisState,
useGetDefaultVariableDescriptor,
useStudyMetadata,
} from '../../core';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useAnalysis, useGetDefaultVariableDescriptor } from '../../core';
import { VariableDescriptor } from '../../core/types/variable';
import { useGetDefaultTimeVariableDescriptor } from './hooks/eztimeslider';

Expand Down Expand Up @@ -122,7 +118,17 @@ export const defaultViewport: AppState['viewport'] = {
zoom: 1,
};

export function useAppState(uiStateKey: string, analysisState: AnalysisState) {
export function useAppState(uiStateKey: string, analysisId?: string) {
const analysisState = useAnalysis(analysisId);

// make some backwards compatability updates to the appstate retrieved from the back end
const [appStateChecked, setAppStateChecked] = useState(false);

useEffect(() => {
// flip bit when analysis id changes
setAppStateChecked(false);
}, [analysisId]);

const { analysis, setVariableUISettings } = analysisState;
const appState = pipe(
AppState.decode(
Expand Down Expand Up @@ -177,11 +183,8 @@ export function useAppState(uiStateKey: string, analysisState: AnalysisState) {
[defaultVariable, defaultTimeVariable]
);

// make some backwards compatability updates to the appstate retrieved from the back end
const appStateCheckedRef = useRef(false);

useEffect(() => {
if (appStateCheckedRef.current) return;
if (appStateChecked) return;
if (analysis) {
if (!appState) {
setVariableUISettings((prev) => ({
Expand Down Expand Up @@ -216,9 +219,16 @@ export function useAppState(uiStateKey: string, analysisState: AnalysisState) {
}));
}
}
appStateCheckedRef.current = true;
setAppStateChecked(true);
}
}, [analysis, appState, setVariableUISettings, uiStateKey, defaultAppState]);
}, [
analysis,
appState,
setVariableUISettings,
uiStateKey,
defaultAppState,
appStateChecked,
]);

function useSetter<T extends keyof AppState>(key: T) {
return useCallback(
Expand All @@ -243,6 +253,7 @@ export function useAppState(uiStateKey: string, analysisState: AnalysisState) {

return {
appState,
analysisState,
setActiveMarkerConfigurationType: useSetter(
'activeMarkerConfigurationType'
),
Expand Down
32 changes: 21 additions & 11 deletions packages/libs/eda/src/lib/workspace/AnalysisNameDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,25 @@ interface AnalysisNameDialogProps {
redirectToNewAnalysis: () => void;
}

export function AnalysisNameDialog({
export default function AnalysisNameDialog({
isOpen,
setIsOpen,
initialAnalysisName,
setAnalysisName,
redirectToNewAnalysis,
}: AnalysisNameDialogProps) {
const [inputText, setInputText] = useState(initialAnalysisName);
const [continueText, setContinueText] =
useState<'Continue' | 'Rename and continue'>('Continue');
const [nameIsValid, setNameIsValid] = useState(true);
const [disableButtons, setDisableButtons] = useState(false);

const handleTextChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const newText = event.target.value;
setInputText(newText);
setContinueText(
newText === initialAnalysisName ? 'Continue' : 'Rename and continue'
);
// Currently the only requirement is no empty name
newText.length > 0 ? setNameIsValid(true) : setNameIsValid(false);
};
Expand All @@ -44,11 +50,12 @@ export function AnalysisNameDialog({
setInputText(initialAnalysisName);
};

const handleContinue = async () => {
// TypeScript says this `await` has no effect, but it seems to be required
// for this function to finish before the page redirect
await setAnalysisName(inputText);
redirectToNewAnalysis();
const handleContinue = () => {
setDisableButtons(true);
setAnalysisName(inputText);
// The timeout for saving an analysis is 1 second,
// so wait a bit longer than that
setTimeout(redirectToNewAnalysis, 1200);
};

return (
Expand All @@ -74,20 +81,23 @@ export function AnalysisNameDialog({
error={!nameIsValid}
// Currently the only requirement is no empty name
helperText={nameIsValid ? ' ' : 'Name must not be blank'}
disabled={disableButtons}
/>
</DialogContent>
<DialogActions>
<Button onClick={handleCancel} color="secondary">
<Button
onClick={handleCancel}
color="secondary"
disabled={disableButtons}
>
Cancel
</Button>
<Button
onClick={handleContinue}
color="primary"
disabled={!nameIsValid}
disabled={!nameIsValid || disableButtons}
>
{inputText === initialAnalysisName
? 'Continue'
: 'Rename and continue'}
{continueText}
</Button>
</DialogActions>
</Dialog>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Path from 'path';
import { H3, Table, FloatingButton } from '@veupathdb/coreui';

import { safeHtml } from '@veupathdb/wdk-client/lib/Utils/ComponentUtils';
import { AnalysisNameDialog } from './AnalysisNameDialog';
import AnalysisNameDialog from './AnalysisNameDialog';
import AddIcon from '@material-ui/icons/Add';

// Hooks
Expand Down
Loading