diff --git a/packages/libs/coreui/src/components/buttons/FloatingButton/index.tsx b/packages/libs/coreui/src/components/buttons/FloatingButton/index.tsx index 94b4c5f6f3..64438d2522 100644 --- a/packages/libs/coreui/src/components/buttons/FloatingButton/index.tsx +++ b/packages/libs/coreui/src/components/buttons/FloatingButton/index.tsx @@ -2,7 +2,7 @@ import { merge } from 'lodash'; import { useMemo } from 'react'; import useUITheme from '../../theming/useUITheme'; -import { blue, gray } from '../../../definitions/colors'; +import { blue, gray, mutedBlue } from '../../../definitions/colors'; import SwissArmyButton from '../SwissArmyButton'; import { ButtonStyleSpec, @@ -100,3 +100,26 @@ export default function FloatingButton({ /> ); } + +export const FloatingButtonWDKStyle: ButtonStyleSpec = { + default: { + color: 'transparent', + textColor: '#069', + fontWeight: 600, + }, + hover: { + color: mutedBlue[100], + textColor: '#069', + fontWeight: 600, + }, + pressed: { + color: mutedBlue[200], + textColor: '#069', + fontWeight: 600, + }, + disabled: { + color: 'transparent', + textColor: gray[500], + fontWeight: 600, + }, +}; diff --git a/packages/libs/coreui/src/components/buttons/OutlinedButton/index.tsx b/packages/libs/coreui/src/components/buttons/OutlinedButton/index.tsx index d28f483a0f..1519e39359 100644 --- a/packages/libs/coreui/src/components/buttons/OutlinedButton/index.tsx +++ b/packages/libs/coreui/src/components/buttons/OutlinedButton/index.tsx @@ -2,7 +2,7 @@ import { merge } from 'lodash'; import { useMemo } from 'react'; import useUITheme from '../../theming/useUITheme'; -import { blue, gray } from '../../../definitions/colors'; +import { blue, gray, mutedBlue } from '../../../definitions/colors'; import SwissArmyButton from '../SwissArmyButton'; import { ButtonStyleSpec, @@ -133,3 +133,51 @@ export default function OutlinedButton({ /> ); } + +// Styled for use in the wdk +export const OutlinedButtonWDKStyle = { + default: { + textColor: '#0F86C1', + fontWeight: 600, + color: 'transparent', + border: { + radius: 5, + color: '#0F86C1', + style: 'solid', + width: 2, + }, + }, + hover: { + textColor: mutedBlue[600], + fontWeight: 600, + color: 'transparent', + border: { + radius: 5, + color: mutedBlue[600], + style: 'solid', + width: 2, + }, + }, + pressed: { + textColor: mutedBlue[700], + fontWeight: 600, + color: 'transparent', + border: { + radius: 5, + color: mutedBlue[700], + style: 'solid', + width: 2, + }, + }, + disabled: { + textColor: gray[500], + fontWeight: 600, + color: 'transparent', + border: { + radius: 5, + color: gray[500], + style: 'solid', + width: 2, + }, + }, +}; diff --git a/packages/libs/user-datasets/src/lib/Components/UploadForm.scss b/packages/libs/user-datasets/src/lib/Components/UploadForm.scss index 7a2a5f0465..b5b6125c47 100644 --- a/packages/libs/user-datasets/src/lib/Components/UploadForm.scss +++ b/packages/libs/user-datasets/src/lib/Components/UploadForm.scss @@ -38,7 +38,6 @@ display: flex; flex-direction: column; gap: 0.5em; - padding-left: 1em; padding-right: 1em; > label { diff --git a/packages/libs/user-datasets/src/lib/Components/UploadForm.tsx b/packages/libs/user-datasets/src/lib/Components/UploadForm.tsx index 9bdc3ac67e..b4f88684db 100644 --- a/packages/libs/user-datasets/src/lib/Components/UploadForm.tsx +++ b/packages/libs/user-datasets/src/lib/Components/UploadForm.tsx @@ -36,12 +36,14 @@ import { UserDatasetPublication, } from '../Utils/types'; -import { FloatingButton, Modal } from '@veupathdb/coreui'; +import { FloatingButton, Modal, OutlinedButton } from '@veupathdb/coreui'; +import { OutlinedButtonWDKStyle } from '@veupathdb/coreui/lib/components/buttons/OutlinedButton'; import Banner from '@veupathdb/coreui/lib/components/banners/Banner'; import AddIcon from '@material-ui/icons/Add'; import Trash from '@veupathdb/coreui/lib/components/icons/Trash'; import './UploadForm.scss'; +import { FloatingButtonWDKStyle } from '@veupathdb/coreui/lib/components/buttons/FloatingButton'; const cx = makeClassNameHelper('UploadForm'); @@ -490,143 +492,144 @@ function UploadForm({ />
-
- Additional Details -
- - Publications (Optional) - - {publications.map((publication, index) => { - const updatePublicationsObject = createNestedInputUpdater({ - nestedInputObject: publications, - index, - }); - return ( - { - const updatedPublications = updatePublicationsObject( - value, - 'pubMedId' - ); - setPublications(updatedPublications); - }} - onRemovePublication={( - event: React.MouseEvent - ) => { - event.preventDefault(); - const updatedPublications = [...publications]; - updatedPublications.splice(index, 1); - setPublications(updatedPublications); - }} - citation={publication.citation} - onAddCitation={(value: string) => { - const updatedPublications = updatePublicationsObject( - value, - 'citation' - ); - setPublications(updatedPublications); - }} - /> - ); - })} - ) => { - event.preventDefault(); - setPublications((oldPublications) => [ - ...oldPublications, - {} as UserDatasetPublication, - ]); - }} - icon={AddIcon} - /> -
-
- - Hyperlinks (Optional) - - {hyperlinks.map((hyperlink, index) => { - const updateHyperlinksObject = createNestedInputUpdater({ - nestedInputObject: hyperlinks, - index, - }); - return ( - { - const updatedHyperlinks = updateHyperlinksObject( - value, - 'url' - ); - setHyperlinks(updatedHyperlinks); - }} - onRemoveHyperlink={( - event: React.MouseEvent - ) => { - event.preventDefault(); - const updatedHyperlinks = [...hyperlinks]; - updatedHyperlinks.splice(index, 1); - setHyperlinks(updatedHyperlinks); - }} - text={hyperlink.text} - onAddText={(value: string) => { - const updatedHyperlinks = updateHyperlinksObject( - value, - 'text' - ); - setHyperlinks(updatedHyperlinks); - }} - description={hyperlinks[index]?.description} - onAddDescription={(value: string) => { - const updatedHyperlinks = updateHyperlinksObject( - value, - 'description' - ); - setHyperlinks(updatedHyperlinks); - }} - isPublication={hyperlinks[index]?.isPublication} - onAddIsPublication={(value: boolean) => { - const updatedHyperlinks = updateHyperlinksObject( - value, - 'publication' - ); - setHyperlinks(updatedHyperlinks); - return; - }} - /> - ); - })} - ) => { - event.preventDefault(); - setHyperlinks((oldHyperlinks) => [ - ...oldHyperlinks, - {} as UserDatasetHyperlink, - ]); - }} - icon={AddIcon} - /> -
+
+ + Publications + + {publications.map((publication, index) => { + const updatePublicationsObject = createNestedInputUpdater({ + nestedInputObject: publications, + index, + }); + return ( + { + const updatedPublications = updatePublicationsObject( + value, + 'pubMedId' + ); + setPublications(updatedPublications); + }} + onRemovePublication={( + event: React.MouseEvent + ) => { + event.preventDefault(); + const updatedPublications = [...publications]; + updatedPublications.splice(index, 1); + setPublications(updatedPublications); + }} + citation={publication.citation} + onAddCitation={(value: string) => { + const updatedPublications = updatePublicationsObject( + value, + 'citation' + ); + setPublications(updatedPublications); + }} + /> + ); + })} + ) => { + event.preventDefault(); + setPublications((oldPublications) => [ + ...oldPublications, + {} as UserDatasetPublication, + ]); + }} + icon={AddIcon} + styleOverrides={OutlinedButtonWDKStyle} + /> +
+
+ + Hyperlinks + + {hyperlinks.map((hyperlink, index) => { + const updateHyperlinksObject = createNestedInputUpdater({ + nestedInputObject: hyperlinks, + index, + }); + return ( + { + const updatedHyperlinks = updateHyperlinksObject( + value, + 'url' + ); + setHyperlinks(updatedHyperlinks); + }} + onRemoveHyperlink={( + event: React.MouseEvent + ) => { + event.preventDefault(); + const updatedHyperlinks = [...hyperlinks]; + updatedHyperlinks.splice(index, 1); + setHyperlinks(updatedHyperlinks); + }} + text={hyperlink.text} + onAddText={(value: string) => { + const updatedHyperlinks = updateHyperlinksObject( + value, + 'text' + ); + setHyperlinks(updatedHyperlinks); + }} + description={hyperlinks[index]?.description} + onAddDescription={(value: string) => { + const updatedHyperlinks = updateHyperlinksObject( + value, + 'description' + ); + setHyperlinks(updatedHyperlinks); + }} + isPublication={hyperlinks[index]?.isPublication} + onAddIsPublication={(value: boolean) => { + const updatedHyperlinks = updateHyperlinksObject( + value, + 'publication' + ); + setHyperlinks(updatedHyperlinks); + return; + }} + /> + ); + })} + ) => { + event.preventDefault(); + setHyperlinks((oldHyperlinks) => [ + ...oldHyperlinks, + {} as UserDatasetHyperlink, + ]); + }} + icon={AddIcon} + styleOverrides={OutlinedButtonWDKStyle} + /> +
+ {!datasetUploadType.formConfig.hideRelatedOrganisms && (
- Organisms (Optional) + Related Organisms
{organisms.map((organism, index) => { return (
- Organism {index + 1} + Related Organism {index + 1}
); })}
- ) => { event.preventDefault(); setOrganisms((oldOrganisms) => [...oldOrganisms, '']); }} icon={AddIcon} + styleOverrides={OutlinedButtonWDKStyle} />
-
- - Contacts (Optional) - - {contacts.map((contact, index) => { - const updateContactsObject = createNestedInputUpdater({ - nestedInputObject: contacts, - index, - }); - return ( - { - const updatedContacts = updateContactsObject( - value, - 'name' - ); - setContacts(updatedContacts); - }} - email={contact.email} - onAddEmail={(value: string) => { - const updatedContacts = updateContactsObject( - value, - 'email' - ); - setContacts(updatedContacts); - }} - affiliation={contact.affiliation} - onAddAffiliation={(value: string) => { - const updatedContacts = updateContactsObject( - value, - 'affiliation' - ); - setContacts(updatedContacts); - }} - city={contact.city} - onAddCity={(value: string) => { - const updatedContacts = updateContactsObject( - value, - 'city' - ); - setContacts(updatedContacts); - }} - state={contact.state} - onAddState={(value: string) => { - const updatedContacts = updateContactsObject( - value, - 'state' - ); - setContacts(updatedContacts); - }} - country={contact.country} - onAddCountry={(value: string) => { - const updatedContacts = updateContactsObject( - value, - 'country' - ); - setContacts(updatedContacts); - }} - address={contact.address} - onAddAddress={(value: string) => { - const updatedContacts = updateContactsObject( - value, - 'address' - ); - setContacts(updatedContacts); - }} - isPrimary={contact.isPrimary} - onAddIsPrimary={(value: boolean) => { - const updatedContacts = updateContactsObject( - value, - 'isPrimary' - ); - setContacts(updatedContacts); - return; - }} - onRemoveContact={( - event: React.MouseEvent - ) => { - event.preventDefault(); - const updatedContacts = [...contacts]; - updatedContacts.splice(index, 1); - setContacts(updatedContacts); - }} - /> - ); - })} - ) => { - event.preventDefault(); - setContacts((contacts) => [ - ...contacts, - {} as UserDatasetContact, - ]); - }} - icon={AddIcon} - /> -
-
+ )} +
+ + Contacts + + {contacts.map((contact, index) => { + const updateContactsObject = createNestedInputUpdater({ + nestedInputObject: contacts, + index, + }); + return ( + { + const updatedContacts = updateContactsObject(value, 'name'); + setContacts(updatedContacts); + }} + email={contact.email} + onAddEmail={(value: string) => { + const updatedContacts = updateContactsObject( + value, + 'email' + ); + setContacts(updatedContacts); + }} + affiliation={contact.affiliation} + onAddAffiliation={(value: string) => { + const updatedContacts = updateContactsObject( + value, + 'affiliation' + ); + setContacts(updatedContacts); + }} + city={contact.city} + onAddCity={(value: string) => { + const updatedContacts = updateContactsObject(value, 'city'); + setContacts(updatedContacts); + }} + state={contact.state} + onAddState={(value: string) => { + const updatedContacts = updateContactsObject( + value, + 'state' + ); + setContacts(updatedContacts); + }} + country={contact.country} + onAddCountry={(value: string) => { + const updatedContacts = updateContactsObject( + value, + 'country' + ); + setContacts(updatedContacts); + }} + address={contact.address} + onAddAddress={(value: string) => { + const updatedContacts = updateContactsObject( + value, + 'address' + ); + setContacts(updatedContacts); + }} + isPrimary={contact.isPrimary} + onAddIsPrimary={(value: boolean) => { + const updatedContacts = updateContactsObject( + value, + 'isPrimary' + ); + setContacts(updatedContacts); + return; + }} + onRemoveContact={( + event: React.MouseEvent + ) => { + event.preventDefault(); + const updatedContacts = [...contacts]; + updatedContacts.splice(index, 1); + setContacts(updatedContacts); + }} + /> + ); + })} + ) => { + event.preventDefault(); + setContacts((contacts) => [ + ...contacts, + {} as UserDatasetContact, + ]); + }} + icon={AddIcon} + styleOverrides={OutlinedButtonWDKStyle} + /> +
{datasetUploadType.formConfig.dependencies && (
@@ -1000,6 +1000,7 @@ export function PublicationInput(props: PublicationInputProps): JSX.Element { text="Remove" onPress={onRemovePublication} icon={Trash} + styleOverrides={FloatingButtonWDKStyle} />
@@ -1064,6 +1065,7 @@ function HyperlinkInput(props: HyperlinkInputProps): JSX.Element { text="Remove" onPress={onRemoveHyperlink} icon={Trash} + styleOverrides={FloatingButtonWDKStyle} />
@@ -1161,7 +1163,12 @@ function ContactInput(props: ContactInputProps): JSX.Element { Contact {n + 1} - +
Name diff --git a/packages/libs/user-datasets/src/lib/Components/UploadFormMenu.tsx b/packages/libs/user-datasets/src/lib/Components/UploadFormMenu.tsx index 6687a8ea28..4e923a7d91 100644 --- a/packages/libs/user-datasets/src/lib/Components/UploadFormMenu.tsx +++ b/packages/libs/user-datasets/src/lib/Components/UploadFormMenu.tsx @@ -20,7 +20,7 @@ export function UploadFormMenu(props: Props) { const datasetUploadType = datasetUploadTypes[type]; return ( datasetUploadType && ( -
  • +
  • {' '} diff --git a/packages/libs/user-datasets/src/lib/Components/UserDatasetsWorkspace.tsx b/packages/libs/user-datasets/src/lib/Components/UserDatasetsWorkspace.tsx index ec6f8a1ab8..4484523ff9 100644 --- a/packages/libs/user-datasets/src/lib/Components/UserDatasetsWorkspace.tsx +++ b/packages/libs/user-datasets/src/lib/Components/UserDatasetsWorkspace.tsx @@ -1,6 +1,11 @@ -import { ReactNode } from 'react'; +import { ReactNode, useEffect, useState } from 'react'; -import { Switch, Redirect, RouteComponentProps } from 'react-router-dom'; +import { + Switch, + Redirect, + RouteComponentProps, + useRouteMatch, +} from 'react-router-dom'; import WorkspaceNavigation from '@veupathdb/wdk-client/lib/Components/Workspace/WorkspaceNavigation'; import WdkRoute from '@veupathdb/wdk-client/lib/Core/WdkRoute'; @@ -19,6 +24,8 @@ interface Props { helpTabContents?: ReactNode; dataNoun: DataNoun; enablePublicUserDatasets: boolean; + activeUploadType?: string; + setActiveUploadType?: (newType?: string) => void; } function UserDatasetsWorkspace(props: Props) { @@ -30,8 +37,21 @@ function UserDatasetsWorkspace(props: Props) { helpTabContents, dataNoun, enablePublicUserDatasets, + activeUploadType, + setActiveUploadType, } = props; + const { + path, + params: { type: currentUploadType }, + } = useRouteMatch<{ type?: string }>(); + + useEffect(() => { + if (setActiveUploadType && path.match('/new/')) { + setActiveUploadType(currentUploadType); + } + }, [currentUploadType, path, setActiveUploadType]); + return (
    ; } + return ( - + <> + + Back to choose an upload type + + + ); } @@ -157,6 +165,7 @@ function InnerUserDatasetUploadController({ ) : (
    ({ [availableUploadTypes, uploadTypeConfig] ); + const [activeUploadType, setActiveUploadType] = useState(); + return ( ({ helpTabContents={helpTabContents} dataNoun={dataNoun} enablePublicUserDatasets={enablePublicUserDatasets} + activeUploadType={activeUploadType} + setActiveUploadType={setActiveUploadType} /> ); }} @@ -102,6 +105,8 @@ export function UserDatasetRouter({ helpTabContents={helpTabContents} dataNoun={dataNoun} enablePublicUserDatasets={enablePublicUserDatasets} + activeUploadType={activeUploadType} + setActiveUploadType={setActiveUploadType} /> ); }} @@ -159,6 +164,8 @@ export function UserDatasetRouter({ helpTabContents={helpTabContents} dataNoun={dataNoun} enablePublicUserDatasets={enablePublicUserDatasets} + activeUploadType={activeUploadType} + setActiveUploadType={setActiveUploadType} /> ); }} diff --git a/packages/libs/user-datasets/src/lib/Utils/types.ts b/packages/libs/user-datasets/src/lib/Utils/types.ts index bafd219f1e..8a7256a7cd 100644 --- a/packages/libs/user-datasets/src/lib/Utils/types.ts +++ b/packages/libs/user-datasets/src/lib/Utils/types.ts @@ -109,6 +109,7 @@ export interface DatasetUploadTypeConfigEntry { render: (props: DependencyProps) => ReactNode; required?: boolean; }; + hideRelatedOrganisms?: boolean; uploadMethodConfig: { file?: FileUploadConfig; url?: UrlUploadConfig; diff --git a/packages/libs/web-common/src/user-dataset-upload-config.tsx b/packages/libs/web-common/src/user-dataset-upload-config.tsx index eb5ae751fe..40d1352de9 100644 --- a/packages/libs/web-common/src/user-dataset-upload-config.tsx +++ b/packages/libs/web-common/src/user-dataset-upload-config.tsx @@ -175,6 +175,7 @@ export const uploadTypeConfig: DatasetUploadTypeConfig = 'optional longer description of the summary including background, study objectives, methodology, etc.', }, }, + hideRelatedOrganisms: true, renderInfo: () => (

    We accept any file in the{' '} @@ -301,6 +302,7 @@ export const uploadTypeConfig: DatasetUploadTypeConfig = 'optional longer description of the study including background, study objectives, methodology, etc.', }, }, + hideRelatedOrganisms: true, uploadMethodConfig: { file: { render: ({ fieldNode }) => (