1414 * limitations under the License.
1515 */
1616
17- import React , { useEffect } from 'react' ;
17+ import React , { useEffect , useState , useRef } from 'react' ;
1818import classNames from 'classnames' ;
19+ import { useNavigate } from 'react-router-dom' ;
1920
2021import { useAppSelector , useAppDispatch } from 'src/store' ;
2122
23+ import * as urlFor from 'src/shared/helpers/urlHelper' ;
2224import { getDisplayName } from 'src/shared/components/selected-species/selectedSpeciesHelpers' ;
25+
26+ import useSpeciesAnalytics from 'src/content/app/species/hooks/useSpeciesAnalytics' ;
27+ import useResizeObserver from 'src/shared/hooks/useResizeObserver' ;
28+
29+ import { SecondaryButton } from 'src/shared/components/button/Button' ;
30+ import DeletionConfirmation from 'src/shared/components/deletion-confirmation/DeletionConfirmation' ;
31+
2332import SearchIcon from 'static/icons/icon_search.svg' ;
2433
25- import { isSpeciesSidebarOpen as getSidebarStatus } from 'src/content/app/species/state/sidebar/speciesSidebarSelectors' ;
2634import { getCommittedSpeciesById } from 'src/content/app/species-selector/state/speciesSelectorSelectors' ;
2735import { getActiveGenomeId } from 'src/content/app/species/state/general/speciesGeneralSelectors' ;
2836import { getPopularSpecies } from 'src/content/app/species-selector/state/speciesSelectorSelectors' ;
37+
2938import {
3039 SpeciesSidebarModalView ,
3140 updateSpeciesSidebarModalForGenome
3241} from 'src/content/app/species/state/sidebar/speciesSidebarSlice' ;
33-
34- import { fetchPopularSpecies } from 'src/content/app/species-selector/state/speciesSelectorSlice' ;
42+ import {
43+ fetchPopularSpecies ,
44+ deleteSpeciesAndSave
45+ } from 'src/content/app/species-selector/state/speciesSelectorSlice' ;
3546
3647import SpeciesUsageToggle from './species-usage-toggle/SpeciesUsageToggle' ;
37- import SpeciesRemove from './species-remove/SpeciesRemove' ;
3848
3949import { RootState } from 'src/store' ;
4050
4151import styles from './SpeciesTitleArea.scss' ;
4252
53+ const MEDIUM_WIDTH = 720 ;
54+ const SMALL_WIDTH = 560 ;
55+
56+ enum Display {
57+ FULL = 'full' ,
58+ COMPACT = 'compact' ,
59+ MINIMAL = 'minimal'
60+ }
61+
4362const useSpecies = ( ) => {
4463 const activeGenomeId = useAppSelector ( getActiveGenomeId ) ;
4564 const popularSpecies = useAppSelector ( getPopularSpecies ) ;
@@ -68,12 +87,31 @@ const useSpecies = () => {
6887
6988const SpeciesTitleArea = ( ) => {
7089 const activeGenomeId = useAppSelector ( getActiveGenomeId ) ;
71- const isSidebarOpen = useAppSelector ( getSidebarStatus ) ;
7290 const dispatch = useAppDispatch ( ) ;
91+ const navigate = useNavigate ( ) ;
7392 const { species, iconUrl } = useSpecies ( ) || { } ;
93+ const [ isRemoving , setIsRemoving ] = useState ( false ) ;
94+ const [ display , setDisplay ] = useState ( Display . FULL ) ;
95+ const { trackDeletedSpecies } = useSpeciesAnalytics ( ) ;
96+
97+ const containerRef = useRef < HTMLDivElement > ( null ) ;
98+ const { width : containerWidth } = useResizeObserver ( { ref : containerRef } ) ;
99+
100+ // TODO:
101+ // Remove the useEffect below when all of our target browsers support CSS container queries
102+ useEffect ( ( ) => {
103+ if ( containerWidth < SMALL_WIDTH ) {
104+ display !== Display . MINIMAL && setDisplay ( Display . MINIMAL ) ;
105+ } else if ( containerWidth < MEDIUM_WIDTH ) {
106+ display !== Display . COMPACT && setDisplay ( Display . COMPACT ) ;
107+ } else {
108+ display !== Display . FULL && setDisplay ( Display . FULL ) ;
109+ }
110+ } , [ containerWidth ] ) ;
74111
75112 const blockClasses = classNames ( styles . speciesTitleArea , {
76- [ styles . speciesTitleAreaNarrow ] : isSidebarOpen
113+ [ styles . speciesTitleAreaMinimal ] : display === Display . MINIMAL ,
114+ [ styles . speciesTitleAreaCompact ] : display === Display . COMPACT
77115 } ) ;
78116
79117 if ( ! activeGenomeId ) {
@@ -89,8 +127,18 @@ const SpeciesTitleArea = () => {
89127 ) ;
90128 } ;
91129
130+ const toggleRemovalDialog = ( ) => {
131+ setIsRemoving ( ! isRemoving ) ;
132+ } ;
133+
134+ const onRemove = ( ) => {
135+ dispatch ( deleteSpeciesAndSave ( activeGenomeId ) ) ;
136+ species && trackDeletedSpecies ( species ) ;
137+ navigate ( urlFor . speciesSelector ( ) ) ;
138+ } ;
139+
92140 return species && iconUrl ? (
93- < div className = { blockClasses } >
141+ < div className = { blockClasses } ref = { containerRef } >
94142 < div className = { styles . speciesIcon } >
95143 < img src = { iconUrl } />
96144 </ div >
@@ -106,8 +154,24 @@ const SpeciesTitleArea = () => {
106154 < SearchIcon />
107155 </ div >
108156 < div className = { styles . speciesRemove } >
109- < SpeciesRemove />
157+ < SecondaryButton
158+ onClick = { toggleRemovalDialog }
159+ isDisabled = { isRemoving }
160+ className = { classNames ( { [ styles . disabledRemoveButton ] : isRemoving } ) }
161+ >
162+ Remove species
163+ </ SecondaryButton >
110164 </ div >
165+ { isRemoving && (
166+ < DeletionConfirmation
167+ warningText = "If you remove this species, any views you have configured will be lost — do you wish to continue?"
168+ confirmText = "Remove"
169+ cancelText = "Do not remove"
170+ className = { styles . speciesRemoveMessage }
171+ onCancel = { toggleRemovalDialog }
172+ onConfirm = { onRemove }
173+ />
174+ ) }
111175 </ div >
112176 ) : (
113177 < div className = { blockClasses } />
0 commit comments