From 5e04a7680bbb5bff1558b97c725d089bae0309d0 Mon Sep 17 00:00:00 2001 From: Bob Date: Fri, 1 Nov 2024 17:49:07 +0000 Subject: [PATCH 01/13] new warning added, no new component, sorry --- .../js/client/records/Sequences.tsx | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx index b584b3a12a..e5f70fc189 100644 --- a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx +++ b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx @@ -622,6 +622,22 @@ export function RecordTable_Sequences( if (filteredRows == null) return null; + const warningText = + filteredRows.length > MAX_SEQUENCES_FOR_TREE || + filteredRows.length < MIN_SEQUENCES_FOR_TREE ? ( + + To see a phylogenetic tree please use a filter to display between{' '} + {MIN_SEQUENCES_FOR_TREE.toLocaleString()} and{' '} + {MAX_SEQUENCES_FOR_TREE.toLocaleString()} sequences + + ) : filteredRows.length < sortedRows.length ? ( + + Note: The ortholog group's phylogeny has been pruned to display only the + currently filtered proteins. This may differ from a tree constructed{' '} + de novo using only these sequences. + + ) : undefined; + return (
- {(filteredRows.length > MAX_SEQUENCES_FOR_TREE || - filteredRows.length < MIN_SEQUENCES_FOR_TREE) && ( + {warningText && (
- To see a phylogenetic tree please use a filter to display between{' '} - {MIN_SEQUENCES_FOR_TREE.toLocaleString()} and{' '} - {MAX_SEQUENCES_FOR_TREE.toLocaleString()} sequences + {warningText}
)}
Date: Fri, 1 Nov 2024 18:04:33 +0000 Subject: [PATCH 02/13] improved tree error warning with link to contact form --- .../js/client/records/Sequences.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx index e5f70fc189..256d17f9a7 100644 --- a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx +++ b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx @@ -9,7 +9,7 @@ import React, { import TreeTable from '@veupathdb/components/lib/components/tidytree/TreeTable'; import { RecordTableProps, WrappedComponentProps } from './Types'; import { useOrthoService } from 'ortho-client/hooks/orthoService'; -import { Loading } from '@veupathdb/wdk-client/lib/Components'; +import { Loading, Link } from '@veupathdb/wdk-client/lib/Components'; import { Branch, parseNewick } from 'patristic'; import { AttributeValue, @@ -404,7 +404,8 @@ export function RecordTable_Sequences( if ( mesaRows != null && sortedRows != null && - mesaRows.length !== sortedRows.length + (mesaRows.length !== sortedRows.length || + mesaRows.length !== leaves?.length) ) { console.log( 'Tree and protein list mismatch. A=Tree, B=Table. Summary below:' @@ -419,8 +420,13 @@ export function RecordTable_Sequences( + A data processing error has occurred on our end. We apologize for + the inconvenience. If this problem persists, please{' '} + contact us. + + ), }} /> ); From 564f4538378a159338def9798de80dcf85b25cf6 Mon Sep 17 00:00:00 2001 From: Bob Date: Fri, 1 Nov 2024 18:24:18 +0000 Subject: [PATCH 03/13] use display names in SelectList button labels --- .../src/components/inputs/SelectList.tsx | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/packages/libs/coreui/src/components/inputs/SelectList.tsx b/packages/libs/coreui/src/components/inputs/SelectList.tsx index ce495361d3..767e39fb13 100644 --- a/packages/libs/coreui/src/components/inputs/SelectList.tsx +++ b/packages/libs/coreui/src/components/inputs/SelectList.tsx @@ -1,6 +1,9 @@ import { ReactNode, useCallback, useEffect, useState } from 'react'; import PopoverButton from '../buttons/PopoverButton/PopoverButton'; -import CheckboxList, { CheckboxListProps } from './checkboxes/CheckboxList'; +import CheckboxList, { + CheckboxListProps, + Item, +} from './checkboxes/CheckboxList'; export interface SelectListProps extends CheckboxListProps { children?: ReactNode; @@ -30,13 +33,13 @@ export default function SelectList({ }: SelectListProps) { const [selected, setSelected] = useState['value']>(value); const [buttonDisplayContent, setButtonDisplayContent] = useState( - value.length ? value.join(', ') : defaultButtonDisplayContent + getDisplayContent(value, items, defaultButtonDisplayContent) ); const onClose = () => { onChange(selected); setButtonDisplayContent( - selected.length ? selected.join(', ') : defaultButtonDisplayContent + getDisplayContent(selected, items, defaultButtonDisplayContent) ); }; @@ -61,9 +64,9 @@ export default function SelectList({ setSelected(value); if (instantUpdate) return; // we don't want the button text changing on every click setButtonDisplayContent( - value.length ? value.join(', ') : defaultButtonDisplayContent + getDisplayContent(value, items, defaultButtonDisplayContent) ); - }, [value, defaultButtonDisplayContent]); + }, [value, items, defaultButtonDisplayContent]); const buttonLabel = ( ({ ); } + +// Returns button display content based on `value` array, mapping to display names from `items` when available. +// If no matching display name is found, uses the value itself. Returns `defaultContent` if `value` is empty. +function getDisplayContent( + value: T[], + items: Item[], + defaultContent: ReactNode +): ReactNode { + return value.length + ? value + .map((v) => items.find((item) => item.value === v)?.display ?? v) + .join(', ') + : defaultContent; +} From 6907790881a4659559f063ddf3fee2c22de9507b Mon Sep 17 00:00:00 2001 From: Bob Date: Fri, 1 Nov 2024 19:30:14 +0000 Subject: [PATCH 04/13] standardised search behaviour with help text --- .../js/client/records/Sequences.tsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx index 256d17f9a7..b69db3f12a 100644 --- a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx +++ b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx @@ -39,6 +39,10 @@ import { import { RecordTable_TaxonCounts_Filter } from './RecordTable_TaxonCounts_Filter'; import { formatAttributeValue } from '@veupathdb/wdk-client/lib/Utils/ComponentUtils'; import { RecordFilter } from '@veupathdb/wdk-client/lib/Views/Records/RecordTable/RecordFilter'; +import { + areTermsInStringRegexString, + parseSearchQueryString, +} from '../../../../../../../libs/wdk-client/lib/Utils/SearchUtils'; type RowType = Record; @@ -800,14 +804,9 @@ function rowMatch(row: RowType, query: RegExp, keys?: string[]): boolean { function createSafeSearchRegExp(input: string): RegExp | undefined { if (input === '') return undefined; - try { - // Attempt to create a RegExp from the user input directly - return new RegExp(input, 'i'); - } catch (error) { - // If an error occurs (e.g., invalid RegExp), escape the input and create a literal search RegExp - const escapedInput = input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - return new RegExp(escapedInput, 'i'); - } + const queryTerms = parseSearchQueryString(input); + const searchTermRegex = areTermsInStringRegexString(queryTerms); + return new RegExp(searchTermRegex, 'i'); } function logIdMismatches(A: string[], B: string[]) { From 25def369c14acebfdb2a08774a433554cd895f1c Mon Sep 17 00:00:00 2001 From: Bob Date: Fri, 1 Nov 2024 22:36:03 +0000 Subject: [PATCH 05/13] protein filter and paged table interaction fixed --- .../webapp/wdkCustomization/js/client/records/Sequences.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx index b69db3f12a..1d2e9f43ea 100644 --- a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx +++ b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx @@ -524,6 +524,7 @@ export function RecordTable_Sequences( onPress={() => { proteinFilterButtonRef.current?.close(); setProteinFilterIds([]); + setTablePageNumber(1); }} /> ); @@ -532,6 +533,7 @@ export function RecordTable_Sequences( proteinFilterButtonRef.current?.close(); setProteinFilterIds(highlightedNodes); setHighlightedNodes([]); + setTablePageNumber(1); }; const proteinFilter = ( From 075fff3694608df1ae6916955e051a2854fb0157 Mon Sep 17 00:00:00 2001 From: Bob MacCallum Date: Sat, 2 Nov 2024 11:29:54 +0000 Subject: [PATCH 06/13] fixed label display issue in EDA --- .../libs/coreui/src/components/inputs/SelectList.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/libs/coreui/src/components/inputs/SelectList.tsx b/packages/libs/coreui/src/components/inputs/SelectList.tsx index 767e39fb13..e4038e0856 100644 --- a/packages/libs/coreui/src/components/inputs/SelectList.tsx +++ b/packages/libs/coreui/src/components/inputs/SelectList.tsx @@ -18,7 +18,7 @@ export interface SelectListProps extends CheckboxListProps { instantUpdate?: boolean; } -export default function SelectList({ +export default function SelectList({ name, items, value, @@ -109,14 +109,16 @@ export default function SelectList({ // Returns button display content based on `value` array, mapping to display names from `items` when available. // If no matching display name is found, uses the value itself. Returns `defaultContent` if `value` is empty. -function getDisplayContent( +function getDisplayContent( value: T[], items: Item[], defaultContent: ReactNode ): ReactNode { return value.length ? value - .map((v) => items.find((item) => item.value === v)?.display ?? v) - .join(', ') + .map( + (v) => items.find((item) => item.value === v)?.display ?? v + ) + .reduce((accum, elem) => (accum ? [accum, ',', elem] : elem), null) : defaultContent; } From 997837d67b9bf431f2c27b821c621cf57a034969 Mon Sep 17 00:00:00 2001 From: Bob Date: Tue, 5 Nov 2024 21:14:53 +0000 Subject: [PATCH 07/13] target _blank --- .../webapp/wdkCustomization/js/client/records/Sequences.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx index 1d2e9f43ea..231e2fed52 100644 --- a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx +++ b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx @@ -428,7 +428,10 @@ export function RecordTable_Sequences( A data processing error has occurred on our end. We apologize for the inconvenience. If this problem persists, please{' '} - contact us. + + contact us + + . ), }} From 2e761208b68fbd290b62a9cc05ae670576e4d280 Mon Sep 17 00:00:00 2001 From: Bob Date: Tue, 5 Nov 2024 21:40:57 +0000 Subject: [PATCH 08/13] fix import path --- .../webapp/wdkCustomization/js/client/records/Sequences.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx index 231e2fed52..a67a698269 100644 --- a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx +++ b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx @@ -42,7 +42,7 @@ import { RecordFilter } from '@veupathdb/wdk-client/lib/Views/Records/RecordTabl import { areTermsInStringRegexString, parseSearchQueryString, -} from '../../../../../../../libs/wdk-client/lib/Utils/SearchUtils'; +} from '@veupathdb/wdk-client/lib/Utils/SearchUtils'; type RowType = Record; From 6b8f7f432b3fb5d1d07b041593a1d33a8d741009 Mon Sep 17 00:00:00 2001 From: Bob Date: Tue, 5 Nov 2024 22:52:40 +0000 Subject: [PATCH 09/13] show table for 1 or 2 protein groups, not the error. Changes to CheckboxList/SelectList generics 1 of 2 --- .../components/inputs/checkboxes/CheckboxList.tsx | 4 ++-- .../js/client/records/Sequences.tsx | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/libs/coreui/src/components/inputs/checkboxes/CheckboxList.tsx b/packages/libs/coreui/src/components/inputs/checkboxes/CheckboxList.tsx index a945e10340..218dae85ee 100644 --- a/packages/libs/coreui/src/components/inputs/checkboxes/CheckboxList.tsx +++ b/packages/libs/coreui/src/components/inputs/checkboxes/CheckboxList.tsx @@ -76,7 +76,7 @@ export type Item = { disabled?: boolean; }; -export type CheckboxListProps = { +export type CheckboxListProps = { /** Optional name attribute for the native input element */ name?: string; @@ -99,7 +99,7 @@ export type CheckboxListProps = { disabledCheckboxTooltipContent?: ReactNode; }; -export default function CheckboxList({ +export default function CheckboxList({ name, items, value, diff --git a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx index a67a698269..b2cea2d6a7 100644 --- a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx +++ b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx @@ -98,7 +98,10 @@ export function RecordTable_Sequences( const numSequences = mesaRows.length; const treeResponse = useOrthoService( - (orthoService) => orthoService.getGroupTree(groupName), + (orthoService) => { + if (numSequences < 3) return Promise.resolve(undefined); + return orthoService.getGroupTree(groupName); + }, [groupName, numSequences] ); @@ -195,7 +198,7 @@ export function RecordTable_Sequences( const { tree, leaves, sortedRows } = useMemo(() => { const tree = treeResponse == null ? undefined : parseNewick(treeResponse); const leaves = tree && getLeaves(tree); - const sortedRows = leaves && sortRows(leaves, mesaRows); + const sortedRows = leaves ? sortRows(leaves, mesaRows) : mesaRows; return { tree, leaves, sortedRows }; }, [treeResponse, mesaRows]); @@ -406,6 +409,7 @@ export function RecordTable_Sequences( } if ( + numSequences >= 3 && mesaRows != null && sortedRows != null && (mesaRows.length !== sortedRows.length || @@ -638,8 +642,9 @@ export function RecordTable_Sequences( if (filteredRows == null) return null; const warningText = - filteredRows.length > MAX_SEQUENCES_FOR_TREE || - filteredRows.length < MIN_SEQUENCES_FOR_TREE ? ( + numSequences >= 3 && + (filteredRows.length > MAX_SEQUENCES_FOR_TREE || + filteredRows.length < MIN_SEQUENCES_FOR_TREE) ? ( To see a phylogenetic tree please use a filter to display between{' '} {MIN_SEQUENCES_FOR_TREE.toLocaleString()} and{' '} From 5deced2d48160a5cbc89280a27a73e425cfd2ea8 Mon Sep 17 00:00:00 2001 From: Bob Date: Tue, 5 Nov 2024 22:55:12 +0000 Subject: [PATCH 10/13] changes to CheckboxList/SelectList generics 2 of 2 --- packages/libs/coreui/src/components/inputs/SelectList.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/libs/coreui/src/components/inputs/SelectList.tsx b/packages/libs/coreui/src/components/inputs/SelectList.tsx index e4038e0856..8c3fd0a1ff 100644 --- a/packages/libs/coreui/src/components/inputs/SelectList.tsx +++ b/packages/libs/coreui/src/components/inputs/SelectList.tsx @@ -5,7 +5,8 @@ import CheckboxList, { Item, } from './checkboxes/CheckboxList'; -export interface SelectListProps extends CheckboxListProps { +export interface SelectListProps + extends CheckboxListProps { children?: ReactNode; /** A button's content if/when no values are currently selected */ defaultButtonDisplayContent: ReactNode; @@ -18,7 +19,7 @@ export interface SelectListProps extends CheckboxListProps { instantUpdate?: boolean; } -export default function SelectList({ +export default function SelectList({ name, items, value, @@ -109,7 +110,7 @@ export default function SelectList({ // Returns button display content based on `value` array, mapping to display names from `items` when available. // If no matching display name is found, uses the value itself. Returns `defaultContent` if `value` is empty. -function getDisplayContent( +function getDisplayContent( value: T[], items: Item[], defaultContent: ReactNode From 4557b844db80df1360e845bda9160014e9ca3535 Mon Sep 17 00:00:00 2001 From: Bob Date: Tue, 5 Nov 2024 23:08:45 +0000 Subject: [PATCH 11/13] reset button also cancels text search --- .../webapp/wdkCustomization/js/client/records/Sequences.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx index b2cea2d6a7..6fdd3d4e1b 100644 --- a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx +++ b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx @@ -623,12 +623,13 @@ export function RecordTable_Sequences( corePeripheralFilterValue.length + selectedSpecies.length + proteinFilterIds.length === - 0 + 0 && searchQuery === '' } icon={Undo} size={'medium'} themeRole={'primary'} onPress={() => { + setSearchQuery(''); setProteinFilterIds([]); setPfamFilterIds([]); setCorePeripheralFilterValue([]); @@ -695,6 +696,7 @@ export function RecordTable_Sequences( }} > Date: Tue, 5 Nov 2024 23:13:35 +0000 Subject: [PATCH 12/13] error banner was showing instead of loading spinner for large groups, now it isn't --- .../wdkCustomization/js/client/records/Sequences.tsx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx index 6fdd3d4e1b..ee7ee126af 100644 --- a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx +++ b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx @@ -398,13 +398,7 @@ export function RecordTable_Sequences( // None shall pass! (hooks, at least) - if ( - !mesaState || - !sortedRows || - (numSequences >= MIN_SEQUENCES_FOR_TREE && - numSequences <= MAX_SEQUENCES_FOR_TREE && - (tree == null || treeResponse == null)) - ) { + if (!mesaState || !sortedRows || !tree || !treeResponse) { return ; } From 7ef7b0ec7714dcab0cd3c0918ad81f20c01de499 Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 6 Nov 2024 15:34:12 +0000 Subject: [PATCH 13/13] use const for min seqs in tree --- .../wdkCustomization/js/client/records/Sequences.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx index ee7ee126af..1efea4f282 100644 --- a/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx +++ b/packages/sites/ortho-site/webapp/wdkCustomization/js/client/records/Sequences.tsx @@ -99,7 +99,8 @@ export function RecordTable_Sequences( const treeResponse = useOrthoService( (orthoService) => { - if (numSequences < 3) return Promise.resolve(undefined); + if (numSequences < MIN_SEQUENCES_FOR_TREE) + return Promise.resolve(undefined); return orthoService.getGroupTree(groupName); }, [groupName, numSequences] @@ -403,7 +404,7 @@ export function RecordTable_Sequences( } if ( - numSequences >= 3 && + numSequences >= MIN_SEQUENCES_FOR_TREE && mesaRows != null && sortedRows != null && (mesaRows.length !== sortedRows.length || @@ -637,7 +638,7 @@ export function RecordTable_Sequences( if (filteredRows == null) return null; const warningText = - numSequences >= 3 && + numSequences >= MIN_SEQUENCES_FOR_TREE && (filteredRows.length > MAX_SEQUENCES_FOR_TREE || filteredRows.length < MIN_SEQUENCES_FOR_TREE) ? (