diff --git a/src/js/components/Drawers/HeaderProfileDrawer.jsx b/src/js/components/Drawers/HeaderProfileDrawer.jsx index af0dde995..2af676405 100644 --- a/src/js/components/Drawers/HeaderProfileDrawer.jsx +++ b/src/js/components/Drawers/HeaderProfileDrawer.jsx @@ -252,7 +252,10 @@ function HeaderProfileDrawer () { )} -
Your Settings
+
+ Settings + Your Settings +
{windowWidth >= 768 && ( <> @@ -288,7 +291,7 @@ function HeaderProfileDrawer () { <> {showLinksToProfilePages ? ( - {ImportContactsJsx} + {nextReleaseFeaturesEnabled && ImportContactsJsx} {linksToProfilePages} {SignOutJsx} @@ -302,7 +305,7 @@ function HeaderProfileDrawer () { ) : ( <> - {ImportContactsJsx} + {nextReleaseFeaturesEnabled && ImportContactsJsx} {linksToProfilePages} {SignOutJsx} diff --git a/src/js/components/Navigation/SettingsPersonalSideBar.jsx b/src/js/components/Navigation/SettingsPersonalSideBar.jsx index a148f4f9a..7ede1be44 100644 --- a/src/js/components/Navigation/SettingsPersonalSideBar.jsx +++ b/src/js/components/Navigation/SettingsPersonalSideBar.jsx @@ -126,7 +126,7 @@ export default class SettingsPersonalSideBar extends Component {
Your Settings
- {isSignedIn && nextReleaseFeaturesEnabled && ( + {(isSignedIn && nextReleaseFeaturesEnabled) && (
import(/* webpackChunkName: 'HelpWinOrDefeatModal' */ '../../../common/components/CampaignSupport/HelpWinOrDefeatModal')); // eslint-disable-line import/no-cycle -const nextReleaseFeaturesEnabled = webAppConfig.ENABLE_NEXT_RELEASE_FEATURES === undefined ? false : webAppConfig.ENABLE_NEXT_RELEASE_FEATURES; const NUMBER_OF_BALLOT_CHOICES_ALLOWED_BEFORE_SHOW_MODAL = 3; const shareIconSvg = '../../../../img/global/svg-icons/share-icon.svg'; @@ -1102,7 +1101,7 @@ class ItemActionBar extends PureComponent { {/* Chat bubble + "For candidate staff", candidates/politicians only. Pass showCandidateStaffAndChat prop to enable (e.g. in BallotScrollingContainer). */} - {((ballotItemType === 'CANDIDATE' || ballotItemType === 'POLITICIAN') && this.props.showCandidateStaffAndChat && nextReleaseFeaturesEnabled) && ( + {((ballotItemType === 'CANDIDATE' || ballotItemType === 'POLITICIAN') && this.props.showCandidateStaffAndChat) && ( <> {/* When visibilityRowOpen: hide bubble, show divider + visibility text inline */} {visibilityRowOpen ? ( diff --git a/src/js/pages/ElectionFinder/ElectionFinderForElection.jsx b/src/js/pages/ElectionFinder/ElectionFinderForElection.jsx index 053d530de..8bb1f2dd7 100644 --- a/src/js/pages/ElectionFinder/ElectionFinderForElection.jsx +++ b/src/js/pages/ElectionFinder/ElectionFinderForElection.jsx @@ -22,9 +22,12 @@ import { CandidateParty, CandidateRow, DetailTitle, ElectionTitleRow, ExpandCollapseButton, ExpandCollapseRow, ExpandMoreIcon, HighlightSpan, InlineSearchField, NoResults, - OfficeHeader, OfficeHeaderActions, OfficeHeaderLeft, OfficeName, + OfficeHeader, OfficeHeaderActions, OfficeHeaderLeft, OfficeName, OfficePrimaryPartySpan, OfficeSection, SearchIconButton, SearchResultCount, ShowMoreButton, } from './electionFinderStyles'; +import webAppConfig from '../../config'; + +const nextReleaseFeaturesEnabled = webAppConfig.ENABLE_NEXT_RELEASE_FEATURES === undefined ? false : webAppConfig.ENABLE_NEXT_RELEASE_FEATURES; function ElectionFinderForElection () { renderLog('ElectionFinderForElection'); @@ -205,9 +208,11 @@ function ElectionFinderForElection () { {electionName} - - - + {nextReleaseFeaturesEnabled && ( + + + + )} {electionSearchOpen ? ( + {officeName} + {primaryParty && ( + + , + {' '} + {primaryParty} + {' '} + Primary + + )} + + ); return ( onToggle(officeWeVoteId)}> @@ -317,7 +338,7 @@ function OfficeSectionItemInner ({ // eslint-disable-line react/no-multi-comp - {searchText ? highlightMatch(officeName, searchText) : officeName} + {searchText ? highlightMatch(officeNameWithPrimaryParty, searchText) : officeNameWithPrimaryParty} {` (${candidates.length})`} @@ -335,9 +356,11 @@ function OfficeSectionItemInner ({ // eslint-disable-line react/no-multi-comp - - - + {nextReleaseFeaturesEnabled && ( + + + + )} window.open(`/office/${officeWeVoteId}`, '_blank')}> diff --git a/src/js/pages/ElectionFinder/ElectionFinderForState.jsx b/src/js/pages/ElectionFinder/ElectionFinderForState.jsx index 7af5da126..242be5b0b 100644 --- a/src/js/pages/ElectionFinder/ElectionFinderForState.jsx +++ b/src/js/pages/ElectionFinder/ElectionFinderForState.jsx @@ -18,6 +18,9 @@ import { SearchIconButton, SectionTitle, SectionTitleRow, ShowMoreButton, StateSelectWrapper, StateSelectNative, StateSelectLabel, StateSelectCaret, } from './electionFinderStyles'; +import webAppConfig from '../../config'; + +const nextReleaseFeaturesEnabled = webAppConfig.ENABLE_NEXT_RELEASE_FEATURES === undefined ? false : webAppConfig.ENABLE_NEXT_RELEASE_FEATURES; const SORTED_STATES = Object.entries(stateCodeMap) .filter(([code]) => code !== 'NA') @@ -216,9 +219,11 @@ function ElectionFinderForState () { {sectionTitle} - - - + {nextReleaseFeaturesEnabled && ( + + + + )} @@ -245,9 +250,11 @@ function ElectionFinderForState () { - - - + {nextReleaseFeaturesEnabled && ( + + + + )} window.open(`/election-finder/${selectedStateCode.toLowerCase()}/${googleCivicElectionId}`, '_blank')}> diff --git a/src/js/pages/ElectionFinder/ElectionFinderHeader.jsx b/src/js/pages/ElectionFinder/ElectionFinderHeader.jsx index 57b362962..2996e747c 100644 --- a/src/js/pages/ElectionFinder/ElectionFinderHeader.jsx +++ b/src/js/pages/ElectionFinder/ElectionFinderHeader.jsx @@ -18,7 +18,7 @@ function ElectionFinderHeader ({ breadcrumbs, stateLabel, subtitle }) { {isLast || !crumb.href ? ( {crumb.label} ) : ( - + {crumb.label} )} diff --git a/src/js/pages/ElectionFinder/ElectionFinderHome.jsx b/src/js/pages/ElectionFinder/ElectionFinderHome.jsx index 4701b9219..6de59c252 100644 --- a/src/js/pages/ElectionFinder/ElectionFinderHome.jsx +++ b/src/js/pages/ElectionFinder/ElectionFinderHome.jsx @@ -17,6 +17,9 @@ import { SearchIconButton, SectionTitle, SectionTitleRow, ShowMoreButton, StateSelectWrapper, StateSelectNative, StateSelectLabel, StateSelectCaret, } from './electionFinderStyles'; +import webAppConfig from '../../config'; + +const nextReleaseFeaturesEnabled = webAppConfig.ENABLE_NEXT_RELEASE_FEATURES === undefined ? false : webAppConfig.ENABLE_NEXT_RELEASE_FEATURES; function formatDateUS (dateString) { if (!dateString) return ''; @@ -34,15 +37,24 @@ const SORTED_STATES = Object.entries(stateCodeMap) function ElectionFinderHome () { renderLog('ElectionFinderHome'); + const [copyLinkText, setCopyLinkText] = useState('Copy link'); const [electionList, setElectionList] = useState([]); const [selectedStateCode, setSelectedStateCode] = useState('all'); const [filterTab, setFilterTab] = useState('upcoming'); const [visibleCount, setVisibleCount] = useState(50); const [searchOpen, setSearchOpen] = useState(false); const [searchText, setSearchText] = useState(''); + const copyLinkTimeoutRef = useRef(null); const searchInputRef = useRef(null); const searchDebounceRef = useRef(null); + useEffect(() => () => { + // Clear timeout when component unmounts + if (copyLinkTimeoutRef.current) { + clearTimeout(copyLinkTimeoutRef.current); + } + }, []); + useEffect(() => { window.scrollTo(0, 0); const listener = ElectionStore.addListener(() => { @@ -186,9 +198,11 @@ function ElectionFinderHome () { {sectionTitle} - - - + {nextReleaseFeaturesEnabled && ( + + + + )} @@ -206,8 +220,12 @@ function ElectionFinderHome () { {election.election_name || ''} e.stopPropagation()}> - + { + setCopyLinkText('Copied!'); + copyLinkTimeoutRef.current = setTimeout(() => { + setCopyLinkText('Copy link'); + }, 3000); const sc = (election.state_code_list && election.state_code_list.length > 0) ? election.state_code_list[0].toLowerCase() : 'na'; @@ -215,13 +233,15 @@ function ElectionFinderHome () { }} > - Copy link + {copyLinkText} - - - + {nextReleaseFeaturesEnabled && ( + + + + )}