Skip to content

Commit

Permalink
feat: support multiple analysis methods per category (#279) (#296)
Browse files Browse the repository at this point in the history
  • Loading branch information
frano-m authored Feb 14, 2025
1 parent b208c53 commit 57d55db
Show file tree
Hide file tree
Showing 16 changed files with 243 additions and 145 deletions.
Original file line number Diff line number Diff line change
@@ -1,77 +1,65 @@
import { GridPaperSection } from "@databiosphere/findable-ui/lib/components/common/Section/section.styles";
import {
inkLight,
smokeDark,
smokeLightest,
white,
} from "@databiosphere/findable-ui/lib/styles/common/mixins/colors";
import {
textBody4002Lines,
textBody500,
} from "@databiosphere/findable-ui/lib/styles/common/mixins/fonts";
import { css } from "@emotion/react";
import styled from "@emotion/styled";
import { Accordion } from "@mui/material";
import { smokeLightest } from "@databiosphere/findable-ui/lib/theme/common/palette";
import { elevation01 } from "@databiosphere/findable-ui/lib/theme/common/shadows";

interface Props {
isAvailable: boolean;
}
export const StyledAccordion = styled(Accordion)`
&.MuiAccordion-root {
background-color: ${white};
box-shadow: ${elevation01};
export const StyledSection = styled(GridPaperSection, {
shouldForwardProp: (props) => props !== "isAvailable",
})<Props>`
flex-direction: row;
gap: 16px;
.MuiAccordion-heading {
display: block;
padding: 20px;
.MuiChip-root,
.MuiSvgIcon-root {
align-self: center;
}
.MuiAccordionSummary-root {
flex-direction: row;
gap: 16px;
.MuiSvgIcon-root {
transform: rotate(180deg);
transition: transform 300ms;
}
.MuiAccordionSummary-content {
display: flex;
flex-direction: column;
gap: 4px;
margin: 0;
&:hover {
.MuiSvgIcon-root {
transform: rotate(180deg) translateX(-2px);
}
}
.MuiTypography-root {
margin: 0;
${(props) =>
props.isAvailable &&
css`
cursor: pointer;
`}
&.MuiTypography-text-heading-small {
font-size: 16px;
letter-spacing: normal;
line-height: 24px;
}
}
}
${(props) =>
!props.isAvailable &&
css`
background-color: ${smokeLightest(props)};
pointer-events: none;
.MuiAccordionSummary-expandIconWrapper {
.MuiSvgIcon-root {
transform: rotate(90deg);
}
.MuiChip-root {
.MuiChip-label {
color: ${inkLight(props)};
.MuiChip-root {
color: ${inkLight};
}
}
}
.MuiSvgIcon-root {
color: ${smokeDark(props)};
&.Mui-disabled {
opacity: 1;
}
}
`}
`;

export const SectionContent = styled.div`
flex: 1;
}
h3 {
${textBody500};
margin: 0 0 4px;
}
.MuiAccordionDetails-root {
margin: 0;
padding: 0;
}
p {
${textBody4002Lines};
color: ${inkLight};
margin: 0;
&.Mui-disabled {
background-color: ${smokeLightest};
}
}
`;
` as typeof Accordion;
96 changes: 46 additions & 50 deletions app/components/Entity/components/AnalysisMethod/analysisMethod.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,56 @@
import { SouthIcon } from "@databiosphere/findable-ui/lib/components/common/CustomIcon/components/SouthIcon/southIcon";
import { STATUS_BADGE_COLOR } from "@databiosphere/findable-ui/lib/components/common/StatusBadge/statusBadge";
import {
ANCHOR_TARGET,
REL_ATTRIBUTE,
} from "@databiosphere/findable-ui/lib/components/Links/common/entities";
import {
Loading,
LOADING_PANEL_STYLE,
} from "@databiosphere/findable-ui/lib/components/Loading/loading";
import { useAsync } from "@databiosphere/findable-ui/lib/hooks/useAsync";
import { Chip } from "@mui/material";
import { getWorkflowLandingUrl } from "app/utils/galaxy-api";
import { SectionContent, StyledSection } from "./analysisMethod.styles";
import { CHIP_PROPS, ICON_PROPS } from "./constants";
AccordionDetails,
AccordionSummary,
Chip,
Divider,
Typography,
} from "@mui/material";
import { StyledAccordion } from "./analysisMethod.styles";
import { CHIP_PROPS, ICON_PROPS, TYPOGRAPHY_PROPS } from "./constants";
import { Props } from "./types";
import { FluidPaper } from "@databiosphere/findable-ui/lib/components/common/Paper/paper.styles";
import { TEXT_HEADING_SMALL } from "@databiosphere/findable-ui/lib/theme/common/typography";
import { Fragment } from "react";
import { Workflow } from "./components/Workflow/workflow";
import { ChevronRightRounded } from "@mui/icons-material";

export const AnalysisMethod = ({
content,
geneModelUrl,
genomeVersionAssemblyId,
workflowId,
workflowCategory,
workflows,
}: Props): JSX.Element => {
const isAvailable = Boolean(workflowId);
const { data: landingUrl, isLoading, run } = useAsync<string>();
const isDisabled = workflows.length === 0;
return (
<StyledSection
isAvailable={isAvailable}
onClick={async (): Promise<void> => {
if (!workflowId) return;
const url =
landingUrl ??
(await run(
getWorkflowLandingUrl(
workflowId,
genomeVersionAssemblyId,
geneModelUrl
)
));
window.open(
url,
ANCHOR_TARGET.BLANK,
REL_ATTRIBUTE.NO_OPENER_NO_REFERRER
);
}}
role="button"
>
<Loading loading={isLoading} panelStyle={LOADING_PANEL_STYLE.INHERIT} />
<SectionContent>{content}</SectionContent>
{!isAvailable && (
<Chip
{...CHIP_PROPS}
color={STATUS_BADGE_COLOR.DEFAULT}
label="Coming Soon"
/>
)}
<SouthIcon {...ICON_PROPS} />
</StyledSection>
<StyledAccordion component={FluidPaper} disabled={isDisabled}>
<AccordionSummary
expandIcon={
isDisabled ? (
<Chip {...CHIP_PROPS} />
) : (
<ChevronRightRounded {...ICON_PROPS} />
)
}
>
<Typography variant={TEXT_HEADING_SMALL}>
{workflowCategory.name}
</Typography>
<Typography {...TYPOGRAPHY_PROPS}>
{workflowCategory.description}
</Typography>
</AccordionSummary>
<AccordionDetails>
{workflows.map((workflow) => (
<Fragment key={workflow.workflowName}>
<Divider />
<Workflow
geneModelUrl={geneModelUrl}
genomeVersionAssemblyId={genomeVersionAssemblyId}
workflow={workflow}
/>
</Fragment>
))}
</AccordionDetails>
</StyledAccordion>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Grid2Props, SvgIconProps } from "@mui/material";

export const GRID2_PROPS: Grid2Props = {
container: true,
role: "button",
spacing: 4,
wrap: "nowrap",
};

export const ICON_PROPS: Partial<SvgIconProps> = {
color: "inkLight",
fontSize: "small",
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Workflow } from "../../../../../../apis/catalog/brc-analytics-catalog/common/entities";
import { Props as AnalysisMethodsProps } from "../../../AnalysisMethodsCatalog/types";

export interface Props extends AnalysisMethodsProps {
workflow: Workflow;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import styled from "@emotion/styled";
import { Grid2 } from "@mui/material";

export const StyledGrid2 = styled(Grid2)`
cursor: pointer;
padding: 20px;
.MuiSvgIcon-root {
align-self: center;
transform: rotate(180deg);
transition: transform 300ms;
}
&:hover {
.MuiSvgIcon-root {
transform: rotate(180deg) translateX(-2px);
}
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { SouthIcon } from "@databiosphere/findable-ui/lib/components/common/CustomIcon/components/SouthIcon/southIcon";
import {
Loading,
LOADING_PANEL_STYLE,
} from "@databiosphere/findable-ui/lib/components/Loading/loading";
import { useAsync } from "@databiosphere/findable-ui/lib/hooks/useAsync";
import { Grid2, Typography } from "@mui/material";
import { Props } from "./types";
import { TEXT_BODY_500 } from "@databiosphere/findable-ui/lib/theme/common/typography";
import { getWorkflowLandingUrl } from "../../../../../../utils/galaxy-api";
import {
ANCHOR_TARGET,
REL_ATTRIBUTE,
} from "@databiosphere/findable-ui/lib/components/Links/common/entities";
import { StyledGrid2 } from "./workflow.styles";
import { TYPOGRAPHY_PROPS } from "../../constants";
import { GRID2_PROPS, ICON_PROPS } from "./constants";

export const Workflow = ({
geneModelUrl,
genomeVersionAssemblyId,
workflow,
}: Props): JSX.Element => {
const { trsId, workflowDescription, workflowName } = workflow;
const { data: landingUrl, isLoading, run } = useAsync<string>();
return (
<StyledGrid2
{...GRID2_PROPS}
onClick={async (): Promise<void> => {
if (!trsId) return;
const url =
landingUrl ??
(await run(
getWorkflowLandingUrl(trsId, genomeVersionAssemblyId, geneModelUrl)
));
window.open(
url,
ANCHOR_TARGET.BLANK,
REL_ATTRIBUTE.NO_OPENER_NO_REFERRER
);
}}
>
<Loading loading={isLoading} panelStyle={LOADING_PANEL_STYLE.INHERIT} />
<Grid2 container spacing={1}>
<Typography variant={TEXT_BODY_500}>{workflowName}</Typography>
<Typography {...TYPOGRAPHY_PROPS}>{workflowDescription}</Typography>
</Grid2>
<SouthIcon {...ICON_PROPS} />
</StyledGrid2>
);
};
11 changes: 10 additions & 1 deletion app/components/Entity/components/AnalysisMethod/constants.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { ChipProps, SvgIconProps } from "@mui/material";
import { TEXT_BODY_400_2_LINES } from "@databiosphere/findable-ui/lib/theme/common/typography";
import { STATUS_BADGE_COLOR } from "@databiosphere/findable-ui/lib/components/common/StatusBadge/statusBadge";

export const CHIP_PROPS: Partial<ChipProps> = {
color: STATUS_BADGE_COLOR.DEFAULT,
label: "Coming Soon",
variant: "status",
};

export const ICON_PROPS: Partial<SvgIconProps> = {
color: "inkLight",
fontSize: "small",
fontSize: "medium",
};

export const TYPOGRAPHY_PROPS = {
color: "ink.light",
variant: TEXT_BODY_400_2_LINES,
};
12 changes: 8 additions & 4 deletions app/components/Entity/components/AnalysisMethod/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { ReactNode } from "react";
import {
Workflow,
WorkflowCategory,
} from "../../../../apis/catalog/brc-analytics-catalog/common/entities";
import { Props as AnalysisMethodsProps } from "../AnalysisMethodsCatalog/types";

export interface Props {
content: ReactNode;
export interface Props extends AnalysisMethodsProps {
geneModelUrl: string | null;
genomeVersionAssemblyId: string;
workflowId: string;
workflowCategory: WorkflowCategory;
workflows: Workflow[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import styled from "@emotion/styled";
import { Typography } from "@mui/material";
import { mediaTabletDown } from "@databiosphere/findable-ui/lib/styles/common/mixins/breakpoints";

export const StyledTypography = styled(Typography)`
& {
font-size: 18px;
letter-spacing: normal;
line-height: 26px;
${mediaTabletDown} {
margin: 0 16px;
}
}
` as typeof Typography;
Loading

0 comments on commit 57d55db

Please sign in to comment.