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

Some suggestions for the Search help feature #2234

Merged
merged 6 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
190 changes: 112 additions & 78 deletions website/src/components/SearchPage/DisplaySearchDocs.tsx
Original file line number Diff line number Diff line change
@@ -1,92 +1,126 @@
import { type FC, useRef } from 'react';
import { Dialog, Transition, DialogPanel, DialogTitle } from '@headlessui/react';
import React, { Fragment } from 'react';

const DisplaySearchDocs: FC = () => {
const dialogRef = useRef<HTMLDialogElement>(null);
import X from '~icons/material-symbols/close';
import MaterialSymbolsHelpOutline from '~icons/material-symbols/help-outline';

const openDialog = () => {
if (dialogRef.current) {
dialogRef.current.showModal();
}
};
const DisplaySearchDocs: React.FC = () => {
const [isOpen, setIsOpen] = React.useState(false);

const closeDialog = () => {
if (dialogRef.current) {
dialogRef.current.close();
}
};
const openDialog = () => setIsOpen(true);
const closeDialog = () => setIsOpen(false);

return (
<>
<button className='outlineButton' onClick={openDialog}>
?
<button onClick={openDialog} className='text-gray-400 hover:text-primary-600 '>
<MaterialSymbolsHelpOutline className='inline-block h-6 w-5' />
</button>
<dialog ref={dialogRef} className='modal'>
<button
className='btn btn-sm btn-circle btn-ghost text-gray-900 absolute right-2 top-2'
onClick={closeDialog}
>
</button>
<div className='modal-box max-w-5xl'>
<form method='dialog'>
<button className='btn btn-sm btn-circle btn-ghost absolute right-2 top-2'>✕</button>
</form>
<h3 className='font-bold text-2xl mb-4 text-primary-700'>Mutation Search</h3>
<div className='mb-4'>
<h4 className='font-bold text-l mb-4'>Nucleotide Mutations and Insertions</h4>
<p>
A nucleotide mutation has the format <b>&lt;position&gt;&lt;base&gt;</b> or
<b>&lt;base_ref&gt;&lt;position&gt;&lt;base&gt;. A &lt;base&gt;</b> can be one of the four
nucleotides <b>A</b>, <b>T</b>, <b>C</b>, and <b>G</b>. It can also be <b>-</b> for deletion
and <b>N</b> for unknown. For example if the reference sequence is <b>A</b> at position{' '}
<b>23</b> both: <b>23T</b> and <b>A23T</b> will yield the same results.
</p>
<p>
If your organism is multi-segmented you must append the name of the segment to the start of
the mutation, e.g. <b>S:23T</b> and <b>S:A23T</b> for a mutation in segment <b>S</b>.
</p>
<p>
Insertions can be searched for in the same manner, they just need to have <b>ins_</b>{' '}
appended to the start of the mutation. Example <b>ins_10462:A</b> or if the organism is
multi-segmented <b>ins_S:10462:A</b>.
</p>
</div>
<Transition appear show={isOpen} as={Fragment}>
<Dialog as='div' className='relative z-10' onClose={closeDialog}>
<Transition.Child
as={Fragment}
enter='ease-out duration-300'
enterFrom='opacity-0'
enterTo='opacity-100'
leave='ease-in duration-200'
leaveFrom='opacity-100'
leaveTo='opacity-0'
>
<div className='fixed inset-0 bg-black bg-opacity-25' />
</Transition.Child>

<div className='mb-4'>
<h4 className='font-bold text-l mb-4'>Amino Acid Mutations and Insertions</h4>
<p>
An amino acid mutation has the format <b>&lt;gene&gt;:&lt;position&gt;&lt;base&gt;</b> or
<b>&lt;gene&gt;:&lt;base_ref&gt;&lt;position&gt;&lt;base&gt;</b>. A <b>&lt;base&gt;</b> can
be one of the 20 amino acid codes. It can also be <b>-</b> for deletion and <b>X</b> for
unknown. Example: <b>E:57Q</b>.
</p>
<p>
Insertions can be searched for in the same manner, they just need to have <b>ins_ </b>
appended to the start of the mutation. Example <b>ins_NS4B:31:N</b>.
</p>
<div className='fixed inset-0 overflow-y-auto'>
<div className='flex min-h-full items-center justify-center p-4 text-center'>
<Transition.Child
as={Fragment}
enter='ease-out duration-300'
enterFrom='opacity-0 scale-95'
enterTo='opacity-100 scale-100'
leave='ease-in duration-200'
leaveFrom='opacity-100 scale-100'
leaveTo='opacity-0 scale-95'
>
<DialogPanel className='w-full max-w-5xl transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all'>
<DialogTitle as='h3' className='font-bold text-2xl mb-4 text-primary-700'>
Mutation Search
</DialogTitle>
<button className='absolute right-2 top-2 p-1' onClick={closeDialog}>
<X className='h-6 w-6' />
</button>
<div className='mt-2'>
<div className='mb-4'>
<h4 className='font-bold text-l mb-4'>
Nucleotide Mutations and Insertions
</h4>
<p>
A nucleotide mutation has the format <b>&lt;position&gt;&lt;base&gt;</b>{' '}
or
<b>&lt;base_ref&gt;&lt;position&gt;&lt;base&gt;. A &lt;base&gt;</b> can
be one of the four nucleotides <b>A</b>, <b>T</b>, <b>C</b>, and{' '}
<b>G</b>. It can also be <b>-</b> for deletion and <b>N</b> for unknown.
For example if the reference sequence is <b>A</b> at position <b>23</b>{' '}
both: <b>23T</b> and <b>A23T</b> will yield the same results.
</p>
<p>
If your organism is multi-segmented you must append the name of the
segment to the start of the mutation, e.g. <b>S:23T</b> and{' '}
<b>S:A23T</b> for a mutation in segment <b>S</b>.
</p>
<p>
Insertions can be searched for in the same manner, they just need to
have <b>ins_</b> appended to the start of the mutation. Example{' '}
<b>ins_10462:A</b> or if the organism is multi-segmented{' '}
<b>ins_S:10462:A</b>.
</p>
</div>

<p>
Multiple mutation filters can be provided in a single request. They can either be added one
after another or all at once in a comma separated list. Example: <b>123T,E:57Q</b>.
</p>
</div>
<div className='mb-4'>
<h4 className='font-bold text-l mb-4'>
Amino Acid Mutations and Insertions
</h4>
<p>
An amino acid mutation has the format{' '}
<b>&lt;gene&gt;:&lt;position&gt;&lt;base&gt;</b> or
<b>&lt;gene&gt;:&lt;base_ref&gt;&lt;position&gt;&lt;base&gt;</b>. A{' '}
<b>&lt;base&gt;</b> can be one of the 20 amino acid codes. It can also
be <b>-</b> for deletion and <b>X</b> for unknown. Example: <b>E:57Q</b>
.
</p>
<p>
Insertions can be searched for in the same manner, they just need to
have <b>ins_ </b>
appended to the start of the mutation. Example <b>ins_NS4B:31:N</b>.
</p>

<div className='mb-4'>
<h4 className='font-bold text-l mb-4'>Any Mutation</h4>
<p>
To filter for any mutation at a given position you can omit the <b>&lt;base&gt;</b>.
</p>
</div>
<div className='mb-4'>
<h4 className='font-bold text-l mb-4'>No Mutation</h4>
<p>
You can write a <b>.</b> for the <b>&lt;base&gt;</b> to filter for sequences for which it is
confirmed that no mutation occurred, i.e. has the same base as the reference genome at the
specified position.
</p>
<p>
Multiple mutation filters can be provided in a single request. They can
either be added one after another or all at once in a comma separated
list. Example: <b>123T,E:57Q</b>.
</p>
</div>

<div className='mb-4'>
<h4 className='font-bold text-l mb-4'>Any Mutation</h4>
<p>
To filter for any mutation at a given position you can omit the{' '}
<b>&lt;base&gt;</b>.
</p>
</div>
<div className='mb-4'>
<h4 className='font-bold text-l mb-4'>No Mutation</h4>
<p>
You can write a <b>.</b> for the <b>&lt;base&gt;</b> to filter for
sequences for which it is confirmed that no mutation occurred, i.e. has
the same base as the reference genome at the specified position.
</p>
</div>
</div>
</DialogPanel>
</Transition.Child>
</div>
</div>
</div>
</dialog>
</Dialog>
</Transition>
</>
);
};
Expand Down
22 changes: 13 additions & 9 deletions website/src/components/SearchPage/SearchForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import type { GroupedMetadataFilter, MetadataFilter, FieldValues, SetAFieldValue
import { type ReferenceGenomesSequenceNames } from '../../types/referencesGenomes.ts';
import type { ClientConfig } from '../../types/runtimeConfig.ts';
import { OffCanvasOverlay } from '../OffCanvasOverlay.tsx';
import MaterialSymbolsHelpOutline from '~icons/material-symbols/help-outline';
import MaterialSymbolsResetFocus from '~icons/material-symbols/reset-focus';
import StreamlineWrench from '~icons/streamline/wrench';

const queryClient = new QueryClient();

interface SearchFormProps {
Expand Down Expand Up @@ -60,23 +64,23 @@ export const SearchForm = ({
>
<div className='shadow-xl rounded-r-lg px-4 pt-4'>
<h2 className='text-lg font-semibold flex-1 md:hidden mb-2'>Search query</h2>
<a href='/docs/how-to/search_sequences_website' className='text-primary-700 underline mb-2'>
How to Search
</a>
<div className='flex'>
<div className='flex items-center justify-between w-full mb-2 text-primary-700'>
<div className='flex items-center justify-between w-full mb-2 text-primary-700'>
<button className='underline' onClick={toggleCustomizeModal}>
Customize fields
<div className='flex items-center justify-between w-full mb-1 text-primary-700'>
<div className='flex items-center justify-between w-full mb-1 text-primary-700 text-sm'>
<button className='hover:underline' onClick={toggleCustomizeModal}>
<StreamlineWrench className='inline-block' /> Select fields
</button>
<button
className='underline'
className='hover:underline'
onClick={() => {
window.location.href = './';
}}
>
Reset
<MaterialSymbolsResetFocus className='inline-block' /> Reset
</button>
<a href='/docs/how-to/search_sequences_website' target='_blank'>
<MaterialSymbolsHelpOutline className='inline-block' /> Help
</a>
</div>
</div>{' '}
</div>
Expand Down
28 changes: 17 additions & 11 deletions website/src/components/SearchPage/fields/MutationField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,19 +227,26 @@ export const MutationField: FC<MutationFieldProps> = ({ referenceGenomesSequence
>
Mutations
</label>
<ComboboxInput
onFocus={() => setHasFocus(true)}
onBlur={() => setHasFocus(false)}
placeholder={hasFocus ? '' : selectedOptions.length === 0 ? 'Mutations' : 'Enter mutation'}
onChange={handleInputChange}
displayValue={(option: MutationQuery) => option.text}
value={inputValue}
id='mutField'
className={`
<div className='justify-between w-full'>
<ComboboxInput
onFocus={() => setHasFocus(true)}
onBlur={() => setHasFocus(false)}
placeholder={
hasFocus ? '' : selectedOptions.length === 0 ? 'Mutations' : 'Enter mutation'
}
onChange={handleInputChange}
displayValue={(option: MutationQuery) => option.text}
value={inputValue}
id='mutField'
className={`
block w-full text-sm text-gray-900 bg-transparent focus:outline-none focus:ring-0
${selectedOptions.length === 0 ? 'border-0 focus:border-0 py-3' : 'border border-gray-300 border-solid m-2 text-sm ml-0'}
`}
/>
/>
<div className='absolute bottom-3 right-1'>
<DisplaySearchDocs />
</div>
</div>
</div>
<Transition
as={Fragment}
Expand Down Expand Up @@ -267,7 +274,6 @@ export const MutationField: FC<MutationFieldProps> = ({ referenceGenomesSequence
</Transition>
</div>
</Combobox>
<DisplaySearchDocs></DisplaySearchDocs>
</div>
);
};
Loading