diff --git a/src/js/common/utils/logging.js b/src/js/common/utils/logging.js index b516f8c..31dc669 100644 --- a/src/js/common/utils/logging.js +++ b/src/js/common/utils/logging.js @@ -54,6 +54,18 @@ export function authLog (text, res) { } } +// Log reactQuery fetches and responses +export function reactQueryLog (text, res) { + if (webAppConfig.LOG_REACT_QUERY_EVENTS) { + if (res) { + console.log('>> reactQuery >> ', text, res); + } else { + console.log('>> reactQuery >> ', text); + } + } +} + + // Cordova offsets export function cordovaOffsetLog (text, res) { if (webAppConfig.LOG_CORDOVA_OFFSETS) { diff --git a/src/js/components/Login/ResetYourPassword.jsx b/src/js/components/Login/ResetYourPassword.jsx new file mode 100644 index 0000000..5f52dfd --- /dev/null +++ b/src/js/components/Login/ResetYourPassword.jsx @@ -0,0 +1,179 @@ +import { Modal } from '@mui/material'; +import Button from '@mui/material/Button'; +import Dialog from '@mui/material/Dialog'; +import DialogContent from '@mui/material/DialogContent'; +import DialogContentText from '@mui/material/DialogContentText'; +import DialogTitle from '@mui/material/DialogTitle'; +import TextField from '@mui/material/TextField'; +import PropTypes from 'prop-types'; +import * as React from 'react'; +import { useEffect, useRef, useState } from 'react'; +import validator from 'validator'; +import { renderLog } from '../../common/utils/logging'; +import { useConnectAppContext } from '../../contexts/ConnectAppContext'; +import makeRequestParams from '../../react-query/makeRequestParams'; +import { useLogoutMutation, usePersonRetrieveByEmailMutation, usePersonSaveForAuthMutation } from '../../react-query/mutations'; +import weConnectQueryFn, { METHOD } from '../../react-query/WeConnectQuery'; +import { ErrorMessage } from '../Style/sharedStyles'; +import VerifySecretCodeModal from '../VerifySecretCodeModal'; + +const ResetYourPassword = ({ openDialog, closeDialog }) => { + renderLog('ResetYourPassword'); + const { mutate: mutateRetrievePersonByEmail } = usePersonRetrieveByEmailMutation(); + const { mutate: mutatePersonSaveForAuth } = usePersonSaveForAuthMutation(); + const { mutate: mutateLogout } = useLogoutMutation(); + const { getAppContextValue, setAppContextValue } = useConnectAppContext(); + + const [open, setOpen] = React.useState(openDialog); + const [displayEmailAddress, setDisplayEmailAddress] = useState(true); + const [warningLine, setWarningLine] = useState(''); + const [errorMessage, setErrorMessage] = useState(''); + + const emailRef = useRef(''); + const password1Ref = useRef(''); + const password2Ref = useRef(''); + const authPerson = useRef(undefined); + + useEffect(() => { + setOpen(openDialog); + }, [openDialog]); + + const secretCodeVerified = getAppContextValue('secretCodeVerifiedForReset') || false; + useEffect(() => { + if (secretCodeVerified === true) { + console.log('received new secretCodeVerifiedForReset', secretCodeVerified); + setDisplayEmailAddress(false); + emailRef.current = ''; + password1Ref.current = ''; + password2Ref.current = ''; + } + }, [secretCodeVerified]); + + const auth = getAppContextValue('authenticatedPerson'); + useEffect(() => { + const authP = getAppContextValue('authenticatedPerson'); + if (authP && open) { + console.log('received new authP', authP); + authPerson.current = authP; + console.log('authPerson.personId in Login useEffect [auth] id: ', authP.personId); + console.log('authPerson.personId in Login useEffect [auth] open: ', open); + weConnectQueryFn('send-email-code', { personId: authP.personId }, METHOD.POST) + .then(setAppContextValue('openVerifySecretCodeModalDialog', true)); + } + // eslint would have us add getAppContextValue and setAppContextValue, which causes and endless loop + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [auth]); + + const sendEmail = async () => { + const email = emailRef.current.value; + setAppContextValue('resetEmail', email); + console.log('email in sendEmail: ', emailRef.current.value); + if (!validator.isEmail(email)) { + setWarningLine('Please enter a valid email address.'); + return; + } + setWarningLine(''); + setAppContextValue('openVerifySecretCodeModalDialog', true); + // Logout so that the current sessionID will not be reused when resetting password for a potentially differnt staff member + await mutateLogout(); + // This retrieve will set the 'authenticatedPerson' app context value, and bring back a new sessionID (without touching the cookie) + await mutateRetrievePersonByEmail({ emailPersonal: email }); + }; + + const handleClose = () => { + setOpen(false); + closeDialog(false); + }; + + const changePassword = async () => { + const pass1 = password1Ref.current.value; + const pass2 = password2Ref.current.value; + const person = authPerson.current; + + console.log('password in changePassword: ', pass1, pass2); + if (pass1 !== pass2) { + setErrorMessage('Your password entries do not match.'); + } else { + setErrorMessage(''); + // const person = getAppContextValue('authenticatedPerson'); + await mutatePersonSaveForAuth(makeRequestParams({ id: person.id }, { password: pass1 })); + setAppContextValue('isAuthenticated', true); + console.log('ResetYourPassword changePassword pass1, pass2: ', pass1, pass2); + setAppContextValue('resetPassword', pass1); + handleClose(); + } + }; + + console.log('ResetYourPassword incoming authPerson: ', authPerson); + return ( + <> + + + Reset your Password +
{warningLine}
+ + + {displayEmailAddress ? 'Please enter your email address.' : 'Please enter your new password.'} + + {errorMessage} + { displayEmailAddress ? ( + + ) : ( +
+ + + + )} + +
+
+
+ + + ); +}; +ResetYourPassword.propTypes = { + openDialog: PropTypes.func, + closeDialog: PropTypes.func, +}; + +export default ResetYourPassword; diff --git a/src/js/components/Navigation/HeaderBar.jsx b/src/js/components/Navigation/HeaderBar.jsx index a5f663d..03c35fd 100644 --- a/src/js/components/Navigation/HeaderBar.jsx +++ b/src/js/components/Navigation/HeaderBar.jsx @@ -7,7 +7,7 @@ import styled from 'styled-components'; import standardBoxShadow from '../../common/components/Style/standardBoxShadow'; import { hasIPhoneNotch } from '../../common/utils/cordovaUtils'; import { normalizedHrefPage } from '../../common/utils/hrefUtils'; -import { renderLog } from '../../common/utils/logging'; +import { authLog, renderLog } from '../../common/utils/logging'; import { useConnectAppContext } from '../../contexts/ConnectAppContext'; import { clearSignedInGlobals } from '../../contexts/contextFunctions'; import { viewerCanSeeOrDo } from '../../models/AuthModel'; @@ -22,7 +22,7 @@ import HeaderBarLogo from './HeaderBarLogo'; const HeaderBar = ({ hideTabs }) => { renderLog('HeaderBar'); const navigate = useNavigate(); - const { apiDataCache, getAppContextValue, setAppContextValue } = useConnectAppContext(); + const { apiDataCache, getAppContextValue, setAppContextValue, getAppContextData } = useConnectAppContext(); const { viewerAccessRights } = apiDataCache; const { mutate: mutateLogout } = useLogoutMutation(); @@ -34,7 +34,7 @@ const HeaderBar = ({ hideTabs }) => { const isAuth = getAppContextValue('isAuthenticated'); useEffect(() => { if (isAuth !== null) { - console.log('----------- isAuthenticated changed =', isAuth); + authLog('HeaderBar isAuthenticated changed =', isAuth); setIsAuthenticated(isAuth); } }, [isAuth]); @@ -43,7 +43,7 @@ const HeaderBar = ({ hideTabs }) => { // I don't think we want to make the weConnectQueryFn call here since we are about to call mutateLogout const data = await weConnectQueryFn('logout', {}, METHOD.POST); console.log(`/logout response in HeaderBar -- status: '${'status'}', data: ${JSON.stringify(data)}`); - clearSignedInGlobals(setAppContextValue); + clearSignedInGlobals(setAppContextValue, getAppContextData); navigate('/login'); mutateLogout(); }; diff --git a/src/js/components/Person/PersonSummaryRow.jsx b/src/js/components/Person/PersonSummaryRow.jsx index ef04899..019c673 100644 --- a/src/js/components/Person/PersonSummaryRow.jsx +++ b/src/js/components/Person/PersonSummaryRow.jsx @@ -5,10 +5,7 @@ import styled from 'styled-components'; import DesignTokenColors from '../../common/components/Style/DesignTokenColors'; import { renderLog } from '../../common/utils/logging'; import { useConnectAppContext } from '../../contexts/ConnectAppContext'; -import { - getFullNamePreferredPerson, - // useGetFullNamePreferred, -} from '../../models/PersonModel'; +import { getFullNamePreferredPerson } from '../../models/PersonModel'; import { useRemoveTeamMemberMutation } from '../../react-query/mutations'; import { DeleteStyled, EditStyled } from '../Style/iconStyles'; import { viewerCanSeeOrDo, viewerCanSeeOrDoForThisTeam } from '../../models/AuthModel'; @@ -117,7 +114,6 @@ const PersonSummaryRow = ({ person, rowNumberForDisplay, teamId }) => { id={`removeMember-personId-${person.personId}`} onClick={() => removeTeamMemberClick(person)} style={{ cursor: 'pointer' }} - // cellwidth="20" cellwidth={20} > diff --git a/src/js/components/PrivateRoute.jsx b/src/js/components/PrivateRoute.jsx index be3736a..5a49563 100644 --- a/src/js/components/PrivateRoute.jsx +++ b/src/js/components/PrivateRoute.jsx @@ -7,7 +7,7 @@ import { captureAccessRightsData } from '../models/AuthModel'; const PrivateRoute = () => { const location = useLocation(); - const { apiDataCache, getAppContextValue } = useConnectAppContext(); + const { apiDataCache, getAppContextValue, setAppContextValue } = useConnectAppContext(); const dispatch = useConnectDispatch(); const [isAuthenticated, setIsAuthenticated] = useState(null); @@ -15,17 +15,16 @@ const PrivateRoute = () => { const { data: dataAuth, isSuccess: isSuccessAuth } = useFetchData(['get-auth'], {}, METHOD.POST); useEffect(() => { if (isSuccessAuth) { - // console.log('useFetchData in PrivateRoute useEffect dataAuth good:', dataAuth, isSuccessAuth); + authLog('useFetchData in PrivateRoute useEffect dataAuth good:', dataAuth, isSuccessAuth); setIsAuthenticated(dataAuth.isAuthenticated); - // setAppContextValue('loggedInPersonIsAdmin', dataAuth.loggedInPersonIsAdmin); + setAppContextValue('loggedInPersonIsAdmin', dataAuth.loggedInPersonIsAdmin); captureAccessRightsData(dataAuth, isSuccessAuth, apiDataCache, dispatch); - authLog('========= PrivateRoute =========== INNER isAuthenticated: ', dataAuth.isAuthenticated); } }, [dataAuth, isSuccessAuth]); const isAuth = getAppContextValue('isAuthenticated'); - authLog('========= PrivateRoute =========== OUTER isAuthenticated: ', isAuthenticated, ', isAuth: ', isAuth); + authLog('========= PrivateRoute =========== isAuthenticated: ', isAuthenticated); if (isAuthenticated || isAuth || isAuthenticated !== false) { return ; diff --git a/src/js/components/Style/sharedStyles.js b/src/js/components/Style/sharedStyles.js index c4fd278..fe94170 100644 --- a/src/js/components/Style/sharedStyles.js +++ b/src/js/components/Style/sharedStyles.js @@ -9,3 +9,10 @@ export const MatchingPerson = styled('div')` margin: 10px 0 0 10px; font-style: italic; `; + +export const ErrorMessage = styled('div')` + color: red; + margin-top: 50px; + text-align: center; + font-size: 18px; +`; diff --git a/src/js/components/Team/TeamHeader.jsx b/src/js/components/Team/TeamHeader.jsx index 00185c2..33348cf 100644 --- a/src/js/components/Team/TeamHeader.jsx +++ b/src/js/components/Team/TeamHeader.jsx @@ -30,7 +30,7 @@ const TeamHeader = ({ showHeaderLabels, showIcons, team }) => { return ( {/* Width (below) of this TeamHeaderCell comes from the combined widths of the first x columns in TeamMemberList */} - + {teamLocal && ( {teamLocal.teamName} @@ -85,19 +85,17 @@ const OneTeamHeader = styled('div')` margin-top: 10px; `; -const TeamHeaderCell = styled('div', { - shouldForwardProp: (prop) => !['largefont', 'titlecell', 'cellwidth'].includes(prop), -})(({ largefont, titlecell, cellwidth }) => (` +const TeamHeaderCell = styled.div` align-content: center; - ${(titlecell) ? '' : 'border-bottom: 1px solid #ccc;'} - ${(largefont) ? 'font-size: 1.1em;' : 'font-size: .8em;'} - ${(titlecell) ? '' : 'font-weight: 550;'} + border-bottom: ${(props) => (props?.$titleCell ? ';' : '1px solid #ccc;')} + font-size: ${(props) => (props?.$largefont ? '1.1em;' : '.8em;')}; + font-weight: ${(props) => (props?.$titleCell ? ';' : '550;')} height: 22px; - ${cellwidth ? `max-width: ${cellwidth}px;` : ''} - ${cellwidth ? `min-width: ${cellwidth}px;` : ''} + max-width: ${(props) => (props.cellwidth ? `${props.cellwidth}px;` : ';')}; + min-width: ${(props) => (props.cellwidth ? `${props.cellwidth}px;` : ';')}; + width: ${(props) => (props.cellwidth ? `${props.cellwidth}px;` : ';')}; overflow: hidden; white-space: nowrap; - ${cellwidth ? `width: ${cellwidth}px;` : ''} -`)); +`; export default withStyles(styles)(TeamHeader); diff --git a/src/js/components/VerifySecretCodeModal.jsx b/src/js/components/VerifySecretCodeModal.jsx index ed133be..bcdce62 100644 --- a/src/js/components/VerifySecretCodeModal.jsx +++ b/src/js/components/VerifySecretCodeModal.jsx @@ -9,13 +9,12 @@ import { isIPhone4in } from '../common/utils/cordovaUtils'; import { isCordova, isWebApp } from '../common/utils/isCordovaOrWebApp'; import { renderLog } from '../common/utils/logging'; import { useConnectAppContext } from '../contexts/ConnectAppContext'; -import { useGetAuthMutation } from '../react-query/mutations'; import weConnectQueryFn, { METHOD } from '../react-query/WeConnectQuery'; +import { ErrorMessage } from './Style/sharedStyles'; -const VerifySecretCodeModal = ({ classes, person, openVerifyModalDialog }) => { +const VerifySecretCodeModal = ({ classes, person }) => { renderLog('VerifySecretCodeModal'); - const { mutate: mutateAuth } = useGetAuthMutation(); - const { getAppContextValue } = useConnectAppContext(); + const { getAppContextValue, setAppContextValue } = useConnectAppContext(); const d1FldRef = useRef(''); const d2FldRef = useRef(''); @@ -29,21 +28,25 @@ const VerifySecretCodeModal = ({ classes, person, openVerifyModalDialog }) => { const [condensed] = useState(true); const [voterPhoneNumber] = useState(undefined); const [voterEmailAddress] = useState(true); - const [openDialog, setOpenDialog] = useState(true); + const [openDialogMutable, setOpenDialogMutable] = useState(false); + const [errorMessage, setErrorMessage] = useState(''); const digits = [[1, 'd1Id', d1FldRef], [2, 'd2Id', d2FldRef], [3, 'd3Id', d3FldRef], [4, 'd4Id', d4FldRef], [5, 'd5Id', d5FldRef], [6, 'd6Id', d6FldRef]]; + const open = getAppContextValue('openVerifySecretCodeModalDialog'); useEffect(() => { - setOpenDialog(openVerifyModalDialog); - }, [openVerifyModalDialog]); + setOpenDialogMutable(getAppContextValue('openVerifySecretCodeModalDialog')); + setAppContextValue('secretCodeVerified', false); + }, [open]); const handleClose = () => { console.log('handleClose pressed'); - setOpenDialog(false); + setOpenDialogMutable(false); + setAppContextValue('openVerifySecretCodeModalDialog', false); }; - const voterVerifySecretCode = async () => { - console.log('voterVerifySecretCode pressed'); + const verifySecretCode = async () => { + console.log('verifySecretCode pressed'); let code = ''; for (let i = 0; i < digits.length; i++) { const digit = digits[i]; @@ -51,15 +54,19 @@ const VerifySecretCodeModal = ({ classes, person, openVerifyModalDialog }) => { code += refDigit.current.value.toString(); } - const newPersonId = getAppContextValue('authenticatedPersonId'); - const data = await weConnectQueryFn('verify-email-code', { personId: newPersonId, code }, METHOD.POST); + const data = await weConnectQueryFn('verify-email-code', { personId: person.personId, code }, METHOD.POST); console.log(`/verify-email-code response: data: ${JSON.stringify(data)}`); - await mutateAuth(); // to propagate the invalidation to HeaderBar and Login (might be a better way to do this) - setOpenDialog(false); + if (data.emailVerified) { + setAppContextValue('secretCodeVerified', true); + setAppContextValue('secretCodeVerifiedForReset', true); + setOpenDialogMutable(false); + } else { + setErrorMessage('Your code did not verify. Try again.'); + } }; useEffect(() => { - while (d1FldRef?.current) { + while (d1FldRef?.current && openDialogMutable) { setTimeout(() => { // See https://github.com/mui/material-ui/issues/33004#issuecomment-1455260156 d1FldRef.current?.focus(); @@ -80,11 +87,14 @@ const VerifySecretCodeModal = ({ classes, person, openVerifyModalDialog }) => { } }, [nextFocus]); + const extractDigits = (str) => { + const digitsLocal = str.match(/\d/g); + return digitsLocal?.length ? digitsLocal.join('') : ''; + }; + const onPaste = (event) => { - // console.log(ev.clipboardData.getData('Text')); - const clipboardData = event.clipboardData || window.clipboardData; - const pastedData = clipboardData.getData('text').trim(); - console.log(pastedData); + const clipboardData = (event.originalEvent || event).clipboardData.getData('text/plain'); + const pastedData = extractDigits(clipboardData); for (let i = 0; i < pastedData.length; i++) { const digit = digits[i]; @@ -97,8 +107,6 @@ const VerifySecretCodeModal = ({ classes, person, openVerifyModalDialog }) => { } }; - - const onDigitChange = (event) => { // eslint-disable-next-line no-unused-vars const [index, id, refThis] = digits.find((dig) => dig[1] === event.target.id); @@ -109,25 +117,23 @@ const VerifySecretCodeModal = ({ classes, person, openVerifyModalDialog }) => { refThis.current.blur(); setNextFocus(index + 1); } - + setErrorMessage(''); console.log(event); }; - if (!(openDialog)) { + if (!openDialogMutable || !person || Object.keys(person).length === 0) { return null; } return ( { Code Verification A 6-digit code has been sent to - {person?.email} + {person?.email} {(voterEmailAddress) ? ( If you haven't received the code in 30 seconds, please check your spam folder and mark the email as 'Not Spam'. @@ -159,6 +165,7 @@ const VerifySecretCodeModal = ({ classes, person, openVerifyModalDialog }) => { {digits.map((dig) => ( { label={false} notched={false} onChange={onDigitChange} + onPaste={onPaste} type="tel" - autoFocus={dig[0] === 0} // onFocus="this.select()" // maxLength={1} // value={this.state.digit1} // onBlur={this.handleBlur} - onPaste={onPaste} /> ))} + {errorMessage} @@ -201,7 +206,6 @@ const VerifySecretCodeModal = ({ classes, person, openVerifyModalDialog }) => { VerifySecretCodeModal.propTypes = { classes: PropTypes.object, person: PropTypes.object, - openVerifyModalDialog: PropTypes.bool, }; const styles = (theme) => ({ @@ -345,18 +349,10 @@ const Subtitle = styled('h4')` text-align: center; `; -const PhoneSubtitle = styled('h4')` +const EmailSubtitle = styled('h4')` color: black; font-weight: bold; text-align: center; `; -// const ErrorMessage = styled('div')` -// color: red; -// margin: 12px 0; -// text-align: center; -// font-size: 14px; -// `; - - export default withTheme(withStyles(styles)(VerifySecretCodeModal)); diff --git a/src/js/config-template.js b/src/js/config-template.js index 8074cc9..c771d6d 100644 --- a/src/js/config-template.js +++ b/src/js/config-template.js @@ -57,14 +57,15 @@ module.exports = { DEBUG_MODE: false, SHOW_TEST_OPTIONS: false, // On the DeviceDialog and elsewhere - LOG_RENDER_EVENTS: false, - LOG_ONLY_FIRST_RENDER_EVENTS: false, + ENABLE_REACT_QUERY_TOOLS: false, // Show ReactQueryDevtools icon/console + LOG_AUTHENTICATION: false, // authLog function prints to console + LOG_CORDOVA_OFFSETS: false, LOG_HTTP_REQUESTS: false, + LOG_RENDER_EVENTS__FIRST_ONLY: false, // Log the render event for a component, but only the first time + LOG_REACT_QUERY_EVENTS: false, // Log query requests/responses + LOG_RENDER_EVENTS: false, LOG_ROUTING: false, - LOG_AUTHENTICATION: false, // authLog function prints to console - LOG_CORDOVA_OFFSETS: false, - SHOW_CORDOVA_URL_FIELD: false, // Only needed for debugging in Cordova - ENABLE_REACT_QUERY_TOOLS: false, // Show ReactQueryDevtools icon/console + SHOW_CORDOVA_URL_FIELD: false, // Only needed for debugging in Cordova // Use 1 or 0 as opposed to true or false test: { diff --git a/src/js/contexts/ConnectAppContext.jsx b/src/js/contexts/ConnectAppContext.jsx index ac971c8..d24b74f 100644 --- a/src/js/contexts/ConnectAppContext.jsx +++ b/src/js/contexts/ConnectAppContext.jsx @@ -1,20 +1,15 @@ import PropTypes from 'prop-types'; import React, { createContext, useContext, useEffect, useReducer, useState } from 'react'; +import { authLog } from '../common/utils/logging'; import initialApiDataCache from '../models/initialApiDataCache'; // import capturePersonListRetrieveData from '../models/capturePersonListRetrieveData'; import { METHOD, useFetchData } from '../react-query/WeConnectQuery'; import { captureAccessRightsData } from '../models/AuthModel'; -// import { getInitialGlobalPersonVariables, PersonListRetrieveDataCapture } from '../models/PersonModel'; -// import { getInitialGlobalTaskVariables } from '../models/TaskModel'; -// import { getInitialGlobalTeamVariables } from '../models/TeamModel'; // Replaces AppObservableStore.js // Create the context const ConnectAppContext = createContext({}); const ConnectDispatch = createContext(null); -// const initialCachedApiPersonVariables = getInitialGlobalPersonVariables(); -// const initialCachedApiTaskVariables = getInitialGlobalTaskVariables(); -// const initialCachedApiTeamVariables = getInitialGlobalTeamVariables(); function apiDataCacheReducer (apiDataCache, action) { let revisedApiDataCache = { ...apiDataCache }; @@ -30,12 +25,6 @@ function apiDataCacheReducer (apiDataCache, action) { } } -// const initialApiDataCache = { -// ...initialCachedApiPersonVariables, -// ...initialCachedApiTaskVariables, -// ...initialCachedApiTeamVariables, -// }; - // Create the provider component // eslint-disable-next-line no-unused-vars export const ConnectAppContextProvider = ({ children }) => { @@ -67,16 +56,48 @@ export const ConnectAppContextProvider = ({ children }) => { } }; + // const { data: dataP, isSuccess: isSuccessP, isFetching: isFetchingP, isStale: isStaleP } = useFetchData(['person-list-retrieve'], {}, METHOD.GET); + // const personListRetrieveResults = useFetchData(['person-list-retrieve'], {}, METHOD.GET); + // This is not currently the right place to pass these values, but I'm saving these here for the next 30 days until we work out the correct place. + // { + // cacheTime: 0, + // networkMode: 'no-cache', <-- This is not a solution, it just covers up some problem in our code, while disabling the biggest benefit of ReactQueries. + // refetchOnMount: true, + // refetchOnWindowFocus: true, + // refetchInterval: 0, + // staleTime: 0, + // } + + // Moved to root pages: Teams, TeamHome, etc. + // useEffect(() => { + // // console.log('useFetchData person-list-retrieve in Teams useEffect:', personListRetrieveResults); + // if (personListRetrieveResults) { + // // console.log('In useEffect apiDataCache:', apiDataCache); + // // const changeResults = + // capturePersonListRetrieveData(personListRetrieveResults, apiDataCache, dispatch); + // // console.log('ConnectAppContext useEffect capturePersonListRetrieveData changeResults:', changeResults); + // } + // }, [personListRetrieveResults]); + + // const { data: dataP, isSuccess: isSuccessP, isFetching: isFetchingP } = personListRetrieveResults; + // useEffect(() => { + // // console.log('useFetchData in TeamHome (person-list-retrieve) useEffect:', dataP, isSuccessP, isFetchingP, isStaleP); + // if (isSuccessP) { + // // console.log('useFetchData in TeamHome (person-list-retrieve)useEffect data good:', dataP, isSuccessP, isFetchingP, isStaleP); + // setAppContextValue('allPeopleList', dataP ? dataP.personList : []); + // // console.log('ConnectAppContext useEffect allPeopleList fetched'); + // } + // }, [dataP, isSuccessP, isFetchingP]); + // The following prints console log errors const { data: dataAuth, isSuccess: isSuccessAuth, isFetching: isFetchingAuth } = useFetchData(['get-auth'], {}, METHOD.POST); useEffect(() => { if (isSuccessAuth) { - // console.log('useFetchData in ConnectAppContext useEffect dataAuth good:', dataAuth, isSuccessAuth, isFetchingAuth); + authLog('useFetchData in ConnectAppContext useEffect dataAuth good:', dataAuth, isSuccessAuth, isFetchingAuth); const { isAuthenticated } = dataAuth; setAppContextValue('authenticatedPerson', dataAuth.person); - setAppContextValue('authenticatedPersonId', dataAuth.personId); setAppContextValue('isAuthenticated', isAuthenticated); - // setAppContextValue('loggedInPersonIsAdmin', dataAuth.loggedInPersonIsAdmin); + setAppContextValue('loggedInPersonIsAdmin', dataAuth.loggedInPersonIsAdmin); captureAccessRightsData(dataAuth, isSuccessAuth, apiDataCache, dispatch); console.log('=============== ConnectAppContextProvider ======= isAuthenticated: ', isAuthenticated, ' ==========='); diff --git a/src/js/contexts/contextFunctions.jsx b/src/js/contexts/contextFunctions.jsx index 4e7671e..0a007f2 100644 --- a/src/js/contexts/contextFunctions.jsx +++ b/src/js/contexts/contextFunctions.jsx @@ -1,8 +1,11 @@ - -export const clearSignedInGlobals = (setAppContextValue) => { - setAppContextValue('authenticatedPerson', undefined); - setAppContextValue('authenticatedPersonId', -1); +const clearSignedInGlobals = (setAppContextValue, getAppContextData) => { + setAppContextValue('authenticatedPerson', {}); setAppContextValue('isAuthenticated', false); - // setAppContextValue('loggedInPersonIsAdmin', false); - setAppContextValue('personIsSignedIn', false); + setAppContextValue('loggedInPersonIsAdmin', false); + setAppContextValue('secretCodeVerifiedForReset', false); + setAppContextValue('secretCodeVerified', false); + console.log('appContextData in clearSignedInGlobals after clear: ', getAppContextData()); }; + +// eslint-disable-next-line import/prefer-default-export +export { clearSignedInGlobals }; diff --git a/src/js/pages/Login.jsx b/src/js/pages/Login.jsx index ac37928..3f4555e 100644 --- a/src/js/pages/Login.jsx +++ b/src/js/pages/Login.jsx @@ -1,6 +1,5 @@ import { Button, TextField } from '@mui/material'; import { withStyles } from '@mui/styles'; -import { useQueryClient } from '@tanstack/react-query'; import PropTypes from 'prop-types'; import React, { useEffect, useRef, useState } from 'react'; import { Helmet } from 'react-helmet-async'; @@ -9,23 +8,22 @@ import styled from 'styled-components'; import validator from 'validator'; import { renderLog } from '../common/utils/logging'; import compileDate from '../compileDate'; +import ResetYourPassword from '../components/Login/ResetYourPassword'; import { PageContentContainer } from '../components/Style/pageLayoutStyles'; import VerifySecretCodeModal from '../components/VerifySecretCodeModal'; import webAppConfig from '../config'; import { useConnectAppContext, useConnectDispatch } from '../contexts/ConnectAppContext'; -// import { clearSignedInGlobals } from '../contexts/contextFunctions'; +import { clearSignedInGlobals } from '../contexts/contextFunctions'; import { captureAccessRightsData } from '../models/AuthModel'; import { getFullNamePreferredPerson } from '../models/PersonModel'; import { useLogoutMutation } from '../react-query/mutations'; import weConnectQueryFn, { METHOD, useFetchData } from '../react-query/WeConnectQuery'; -import ReactQuerySaveReadTest from '../test/ReactQuerySaveReadTest'; const Login = ({ classes }) => { renderLog('Login'); const navigate = useNavigate(); - const queryClient = useQueryClient(); - const { apiDataCache, setAppContextValue } = useConnectAppContext(); + const { apiDataCache, getAppContextValue, setAppContextValue, getAppContextData } = useConnectAppContext(); const dispatch = useConnectDispatch(); const { mutate: mutateLogout } = useLogoutMutation(); @@ -38,10 +36,10 @@ const Login = ({ classes }) => { // const stateFldRef = useRef(''); const passwordFldRef = useRef(''); const confirmPasswordFldRef = useRef(''); + const authPerson = useRef(undefined); - const [authPerson, setAuthPerson] = useState({}); - const [openVerifyModalDialog, setOpenVerifyModalDialog] = useState(false); - const [returnFromLogin, setReturnFromLogin] = useState(false); + const [loginAttempted, setLoginAttempted] = useState(false); + const [openResetPasswordDialog, setOpenResetPasswordDialog] = useState(false); const [showCreateStuff, setShowCreateStuff] = useState(false); const [successLine, setSuccessLine] = useState(''); const [warningLine, setWarningLine] = useState(''); @@ -51,17 +49,24 @@ const Login = ({ classes }) => { if (isSuccessAuth) { console.log('useFetchData in Login useEffect dataAuth good:', dataAuth, isSuccessAuth, isFetchingAuth); - const { isAuthenticated } = dataAuth; - const authenticatedPerson = dataAuth.person; - setAuthPerson(authenticatedPerson); - const success = isAuthenticated && authenticatedPerson ? `Signed in as ${getFullNamePreferredPerson(authenticatedPerson)}` : 'Please sign in'; - setSuccessLine(success); - // setAppContextValue('loggedInPersonIsAdmin', dataAuth.loggedInPersonIsAdmin); + const { isAuthenticated, person: authenticatedPerson, emailVerified: emailVerifiedFromAPI, personId } = dataAuth; + authPerson.current = authenticatedPerson; captureAccessRightsData(dataAuth, isSuccessAuth, apiDataCache, dispatch); - if (isAuthenticated && returnFromLogin) { - setTimeout(() => { - navigate('/tasks'); - }, 2000); + console.log('appContextData in Login [dataAuth, isSuccessAuth]: ', getAppContextData()); + if (!emailVerifiedFromAPI && personId > 0) { + setWarningLine(''); + setSuccessLine('A verification email has been sent to your address'); + setAppContextValue('openVerifySecretCodeModalDialog', true); + } else if (isAuthenticated && authenticatedPerson) { + setSuccessLine(`Signed in as ${getFullNamePreferredPerson(authenticatedPerson)}`); + setAppContextValue('loggedInPersonIsAdmin', dataAuth.loggedInPersonIsAdmin); + if (loginAttempted) { // if we navigate to here directly, not as a result of a loginAPI + setTimeout(() => { + navigate('/tasks'); + }, 2000); + } + } else { + setSuccessLine('Please sign in'); } } }, [dataAuth, isSuccessAuth]); @@ -70,30 +75,56 @@ const Login = ({ classes }) => { if (!validator.isEmail(email)) { setWarningLine('Please enter a valid email address.'); return; - } - if (validator.isEmpty(password)) { + } else if (validator.isEmpty(password)) { setWarningLine('Password cannot be blank.'); return; + } else { + setSuccessLine(''); + setSuccessLine(''); } + setLoginAttempted(true); // so we know when to timeout to /tasks const data = await weConnectQueryFn('login', { email, password }, METHOD.POST); console.log(`/login response -- status: '${'status'}', data: ${JSON.stringify(data)}`); if (data.personId > 0) { - setWarningLine(''); - setSuccessLine(`Cheers person #${data.personId}! You are signed in!`); - setAppContextValue('isAuthenticated', true); - setAppContextValue('authenticatedPersonId', data.personId); - setReturnFromLogin(true); - if (!data.emailVerified) { - setOpenVerifyModalDialog(true); + setAppContextValue('isAuthenticated', data.emailVerified); + if (data.emailVerified) { + setWarningLine(''); + setSuccessLine(`${getFullNamePreferredPerson(data.person)}, you are signed in!`); + setAppContextValue('authenticatedPerson', data); + setTimeout(() => { + navigate('/tasks'); + }, 2000); + } else { + authPerson.current = { // just enough data for VerifySecretCodeModal + personId: data.personId, + personEmail: email.trim(), + }; + setAppContextValue('openVerifySecretCodeModalDialog', true); + setSuccessLine('A verification email has been sent to your address'); } - await queryClient.invalidateQueries('get-auth'); } else { setWarningLine(data.error.msg); setSuccessLine(''); } }; + const secretCodeVerified = getAppContextValue('secretCodeVerified'); + const resetPassword = getAppContextValue('resetPassword'); + useEffect(() => { + if (secretCodeVerified === true && resetPassword && resetPassword.length) { + loginApi(getAppContextValue('resetEmail'), getAppContextValue('resetPassword')).then(() => { + // console.log('--------- useEffect secretCodeVerified in Login, clearing resetEmail and resetPassword', e, p); + setAppContextValue('resetEmail', ''); + setAppContextValue('resetPassword', ''); + setAppContextValue('openVerifySecretCodeModalDialog', false); + setAppContextValue('secretCodeVerified', false); + setAppContextValue('secretCodeVerifiedForReset', false); + // console.log('appContextData in Login L124: ', getAppContextData()); + }); + } + }, [secretCodeVerified, resetPassword]); + const logoutApi = async () => { const data = await weConnectQueryFn('logout', {}, METHOD.POST); console.log(`/logout response -- status: '${'status'}', data: ${JSON.stringify(data)}`); @@ -130,12 +161,10 @@ const Login = ({ classes }) => { setWarningLine(errStr); if (data.personCreated) { setSuccessLine(`user # ${data.personId} created`); - // setAppContextValue('isAuthenticated', true); - setAppContextValue('authenticatedPersonId', data.personId); verifyYourEmail(data.personId).then(() => { setSuccessLine('A verification email has been sent to your address'); - console.log('verifyYourEmail in signupApi then clause , setOpenVerifyModalDialog true'); - setOpenVerifyModalDialog(true); + console.log('verifyYourEmail in signupApi then clause , openVerifySecretCodeModalDialog true'); + setAppContextValue('openVerifySecretCodeModalDialog', true); }); } } catch (e) { @@ -152,14 +181,14 @@ const Login = ({ classes }) => { setWarningLine('Enter a valid username and password'); } else { setWarningLine(''); - setAppContextValue('personIsSignedIn', true); loginApi(email, password).then(); } }; const useSignOutPressed = () => { // clearSignedInGlobals is also called in logoutApi, so isn't needed here - // clearSignedInGlobals(setAppContextValue); + // TODO 2/23/25: unfortunately there are two logoutApi(), consolidating them is high priority + clearSignedInGlobals(setAppContextValue, getAppContextData); logoutApi().then(); }; @@ -225,7 +254,7 @@ const Login = ({ classes }) => {
{warningLine}
{successLine}
- { paddingRight: '10px', display: showCreateStuff ? 'block' : 'none' }} /> - { display: showCreateStuff ? 'block' : 'none' }} /> - - { sx={{ paddingBottom: '15px', display: showCreateStuff ? 'block' : 'none' }} /> - { display: showCreateStuff ? 'block' : 'none' }} /> - - @@ -292,7 +321,14 @@ const Login = ({ classes }) => { > Sign In - Forgot your password? +
@@ -317,19 +354,16 @@ const Login = ({ classes }) => {
Compile Date:
{compileDate}
-
- + {authPerson.current && + Object.keys(authPerson.current).length > 0 && + getAppContextValue('secretCodeVerified') !== true && + getAppContextValue('openVerifySecretCodeModalDialog') && ( + + )} + {/* This following test can be deleted or converted to an automated test */} - + {/* */} ); @@ -350,14 +384,6 @@ const styles = (theme) => ({ }, }); -const AStyled = styled('a')` - font-weight: 400; - color: rgb(13, 110, 253); - text-decoration-color: rgb(13, 110, 253); - text-decoration-line: underline; - padding: 8px 0 0 25px; -`; - const DateDisplay = styled('div')` padding: 50px 0 50px 0; `; diff --git a/src/js/pages/SystemSettings/PermissionsAdministration.jsx b/src/js/pages/SystemSettings/PermissionsAdministration.jsx index 95dd65d..60fa972 100644 --- a/src/js/pages/SystemSettings/PermissionsAdministration.jsx +++ b/src/js/pages/SystemSettings/PermissionsAdministration.jsx @@ -65,7 +65,6 @@ const PermissionsAdministration = ({ classes }) => { const cancelClicked = (event) => { const pieces = event.target.id.split('-'); const personId = parseInt(pieces[2]); - // TODO change the data! const activePerson = peopleWorkingArray.find((p) => p.id === personId); const personCached = Object.values(allPeopleCache).find((p) => p.id === personId); Object.assign(activePerson, personCached); diff --git a/src/js/pages/Teams.jsx b/src/js/pages/Teams.jsx index 57401fe..2f273dc 100644 --- a/src/js/pages/Teams.jsx +++ b/src/js/pages/Teams.jsx @@ -210,7 +210,7 @@ const Teams = () => { })}
- Jump to the "Sign in" /login page (Temporary Link) + Sign in
diff --git a/src/js/react-query/WeConnectQuery.js b/src/js/react-query/WeConnectQuery.js index 8f0435f..f5dd9ed 100644 --- a/src/js/react-query/WeConnectQuery.js +++ b/src/js/react-query/WeConnectQuery.js @@ -1,6 +1,6 @@ import { useQuery } from '@tanstack/react-query'; import axios from 'axios'; -import { httpLog } from '../common/utils/logging'; +import { reactQueryLog } from '../common/utils/logging'; import webAppConfig from '../config'; const METHOD = { @@ -16,8 +16,7 @@ const weConnectQueryFn = async (queryKey, params, isGet) => { if (isGet) { url.search = new URLSearchParams(params); } - // 2/12/24 temporarily replaced: httpLog(`weConnectQueryFn ${isGet ? 'GET' : 'POST'} url.href: ${url.href}`); // DO NOT REMOVE, this is the only way to see if we are hitting the API server unnecessarily - // console.log(`weConnectQueryFn ${isGet ? 'GET' : 'POST'} url.href: ${url.href}`); + reactQueryLog(`weConnectQueryFn ${isGet ? 'GET' : 'POST'} url.href: ${url.href}`); let response; try { @@ -38,7 +37,7 @@ const weConnectQueryFn = async (queryKey, params, isGet) => { }; const useFetchData = (queryKey, fetchParams, isGet) => { - httpLog('useFetchData queryKey, fetchParams before fetch: ', queryKey, ' fetchParams: ', fetchParams); + reactQueryLog('useFetchData queryKey, fetchParams before fetch: ', queryKey, ' fetchParams: ', fetchParams); const { data, isSuccess, isFetching, isStale, refetch, error } = useQuery({ queryKey, queryFn: () => weConnectQueryFn(queryKey, fetchParams, isGet), diff --git a/src/js/react-query/mutations.jsx b/src/js/react-query/mutations.jsx index 7510586..a8ac99b 100644 --- a/src/js/react-query/mutations.jsx +++ b/src/js/react-query/mutations.jsx @@ -1,4 +1,5 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; +import { useConnectAppContext } from '../contexts/ConnectAppContext'; import weConnectQueryFn, { METHOD } from './WeConnectQuery'; const useRemoveTeamMutation = () => { @@ -99,6 +100,16 @@ const usePersonSaveMutation = () => { }); }; +const usePersonSaveForAuthMutation = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (params) => weConnectQueryFn('person-save', params, METHOD.GET), + onError: (error) => console.log('error in personSaveMutation: ', error), + onSuccess: () => queryClient.invalidateQueries('get-auth'), + }); +}; + const useSaveTaskMutation = () => { const queryClient = useQueryClient(); @@ -127,10 +138,38 @@ const useGetAuthMutation = () => { }); }; +const usePersonRetrieveMutation = () => { + console.log('entry to useGetPersonMutation'); + const { setAppContextValue } = useConnectAppContext(); + + return useMutation({ + mutationFn: (params) => weConnectQueryFn('person-retrieve', params, METHOD.GET), + onError: (error) => console.log('error in usePersonRetrieveMutation: ', error), + onSuccess: (data, variables, context) => { + console.log('usePersonRetrieveMutation successful, returning', data, variables, context); + setAppContextValue('authenticatedPerson', data); + }, + }); +}; + +const usePersonRetrieveByEmailMutation = () => { + console.log('entry to useGetPersonMutation'); + const { setAppContextValue } = useConnectAppContext(); + + return useMutation({ + mutationFn: (params) => weConnectQueryFn('person-retrieve-by-email', params, METHOD.GET), + onError: (error) => console.log('error in usePersonRetrieveByEmailMutation: ', error), + onSuccess: (data, variables, context) => { + console.log('usePersonRetrieveByEmailMutation successful, returning', data, variables, context); + setAppContextValue('authenticatedPerson', data); + }, + }); +}; + export { useRemoveTeamMutation, useRemoveTeamMemberMutation, useAddPersonToTeamMutation, useQuestionnaireSaveMutation, useTaskDefinitionSaveMutation, useGroupSaveMutation, usePersonAwaySaveMutation, - useQuestionSaveMutation, usePersonSaveMutation, useSaveTaskMutation, useAnswerListSaveMutation, - useLogoutMutation, useGetAuthMutation }; + useQuestionSaveMutation, usePersonSaveMutation, usePersonSaveForAuthMutation, useSaveTaskMutation, useAnswerListSaveMutation, + useLogoutMutation, useGetAuthMutation, usePersonRetrieveMutation, usePersonRetrieveByEmailMutation }; diff --git a/src/js/stores/VoterStore.js b/src/js/stores/VoterStore.js index 0839752..48e07d6 100644 --- a/src/js/stores/VoterStore.js +++ b/src/js/stores/VoterStore.js @@ -1,1341 +1,1341 @@ -import { ReduceStore } from 'flux/utils'; -import VoterActions from '../actions/VoterActions'; // eslint-disable-line import/no-cycle -import Dispatcher from '../common/dispatcher/Dispatcher'; -import AppObservableStore from './AppObservableStore'; // eslint-disable-line import/no-cycle -import apiCalming from '../common/utils/apiCalming'; -import Cookies from '../common/utils/js-cookie/Cookies'; -import stringContains from '../common/utils/stringContains'; -import VoterConstants from '../constants/VoterConstants'; -import { dumpObjProps } from '../utils/appleSiliconUtils'; - -class VoterStore extends ReduceStore { - getInitialState () { - return { - voter: { - interface_status_flags: 0, - state_code_from_ip_address: '', - }, - address: {}, - emailAddressStatus: {}, - emailSignInStatus: {}, - emailAddressList: [], - externalVoterId: '', - facebookSignInStatus: {}, - facebookPhotoRetrieveLoopCount: 0, - latestGoogleCivicElectionId: 0, - secretCodeVerificationStatus: { - incorrectSecretCodeEntered: false, - numberOfTriesRemaining: 5, - secretCodeVerified: false, - voterMustRequestNewCode: false, - voterSecretCodeRequestsLocked: false, - }, - smsPhoneNumberStatus: { - sms_verify_attempted: false, - sms_phone_number_already_owned_by_other_voter: false, - sms_phone_number_already_owned_by_this_voter: false, - sms_phone_number_created: false, - sms_phone_number: '', - sms_phone_number_found: false, - sms_phone_number_deleted: false, - make_primary_sms: false, - sign_in_code_sms_sent: false, - verification_sms_sent: false, - }, - smsPhoneNumberList: [], - voterContactEmailGoogleCount: 0, - voterContactEmailList: [], - voterDeleted: false, - voterEmailQueuedToSave: '', - voterEmailQueuedToSaveSet: false, - voterFirstNameQueuedToSave: '', - voterFirstNameQueuedToSaveSet: false, - voterFirstRetrieveCompleted: false, // Has the first retrieve of the voter completed? - voterFound: false, - voterExternalIdHasBeenSavedOnce: {}, // Dict with externalVoterId and membershipOrganizationWeVoteId as keys, and true/false as value - voterLastNameQueuedToSave: '', - voterLastNameQueuedToSaveSet: false, - voterNotificationSettingsUpdateStatus: { - apiResponseReceived: false, - emailFound: false, - voterFound: false, - normalizedEmailAddress: '', - normalizedSmsPhoneNumber: '', - notificationSettingsFlags: false, - }, - voterPhotoQueuedToSave: '', - voterPhotoQueuedToSaveSet: false, - voterPhotoTooBig: false, - }; - } - - electionId () { - return this.getState().latestGoogleCivicElectionId || 0; - } - - resetState () { - return this.getInitialState(); - } - - getAddressObject () { - return this.getState().address || {}; - } - - getBallotLocationForVoter () { - // console.log('getBallotLocationForVoter this.getState().address:', this.getState().address); - if (this.getState().address) { - return { - text_for_map_search: this.getTextForMapSearch(), - ballot_returned_we_vote_id: this.getState().address.ballot_returned_we_vote_id, - polling_location_we_vote_id: '', - ballot_location_order: 0, - ballot_location_display_name: this.getState().address.ballot_location_display_name, - ballot_location_shortcut: '', - google_civic_election_id: this.getState().address.google_civic_election_id, - voter_entered_address: this.getState().address.voter_entered_address || false, // Did the voter save an address? - voter_specific_ballot_from_google_civic: this.getState().address.voter_specific_ballot_from_google_civic || false, // Did this ballot come back for this specific address? - }; - } - return null; - } - - getEmailAddressList () { - const { emailAddressList } = this.getState(); - return emailAddressList; - } - - getEmailAddressesVerifiedCount () { - const { emailAddressList } = this.getState(); - let oneEmail = {}; - let verifiedCount = 0; - for (let i = 0; i < emailAddressList.length; ++i) { - oneEmail = emailAddressList[i]; - if (oneEmail.email_ownership_is_verified === true) { - verifiedCount += 1; - } - } - return verifiedCount; - } - - getEmailAddressStatus () { - return this.getState().emailAddressStatus; - } - - getEmailSignInStatus () { - return this.getState().emailSignInStatus; - } - - getExternalVoterId () { - return this.getState().externalVoterId; - } - - getFacebookPhoto () { - return this.getState().voter.facebook_profile_image_url_https || ''; - } - - getFacebookSignInStatus () { - return this.getState().facebookSignInStatus; - } - - getFirstName () { - return this.getState().voter.first_name || ''; - } - - getFirstPlusLastName () { - const storedFirstName = this.getFirstName(); - const storedLastName = this.getLastName(); - let displayName = ''; - if (storedFirstName && String(storedFirstName) !== '') { - displayName = storedFirstName; - if (storedLastName && String(storedLastName) !== '') { - displayName += ' '; - } - } - if (storedLastName && String(storedLastName) !== '') { - displayName += storedLastName; - } - return displayName; - } - - getFullName () { - return this.getState().voter.full_name || ''; - } - - getLastName () { - return this.getState().voter.last_name || ''; - } - - getLinkedOrganizationWeVoteId () { - return this.getState().voter.linked_organization_we_vote_id || ''; - } - - getPrimaryEmailAddressDict () { - const { emailAddressList } = this.getState(); - let oneEmail = {}; - let primaryEmailAddress = {}; - for (let i = 0; i < emailAddressList.length; ++i) { - oneEmail = emailAddressList[i]; - // console.log('getPrimaryEmailAddressDict, oneEmail:', oneEmail); - if (oneEmail.primary_email_address === true && - oneEmail.email_permanent_bounce === false && - oneEmail.email_ownership_is_verified === true) { - primaryEmailAddress = oneEmail; - } - } - // console.log('getPrimaryEmailAddressDict, primaryEmailAddress:', primaryEmailAddress); - return primaryEmailAddress; - } - - getSecretCodeVerificationStatus () { - return this.getState().secretCodeVerificationStatus || {}; - } - - getSMSPhoneNumberStatus () { - return this.getState().smsPhoneNumberStatus; - } - - getSMSPhoneNumberList () { - const { smsPhoneNumberList } = this.getState(); - return smsPhoneNumberList; - } - - getSMSPhoneNumbersVerifiedCount () { - const { smsPhoneNumberList } = this.getState(); - let onePhoneNumber = {}; - let verifiedCount = 0; - for (let i = 0; i < smsPhoneNumberList.length; ++i) { - onePhoneNumber = smsPhoneNumberList[i]; - if (onePhoneNumber.sms_ownership_is_verified === true) { - verifiedCount += 1; - } - } - return verifiedCount; - } - - getStateCode () { - // This defaults to state_code_from_ip_address but is overridden by the address the voter defaults to, or enters in text_for_map_search - return this.getState().voter.state_code || ''; - } - - getStateCodeFromIPAddress () { - return this.getState().voter.state_code_from_ip_address || ''; - } - - getTextForMapSearch () { - let textForMapSearch = this.getState().address.text_for_map_search; - if (textForMapSearch === undefined) { - // Attaching full address object to voterRetrieve, so we can phase this out - textForMapSearch = this.getState().voter.text_for_map_search; - if (textForMapSearch === undefined) return ''; - } - if (Array.isArray(textForMapSearch)) return textForMapSearch[0] || ''; - return textForMapSearch; - } - - getTwitterHandle () { - return this.getState().voter.twitter_handle || ''; - } - - getTwitterSignInStatus () { - return this.getState().twitterSignInStatus || {}; - } - - getVoter () { - return this.getState().voter; - } - - getVoterContactEmailGoogleCount () { - return this.getState().voterContactEmailGoogleCount || 0; - } - - getVoterContactEmailList () { - return this.getState().voterContactEmailList || []; - } - - getVoterContactEmailListCount () { - const voterContactEmailList = this.getState().voterContactEmailList || []; - return voterContactEmailList.length; - } - - getVoterDeleted () { - return this.getState().voterDeleted || false; - } - - getVoterEmail () { - return this.getState().voter.email || ''; - } - - getVoterEmailQueuedToSave () { - return this.getState().voterEmailQueuedToSave; - } - - getVoterEmailQueuedToSaveSet () { - return this.getState().voterEmailQueuedToSaveSet; - } - - getVoterFirstName () { - if (this.getState().voter) { - return this.getState().voter.first_name || ''; - } - return ''; - } - - getVoterFirstNameQueuedToSave () { - return this.getState().voterFirstNameQueuedToSave; - } - - getVoterFirstNameQueuedToSaveSet () { - return this.getState().voterFirstNameQueuedToSaveSet; - } - - getVoterIsSignedIn () { - return this.getState().voter.is_signed_in || false; - } - - getVoterIsSignedInWithEmail () { - return this.getState().voter.signed_in_with_email || false; - } - - getVoterIsSignedInWithFacebook () { - return this.getState().voter.signed_in_facebook || false; - } - - getVoterIsSignedInWithTwitter () { - return this.getState().voter.signed_in_twitter || false; - } - - getVoterLastNameQueuedToSave () { - return this.getState().voterLastNameQueuedToSave; - } - - getVoterLastNameQueuedToSaveSet () { - return this.getState().voterLastNameQueuedToSaveSet; - } - - getVoterNotificationSettingsUpdateStatus () { - return this.getState().voterNotificationSettingsUpdateStatus || {}; - } - - getVoterPhotoQueuedToSave () { - return this.getState().voterPhotoQueuedToSave; - } - - getVoterPhotoQueuedToSaveSet () { - return this.getState().voterPhotoQueuedToSaveSet; - } - - getVoterPhotoTooBig () { - return this.getState().voterPhotoTooBig || false; - } - - // Could be either Facebook photo or Twitter photo - getVoterPhotoUrlLarge () { - return this.getState().voter.voter_photo_url_large || ''; - } - - // Could be either Facebook photo or Twitter photo - getVoterPhotoUrlMedium () { - return this.getState().voter.voter_photo_url_medium || ''; - } - - // Could be either Facebook photo or Twitter photo - getVoterPhotoUrlTiny () { - return this.getState().voter.voter_photo_url_tiny || ''; - } - - getVoterProfileUploadedImageUrlLarge () { - return this.getState().voter.we_vote_hosted_profile_uploaded_image_url_large || ''; - } - - getVoterSavedAddress () { - // console.log('VoterStore, getVoterSavedAddress: ', this.getState().address.voter_entered_address); - return this.getState().address.voter_entered_address || false; - } - - getVoterStateCode () { - // TODO in getVoterStateCode we check for normalized_state in the address object. We should be - // capturing the state when we call Google address Auto Complete (search for _placeChanged) - // and we should also figure out the state_code when we call API server voterAddressSave and put it in the "address" - // return data. - // console.log('this.getState().address:', this.getState().address); - // console.log('this.getState().voter:', this.getState().voter); - if (this.getState().address && this.getState().address.normalized_state) { - // console.log('normalized_state:', this.getState().address.normalized_state); - return this.getState().address.normalized_state; - } - if (this.getState().voter && this.getState().voter.state_code_from_ip_address) { - // console.log('state_code_from_ip_address:', this.getState().voter.state_code_from_ip_address); - return this.getState().voter.state_code_from_ip_address; - } - return ''; - } - - getVoterWeVoteId () { - return this.getState().voter.we_vote_id || ''; - } - - voterDeviceId () { - return this.getState().voter.voter_device_id || Cookies.get('voter_device_id'); - } - - setVoterDeviceIdCookie (id) { // eslint-disable-line - Cookies.remove('voter_device_id'); - Cookies.remove('voter_device_id', { path: '/' }); - Cookies.remove('voter_device_id', { path: '/', domain: 'wevote.us' }); - let { hostname } = window.location; - hostname = hostname || ''; - // console.log('setVoterDeviceIdCookie hostname:', hostname, 'cookie id:', id); - if (hostname && stringContains('wevote.us', hostname)) { - Cookies.set('voter_device_id', id, { expires: 10000, path: '/', domain: 'wevote.us' }); - } else { - Cookies.set('voter_device_id', id, { expires: 10000, path: '/' }); - } - } - - // Airbnb doesnt like bitwise operators in JavaScript - getInterfaceFlagState (flag) { - // Look in js/Constants/VoterConstants.js for list of flag constant definitions - // console.log('VoterStore getInterfaceFlagState flag: ', flag); - if (!this.getState().voter) { - return false; - } - - const interfaceStatusFlags = this.getState().voter.interface_status_flags || 0; - // console.log('VoterStore getInterfaceFlagState interfaceStatusFlags: ', interfaceStatusFlags); - // return True if bit specified by the flag is also set in interfaceStatusFlags (voter.interface_status_flags) - // Eg: if interfaceStatusFlags = 5, then we can confirm that bits representing 1 and 4 are set (i.e., 0101) - // so for value of flag = 1 and 4, we return a positive integer, - // but, the bit representing 2 and 8 are not set, so for flag = 2 and 8, we return zero - // const flagIsSet = interfaceStatusFlags & flag; // eslint-disable-line no-bitwise - // console.log('VoterStore getInterfaceFlagState flagIsSet: ', flagIsSet); - return interfaceStatusFlags & flag; // eslint-disable-line no-bitwise - } - - getNotificationSettingConstantFromUnsubscribeModifier (unsubscribeModifier) { - // New unsubscribe modifiers also need to be added in WeVoteServer - let notificationSettingConstant = 0; - // dailyfriendactivity, friendaccept, friendinvite, friendopinions, friendopinionsall, friendmessage, login, newsletter - // NOT IMPLEMENTED YET: suggestedfriend == NOTIFICATION_SUGGESTED_FRIENDS_EMAIL - if (unsubscribeModifier === 'dailyfriendactivity') { - notificationSettingConstant = VoterConstants.NOTIFICATION_VOTER_DAILY_SUMMARY_EMAIL; - } else if (unsubscribeModifier === 'friendaccept' || unsubscribeModifier === 'friendinvite') { - notificationSettingConstant = VoterConstants.NOTIFICATION_FRIEND_REQUESTS_EMAIL; // friendaccept: NOTIFICATION_FRIEND_REQUEST_RESPONSES_EMAIL - } else if (unsubscribeModifier === 'friendopinions' || unsubscribeModifier === 'friendopinionsall') { - notificationSettingConstant = VoterConstants.NOTIFICATION_FRIEND_OPINIONS_YOUR_BALLOT_EMAIL; // friendopinionsall: NOTIFICATION_FRIEND_OPINIONS_OTHER_REGIONS_EMAIL - } else if (unsubscribeModifier === 'friendmessage') { - notificationSettingConstant = VoterConstants.NOTIFICATION_FRIEND_MESSAGES_EMAIL; - } else if (unsubscribeModifier === 'login') { - notificationSettingConstant = VoterConstants.NOTIFICATION_LOGIN_EMAIL; - } else if (unsubscribeModifier === 'newsletter') { - notificationSettingConstant = VoterConstants.NOTIFICATION_NEWSLETTER_OPT_IN; - } - return notificationSettingConstant; - } - - getNotificationSettingsFlagState (flag) { - // Look in js/Constants/VoterConstants.js for list of flag constant definitions - if (!this.getState().voter) { - return false; - } - // Notification settings we haven't implemented yet which we show as still turned on - if ((flag === VoterConstants.NOTIFICATION_FRIEND_MESSAGES_EMAIL) || - (flag === VoterConstants.NOTIFICATION_FRIEND_OPINIONS_OTHER_REGIONS_EMAIL) || - (flag === VoterConstants.NOTIFICATION_LOGIN_EMAIL)) { - return true; - } - const notificationSettingsFlags = this.getState().voter.notification_settings_flags || 0; - // return True if bit specified by the flag is also set - // in notificationSettingsFlags (voter.notification_settings_flags) - // Eg: if interfaceStatusFlags = 5, then we can confirm that bits representing 1 and 4 are set (i.e., 0101) - // so for value of flag = 1 and 4, we return a positive integer, - // but, the bit representing 2 and 8 are not set, so for flag = 2 and 8, we return zero - return notificationSettingsFlags & flag; // eslint-disable-line no-bitwise - } - - getNotificationSettingsFlagStateFromSecretKey (flag) { - // Look in js/Constants/VoterConstants.js for list of flag constant definitions - if (!this.getState().voterNotificationSettingsUpdateStatus) { - return false; - } - // Notification settings we haven't implemented yet which we show as still turned on - if ((flag === VoterConstants.NOTIFICATION_FRIEND_MESSAGES_EMAIL) || - (flag === VoterConstants.NOTIFICATION_FRIEND_OPINIONS_OTHER_REGIONS_EMAIL) || - (flag === VoterConstants.NOTIFICATION_LOGIN_EMAIL)) { - return true; - } - const { notificationSettingsFlags } = this.getState().voterNotificationSettingsUpdateStatus; - // return True if bit specified by the flag is also set - // in notificationSettingsFlags (voter.notification_settings_flags) - // Eg: if interfaceStatusFlags = 5, then we can confirm that bits representing 1 and 4 are set (i.e., 0101) - // so for value of flag = 1 and 4, we return a positive integer, - // but, the bit representing 2 and 8 are not set, so for flag = 2 and 8, we return zero - return notificationSettingsFlags & flag; // eslint-disable-line no-bitwise - } - - getVoterContactEmailAugmentSequenceComplete () { - return this.getState().voterContactEmailAugmentSequenceComplete || false; - } - - getVoterContactEmailAugmentSequenceHasNextStep () { - return this.getState().voterContactEmailAugmentSequenceHasNextStep || false; - } // voterContactEmailAugmentWithWeVoteDataComplete - - getVoterContactEmailAugmentWithWeVoteDataComplete () { - return this.getState().voterContactEmailAugmentWithWeVoteDataComplete || false; - } - - isVoterFound () { - return this.getState().voterFound; - } - - voterFirstRetrieveCompleted () { - return this.getState().voterFirstRetrieveCompleted; - } - - voterExternalIdHasBeenSavedOnce (externalVoterId, membershipOrganizationWeVoteId) { - if (!externalVoterId || !membershipOrganizationWeVoteId) { - return false; - } - if (this.getState().voterExternalIdHasBeenSavedOnce[externalVoterId]) { - return this.getState().voterExternalIdHasBeenSavedOnce[externalVoterId][membershipOrganizationWeVoteId] || false; - } else { - return false; - } - } - - voterPhotoAndNameExist () { - const firstNameExists = !!(this.getState().voter.first_name && this.getState().voter.first_name !== ''); - const lastNameExists = !!(this.getState().voter.last_name && this.getState().voter.last_name !== ''); - const nameExists = firstNameExists || lastNameExists; - const photoExists = !!(this.getState().voter.voter_photo_url_large && this.getState().voter.voter_photo_url_large !== ''); - return !!(nameExists && photoExists); - } - - reduce (state, action) { - let facebookPhotoRetrieveLoopCount; - let address; - let currentVoterDeviceId; - // const delayBeforeApiCall = 3000; - let externalVoterId; - let googleCivicElectionId; - let incomingVoter; - let incorrectSecretCodeEntered; - let membershipOrganizationWeVoteId; - let mergeFromVoterWeVoteId; - let mergeToVoterWeVoteId; - let numberOfTriesRemaining; - let revisedState; - let secretCodeVerified; - let voterDeviceId; - let voterContactEmailAugmentWithWeVoteDataComplete; - let voterExternalIdHasBeenSavedOnce; - let voterFirstRetrieveCompleted; - let voterMustRequestNewCode; - let voterSecretCodeRequestsLocked; - - switch (action.type) { - case 'clearEmailAddressStatus': - // console.log('VoterStore clearEmailAddressStatus'); - return { ...state, emailAddressStatus: {} }; - case 'clearSecretCodeVerificationStatus': - // console.log('VoterStore clearSecretCodeVerificationStatus'); - return { - ...state, - secretCodeVerificationStatus: { - incorrectSecretCodeEntered: false, - numberOfTriesRemaining: 5, - secretCodeVerified: false, - voterMustRequestNewCode: false, - voterSecretCodeRequestsLocked: false, - }, - }; - case 'clearSecretCodeVerificationStatusAndEmail': - // Does both of the above steps in one call - // console.log('VoterStore clearSecretCodeVerificationStatusAndEmail'); - return { - ...state, - emailAddressStatus: {}, - secretCodeVerificationStatus: { - incorrectSecretCodeEntered: false, - numberOfTriesRemaining: 5, - secretCodeVerified: false, - voterMustRequestNewCode: false, - voterSecretCodeRequestsLocked: false, - }, - }; - case 'clearSMSPhoneNumberStatus': - // console.log('VoterStore clearSMSPhoneNumberStatus'); - return { - ...state, - smsPhoneNumberStatus: { - sms_verify_attempted: false, - sms_phone_number_already_owned_by_other_voter: false, - sms_phone_number_already_owned_by_this_voter: false, - sms_phone_number_created: false, - sms_phone_number: '', - sms_phone_number_found: false, - sms_phone_number_deleted: false, - make_primary_sms: false, - sign_in_code_sms_sent: false, - verification_sms_sent: false, - }, - }; - case 'clearSecretCodeVerificationStatusAndPhone': - // console.log('VoterStore clearSecretCodeVerificationStatusAndPhone'); - return { - ...state, - secretCodeVerificationStatus: { - incorrectSecretCodeEntered: false, - numberOfTriesRemaining: 5, - secretCodeVerified: false, - voterMustRequestNewCode: false, - voterSecretCodeRequestsLocked: false, - }, - smsPhoneNumberStatus: { - sms_verify_attempted: false, - sms_phone_number_already_owned_by_other_voter: false, - sms_phone_number_already_owned_by_this_voter: false, - sms_phone_number_created: false, - sms_phone_number: '', - sms_phone_number_found: false, - sms_phone_number_deleted: false, - make_primary_sms: false, - sign_in_code_sms_sent: false, - verification_sms_sent: false, - }, - }; - case 'clearVoterElectionId': - // console.log('VoterStore clearVoterElectionId'); - return { ...state, latestGoogleCivicElectionId: 0 }; - case 'clearVoterContactEmailImportVariables': - return { - ...state, - voterContactEmailAugmentWithWeVoteDataComplete: false, - voterContactEmailAugmentSequenceComplete: false, - voterContactEmailAugmentSequenceHasNextStep: false, - }; - case 'organizationSave': - // console.log('VoterStore organizationSave'); - // If an organization saves, we want to check to see if it is tied to this voter. If so, - // refresh the voter data so we have the value linked_organization_we_vote_id in the voter object. - if (action.res.success) { - if (action.res.facebook_id === state.voter.facebook_id) { - VoterActions.voterRetrieve(); - } else { - const organizationTwitterHandle = action.res.organization_twitter_handle || ''; - const twitterScreenName = state.voter.twitter_screen_name !== undefined ? state.voter.twitter_screen_name : ''; - if (organizationTwitterHandle && organizationTwitterHandle.toLowerCase() === twitterScreenName.toLowerCase()) { - VoterActions.voterRetrieve(); - } - } - } - return state; - - case 'positionListForVoter': - // console.log('VoterStore positionListForVoter'); - if (action.res.show_only_this_election) { - const positionListForOneElection = action.res.position_list; - return { - ...state, - voter: { - ...state.voter, - positionListForOneElection, - }, - }; - } else if (action.res.show_all_other_elections) { - const positionListForAllExceptOneElection = action.res.position_list; - return { - ...state, - voter: { - ...state.voter, - positionListForAllExceptOneElection, - }, - }; - } else { - const positionList = action.res.position_list; - return { - ...state, - voter: { - ...state.voter, - positionList, - }, - }; - } - - case 'setExternalVoterId': - externalVoterId = action.payload; - membershipOrganizationWeVoteId = AppObservableStore.getSiteOwnerOrganizationWeVoteId(); - ({ voterExternalIdHasBeenSavedOnce } = state); - // console.log('VoterStore externalVoterId:', externalVoterId, ', membershipOrganizationWeVoteId:', membershipOrganizationWeVoteId); - if (externalVoterId && membershipOrganizationWeVoteId) { - if (!this.voterExternalIdHasBeenSavedOnce(externalVoterId, membershipOrganizationWeVoteId)) { - // console.log('voterExternalIdHasBeenSavedOnce has NOT been saved before.'); - VoterActions.voterExternalIdSave(externalVoterId, membershipOrganizationWeVoteId); - if (!voterExternalIdHasBeenSavedOnce[externalVoterId]) { - voterExternalIdHasBeenSavedOnce[externalVoterId] = {}; - } - voterExternalIdHasBeenSavedOnce[externalVoterId][membershipOrganizationWeVoteId] = true; - // AnalyticsActions.saveActionBallotVisit(VoterStore.electionId()); - } else { - // console.log('voterExternalIdHasBeenSavedOnce has been saved before.'); - } - } - return { - ...state, - externalVoterId, - voterExternalIdHasBeenSavedOnce, - }; - - case 'twitterRetrieveIdsIFollow': - // console.log('VoterStore twitterRetrieveIdsIFollow'); - if (action.res.success) { - VoterActions.organizationSuggestionTasks('UPDATE_SUGGESTIONS_FROM_TWITTER_IDS_I_FOLLOW', - 'FOLLOW_SUGGESTIONS_FROM_TWITTER_IDS_I_FOLLOW'); - } - - return state; - - case 'voterAnalysisForJumpProcess': - // console.log('VoterStore, voterAnalysisForJumpProcess'); - VoterActions.voterRetrieve(); - return { - ...state, - emailAddressStatus: { - email_ownership_is_verified: action.res.email_ownership_is_verified, - email_secret_key_belongs_to_this_voter: action.res.email_secret_key_belongs_to_this_voter, - email_verify_attempted: action.res.email_verify_attempted, - email_address_found: action.res.email_address_found, - }, - emailSignInStatus: { - email_ownership_is_verified: action.res.email_ownership_is_verified, - email_secret_key_belongs_to_this_voter: action.res.email_secret_key_belongs_to_this_voter, - email_sign_in_attempted: action.res.email_verify_attempted, - email_address_found: action.res.email_address_found, - }, - }; - - case 'voterAddressRetrieve': - case 'voterAddressOnlyRetrieve': - // console.log('VoterStore, voterAddressRetrieve, address:', action.res); - address = action.res || {}; - return { - ...state, - address, - }; - - case 'voterAddressSave': - // console.log('VoterStore, voterAddressSave, action.res:', action.res); - revisedState = state; - if (action.res.status === 'SIMPLE_ADDRESS_SAVE') { - // Don't do any other refreshing - } else { - googleCivicElectionId = action.res.google_civic_election_id || 0; - if (googleCivicElectionId !== 0) { - revisedState = { ...revisedState, - latestGoogleCivicElectionId: googleCivicElectionId, - }; - } - } - ({ address } = action.res); - if (!address) { - address = { - text_for_map_search: '', - google_civic_election_id: 0, - ballot_returned_we_vote_id: '', - ballot_location_display_name: '', - voter_entered_address: '', - voter_specific_ballot_from_google_civic: null, - }; - } - - return { - ...revisedState, - address: { - text_for_map_search: address.text_for_map_search, - google_civic_election_id: address.google_civic_election_id, - ballot_returned_we_vote_id: address.ballot_returned_we_vote_id, - ballot_location_display_name: address.ballot_location_display_name, - voter_entered_address: address.voter_entered_address, - voter_specific_ballot_from_google_civic: address.voter_specific_ballot_from_google_civic, - }, - }; - - case 'voterBallotItemsRetrieve': - // console.log('VoterStore voterBallotItemsRetrieve latestGoogleCivicElectionId: ', action.res.google_civic_election_id); - googleCivicElectionId = action.res.google_civic_election_id || 0; - if (googleCivicElectionId !== 0) { - return { - ...state, - latestGoogleCivicElectionId: googleCivicElectionId, - }; - } - return state; - - case 'voterContactListRetrieve': - // console.log('VoterStore voterContactListRetrieve action:', action); - if (action.res.success) { - const { - voter_contact_email_google_count: voterContactEmailGoogleCount, - voter_contact_email_list: voterContactEmailList, - } = action.res; - return { - ...state, - voterContactEmailGoogleCount, - voterContactEmailList, - }; - } else { - console.log('response voterContactListRetrieve was not successful'); - return state; - } - - case 'voterContactListSave': - // console.log('VoterStore voterContactListSave action.res:', action.res); - if (action.res.success) { - ({ voterContactEmailAugmentWithWeVoteDataComplete } = state); - const { - augment_voter_contact_emails_with_location: justAugmentedWithLocation, - augment_voter_contact_emails_with_we_vote_data: justAugmentedWithWeVoteData, - contacts_stored: googleContactsStored, - delete_all_voter_contact_emails: voterContactEmailsJustDeleted, - voter_contact_email_augment_sequence_complete: voterContactEmailAugmentSequenceComplete, - voter_contact_email_augment_sequence_has_next_step: voterContactEmailAugmentSequenceHasNextStep, - voter_contact_email_google_count: voterContactEmailGoogleCount, - voter_contact_email_list: voterContactEmailList, - we_vote_id_for_google_contacts: weVoteIdForGoogleContacts, - } = action.res; - // console.log('googleContactsStored:', googleContactsStored, ', justAugmentedWithWeVoteData:', justAugmentedWithWeVoteData, ',justAugmentedWithLocation:', justAugmentedWithLocation); - if (voterContactEmailsJustDeleted || justAugmentedWithLocation) { - // Never call again - } else if (googleContactsStored && (googleContactsStored > 0)) { - // console.log('Calling VoterActions.voterContactListAugmentWithWeVoteData'); - VoterActions.voterContactListAugmentWithWeVoteData(true); - } else if (justAugmentedWithWeVoteData) { - // console.log('Calling VoterActions.voterContactListAugmentWithLocation'); - VoterActions.voterContactListAugmentWithLocation(true); - } - if (googleContactsStored) { - voterContactEmailAugmentWithWeVoteDataComplete = false; - } else if (justAugmentedWithWeVoteData) { - voterContactEmailAugmentWithWeVoteDataComplete = true; - } - return { - ...state, - weVoteIdForGoogleContacts, - googleContactsStored, - voterContactEmailAugmentWithWeVoteDataComplete, - voterContactEmailAugmentSequenceComplete, - voterContactEmailAugmentSequenceHasNextStep, - voterContactEmailGoogleCount, - voterContactEmailList, - }; - } else { - console.log('response voterContactListSave was not successful'); - return state; - } - - case 'voterEmailAddressRetrieve': - // console.log('VoterStore voterEmailAddressRetrieve: ', action.res.email_address_list); - return { - ...state, - emailAddressList: action.res.email_address_list, - }; - - case 'voterEmailAddressSave': - // console.log('VoterStore, voterEmailAddressSave'); - VoterActions.voterRetrieve(); - return { - ...state, - emailAddressList: action.res.email_address_list, - emailAddressStatus: { - email_verify_attempted: action.res.email_verify_attempted, - email_address_already_owned_by_other_voter: action.res.email_address_already_owned_by_other_voter, - email_address_already_owned_by_this_voter: action.res.email_address_already_owned_by_this_voter, - email_address_created: action.res.email_address_created, - email_address_deleted: action.res.email_address_deleted, - email_address_not_valid: action.res.email_address_not_valid, - from_voter_we_vote_id: action.res.from_voter_we_vote_id, - link_to_sign_in_email_sent: action.res.link_to_sign_in_email_sent, - make_primary_email: action.res.make_primary_email, - sign_in_code_email_sent: action.res.sign_in_code_email_sent, - secret_code_system_locked_for_this_voter_device_id: action.res.secret_code_system_locked_for_this_voter_device_id, - to_voter_we_vote_id: action.res.to_voter_we_vote_id, - verification_email_sent: action.res.verification_email_sent, - }, - }; - - case 'voterEmailAddressSignIn': - // console.log('VoterStore, voterEmailAddressSignIn'); - VoterActions.voterRetrieve(); - return { - ...state, - emailSignInStatus: { - email_sign_in_attempted: action.res.email_sign_in_attempted, - email_ownership_is_verified: action.res.email_ownership_is_verified, - email_secret_key_belongs_to_this_voter: action.res.email_secret_key_belongs_to_this_voter, - email_address_found: action.res.email_address_found, - yes_please_merge_accounts: action.res.yes_please_merge_accounts, - voter_we_vote_id_from_secret_key: action.res.voter_we_vote_id_from_secret_key, - voter_merge_two_accounts_attempted: false, - }, - }; - - case 'voterEmailAddressVerify': - // console.log('VoterStore, voterEmailAddressVerify'); - VoterActions.voterRetrieve(); - return { - ...state, - emailAddressStatus: { - email_ownership_is_verified: action.res.email_ownership_is_verified, - email_secret_key_belongs_to_this_voter: action.res.email_secret_key_belongs_to_this_voter, - email_verify_attempted: action.res.email_verify_attempted, - email_address_found: action.res.email_address_found, - }, - emailSignInStatus: { - email_ownership_is_verified: action.res.email_ownership_is_verified, - email_secret_key_belongs_to_this_voter: action.res.email_secret_key_belongs_to_this_voter, - email_sign_in_attempted: action.res.email_verify_attempted, - email_address_found: action.res.email_address_found, - }, - }; - - case 'voterEmailQueuedToSave': - // console.log('VoterStore voterEmailQueuedToSave: ', action.payload); - if (action.payload === undefined) { - return { - ...state, - voterEmailQueuedToSave: '', - voterEmailQueuedToSaveSet: false, - }; - } else { - return { - ...state, - voterEmailQueuedToSave: action.payload, - voterEmailQueuedToSaveSet: true, - }; - } - - case 'voterFacebookSaveToCurrentAccount': - // console.log('VoterStore, voterFacebookSaveToCurrentAccount'); - VoterActions.voterRetrieve(); - return { - ...state, - facebookSignInStatus: { - facebook_account_created: action.res.facebook_account_created, - }, - }; - - case 'voterFirstNameQueuedToSave': - // console.log('VoterStore voterFirstNameQueuedToSave: ', action.payload); - if (action.payload === undefined) { - return { - ...state, - voterFirstNameQueuedToSave: '', - voterFirstNameQueuedToSaveSet: false, - }; - } else { - return { - ...state, - voterFirstNameQueuedToSave: action.payload, - voterFirstNameQueuedToSaveSet: true, - }; - } - - case 'voterLastNameQueuedToSave': - // console.log('VoterStore voterLastNameQueuedToSave: ', action.payload); - if (action.payload === undefined) { - return { - ...state, - voterLastNameQueuedToSave: '', - voterLastNameQueuedToSaveSet: false, - }; - } else { - return { - ...state, - voterLastNameQueuedToSave: action.payload, - voterLastNameQueuedToSaveSet: true, - }; - } - - case 'voterMergeTwoAccounts': - // console.log('VoterStore, voterMergeTwoAccounts'); - // On the server we just switched (linked) this voterDeviceId to a new voter record, so we want to the voter. - // refresh a lot of data -- December 2022, but as little as absolutely required, and no more - VoterActions.voterRetrieve(); - // // And set a timer for 3 seconds from now to refresh again - // this.timer = setTimeout(() => { - // VoterActions.voterRetrieve(); - // }, delayBeforeApiCall); - VoterActions.voterEmailAddressRetrieve(); // TODO: December 2022, Is this necessary? - VoterActions.voterSMSPhoneNumberRetrieve(); // TODO: December 2022, Is this necessary? - if (action.res.merge_from_voter_we_vote_id && action.res.merge_to_voter_we_vote_id) { - if (apiCalming('voterRetrieveMergeTwo', 3000)) { - // This completes the time-consuming process 'voter_merge_two_accounts_action' and then returns voter data - console.log('VoterStore: voterMergeTwoAccounts: Completing voterRetrieveMergeTwo process'); - VoterActions.voterRetrieve(action.res.merge_from_voter_we_vote_id, action.res.merge_to_voter_we_vote_id); - } - } - return { - ...state, - emailSignInStatus: { - email_ownership_is_verified: true, - email_secret_key_belongs_to_this_voter: true, - email_sign_in_attempted: true, - email_address_found: true, - yes_please_merge_accounts: false, - voter_we_vote_id_from_secret_key: '', - voter_merge_two_accounts_attempted: true, - }, - facebookSignInStatus: { - voter_merge_two_accounts_attempted: true, - }, - twitterSignInStatus: { - voter_merge_two_accounts_attempted: true, - }, - }; - - case 'voterNotificationSettingsUpdate': - // console.log('VoterStore, voterNotificationSettingsUpdate'); - if (!action.res) { - return { - ...state, - voterNotificationSettingsUpdateStatus: { - apiResponseReceived: true, - emailFound: false, - voterFound: false, - normalizedEmailAddress: '', - normalizedSmsPhoneNumber: '', - notificationSettingsFlags: false, - }, - }; - } - return { - ...state, - voterNotificationSettingsUpdateStatus: { - apiResponseReceived: true, - emailFound: action.res.email_found, - voterFound: action.res.voter_found, - normalizedEmailAddress: action.res.normalized_email_address, - normalizedSmsPhoneNumber: action.res.normalized_sms_phone_number, - notificationSettingsFlags: action.res.notification_settings_flags, - }, - }; - - case 'voterPhotoQueuedToSave': - // console.log('VoterStore voterPhotoQueuedToSave: ', action.payload); - if (action.payload === undefined) { - return { - ...state, - voterPhotoQueuedToSave: '', - voterPhotoQueuedToSaveSet: false, - }; - } else { - return { - ...state, - voterPhotoQueuedToSave: action.payload, - voterPhotoQueuedToSaveSet: true, - }; - } - - case 'voterPhotoSave': - // console.log('VoterStore, voterPhotoSave'); - return { - ...state, - voter: { ...state.voter, facebook_profile_image_url_https: action.res.facebook_profile_image_url_https }, - }; - - case 'voterPhotoTooBigReset': - // console.log('VoterStore, voterPhotoTooBigReset'); - return { - ...state, - voterPhotoTooBig: false, - }; - - case 'voterRetrieve': - // console.log('VoterStore, voterRetrieve state on entry: ', state); - // console.log('VoterStore, voterRetrieve state on entry: ', state.voter); - - // Preserve address within voter - incomingVoter = action.res; - ({ facebookPhotoRetrieveLoopCount, voterFirstRetrieveCompleted } = state); - if (!voterFirstRetrieveCompleted) { - voterFirstRetrieveCompleted = Boolean(action.res.success); - } - - currentVoterDeviceId = Cookies.get('voter_device_id'); - // console.log('VoterStore, voterRetrieve stored Cookie value for voter_device_id value on entry: ', currentVoterDeviceId); - if (!action.res.voter_found) { - console.log(`This voter_device_id is not in the db and is invalid, so delete it: ${currentVoterDeviceId}`); - - // Attempt to delete the voter_device_id cookie in a variety of ways - Cookies.remove('voter_device_id'); - Cookies.remove('voter_device_id', { path: '/' }); - Cookies.remove('voter_device_id', { path: '/', domain: 'wevote.us' }); - - // ...and then ask for a new voter. When it returns a voter with a new voter_device_id, we will set new cookie - if (!Cookies.get('voter_device_id')) { - console.log('voter_device_id gone -- calling voterRetrieve'); - VoterActions.voterRetrieve(); - } else { - // console.log('voter_device_id still exists -- did not call voterRetrieve'); - } - } else { - voterDeviceId = action.res.voter_device_id; - if (voterDeviceId) { - if (currentVoterDeviceId !== voterDeviceId) { - console.log('Setting new voter_device_id'); - this.setVoterDeviceIdCookie(voterDeviceId); - } - // FriendsInvitationList.jsx is choking on this because calling this - // results in an infinite loop cycling between voterRetrieve and getFaceProfilePicture which - // resolves to FACEBOOK_RECEIVED_PICTURE which then attempts to save using voterFacebookSignInPhoto - // which in turn resolves to voterFacebookSignInSave which finally attempts to call - // voterRetrieve again - // console.log('VoterStore, voterRetrieve, action.res: ', action.res); - } else { - // console.log('voter_device_id not returned by voterRetrieve'); - } - } - // April 29, 2021 TODO: We should make a combined Voter and Organization retrieve - // because this fires on the initial page load and takes almost a full second to return, blocking one of six available http channels - // Firing actions from stores should be avoided - // The following (new) condition blocks a organizationRetrieve on the first voterRetrieve - - // if (incomingVoter.signed_in_with_apple) { - // // Completing the logical OR that can't be conveniently made in the server, since Sign in with Apple is device_id specific - // incomingVoter.is_signed_in = incomingVoter.signed_in_with_apple; - // const { voter_photo_url_medium: statePhotoMed } = state.voter; - // const { voter_photo_url_medium: incomingPhotoMed } = incomingVoter; - // if (!statePhotoMed && !incomingPhotoMed) { - // incomingVoter.voter_photo_url_medium = 'https://wevote.us/img/global/logos/Apple_logo_grey.svg'; // TODO: Switch over to wevote.us once live server is updated - // } - // } - if (incomingVoter && incomingVoter.we_vote_id) { - if (incomingVoter.we_vote_id !== AppObservableStore.getOpenReplayVoterWeVoteId()) { - // console.log('tracker.setUserId:', incomingVoter.we_vote_id); - const tracker = AppObservableStore.getOpenReplayTracker(); - if (tracker) { - console.log('OpenReplay setting id: ', incomingVoter.we_vote_id); - AppObservableStore.setOpenReplayVoterWeVoteId(incomingVoter.we_vote_id); - tracker.setUserID(incomingVoter.we_vote_id); - } - } - if (incomingVoter.is_signed_in && !AppObservableStore.getOpenReplayVoterIsSignedIn()) { - const tracker = AppObservableStore.getOpenReplayTracker(); - if (tracker) { - console.log('OpenReplay setting voterIsSignedIn'); - AppObservableStore.setOpenReplayVoterIsSignedIn(true); - tracker.setMetadata('voterIsSignedIn', 'true'); - } - } - if (this.getStateCode() && !AppObservableStore.getOpenReplayStateCode()) { - // getStateCode defaults to state_code_from_ip_address but is overridden by the state in text_for_map_search - const tracker = AppObservableStore.getOpenReplayTracker(); - const stateCode = this.getStateCode().toUpperCase(); - if (tracker && stateCode) { - console.log('OpenReplay setting stateCode'); - AppObservableStore.setOpenReplayStateCode(stateCode); - tracker.setMetadata('stateCode', stateCode); - } - } - if (incomingVoter.state_code_from_ip_address && !AppObservableStore.getOpenReplayStateCodeFromIpAddress()) { - const tracker = AppObservableStore.getOpenReplayTracker(); - const stateCodeFromIpAddress = incomingVoter.state_code_from_ip_address.toUpperCase(); - if (tracker && stateCodeFromIpAddress) { - console.log('OpenReplay setting stateCodeFromIpAddress'); - AppObservableStore.setOpenReplayStateCodeFromIpAddress(stateCodeFromIpAddress); - tracker.setMetadata('stateCodeFromIpAddress', stateCodeFromIpAddress); - } - } - } - revisedState = state; - revisedState = { - ...revisedState, - facebookPhotoRetrieveLoopCount: facebookPhotoRetrieveLoopCount + 1, - voter: incomingVoter, - voterFirstRetrieveCompleted, - voterFound: action.res.voter_found, - }; - if (incomingVoter.address) { - // console.log('incomingVoter.address:', incomingVoter.address); - revisedState = { ...revisedState, address: incomingVoter.address }; - } - return revisedState; - - case 'voterSignOut': - // console.log('VoterStore resetting voterStore via voterSignOut'); - VoterActions.voterRetrieve(); - VoterActions.voterEmailAddressRetrieve(); - VoterActions.voterSMSPhoneNumberRetrieve(); - revisedState = state; - revisedState = { ...revisedState, ...this.getInitialState() }; - return revisedState; - - case 'voterSMSPhoneNumberRetrieve': - // console.log('VoterStore voterSMSPhoneNumberRetrieve: ', action.res.sms_phone_number_list); - return { - ...state, - smsPhoneNumberList: action.res.sms_phone_number_list, - }; - - case 'voterSMSPhoneNumberSave': - // console.log('VoterStore voterSMSPhoneNumberSave action.res:', action.res); - VoterActions.voterRetrieve(); - VoterActions.voterSMSPhoneNumberRetrieve(); - return { - ...state, - smsPhoneNumberList: action.res.sms_phone_number_list, - smsPhoneNumberStatus: { - sms_verify_attempted: action.res.sms_verify_attempted, - sms_phone_number_already_owned_by_other_voter: action.res.sms_phone_number_already_owned_by_other_voter, - sms_phone_number_already_owned_by_this_voter: action.res.sms_phone_number_already_owned_by_this_voter, - sms_phone_number_created: action.res.sms_phone_number_created, - sms_phone_number: action.res.sms_phone_number, - sms_phone_number_found: action.res.sms_phone_number_found, - sms_phone_number_deleted: action.res.sms_phone_number_deleted, - make_primary_sms: action.res.make_primary_sms, - secret_code_system_locked_for_this_voter_device_id: action.res.secret_code_system_locked_for_this_voter_device_id, - sign_in_code_sms_sent: action.res.sign_in_code_sms_sent, - verification_sms_sent: action.res.verification_sms_sent, - }, - }; - - case 'voterSplitIntoTwoAccounts': - // console.log('VoterStore voterSplitIntoTwoAccounts '); - VoterActions.voterRetrieve(); - return state; - - case 'voterTwitterSaveToCurrentAccount': - // console.log('VoterStore voterTwitterSaveToCurrentAccount '); - VoterActions.voterRetrieve(); - return { - ...state, - twitterSignInStatus: { - twitter_account_created: action.res.twitter_account_created, - }, - }; - - case 'voterUpdate': // Formerly voterDeleteAccount - if (action.res.success && action.res.voter_deleted) { - revisedState = state; - revisedState = { ...revisedState, - voterDeleted: true, - voterNotDeleted: false, - }; - return revisedState; - } else if (action.res.success && action.res.voter_not_deleted) { - revisedState = state; - revisedState = { ...revisedState, - voterDeleted: false, - voterNotDeleted: true, - }; - return revisedState; - } else if (action.res.success) { - let interfaceStatusFlags = action.res.interface_status_flags; - if (interfaceStatusFlags === undefined) { - interfaceStatusFlags = state.voter.interface_status_flags; - } - let notificationSettingsFlags = action.res.notification_settings_flags; - if (notificationSettingsFlags === undefined) { - notificationSettingsFlags = state.voter.notification_settings_flags; - } - return { - ...state, - voter: { - ...state.voter, - // With this we are only updating the values we change with a voterUpdate call. - facebook_email: action.res.email || state.voter.email, - first_name: action.res.first_name, - interface_status_flags: interfaceStatusFlags, - last_name: action.res.last_name, - notification_settings_flags: notificationSettingsFlags, - profile_image_type_currently_active: action.res.profile_image_type_currently_active || '', - voter_donation_history_list: action.res.voter_donation_history_list || state.voter.voter_donation_history_list, - voter_photo_url_large: action.res.we_vote_hosted_profile_image_url_large || '', - voter_photo_url_medium: action.res.we_vote_hosted_profile_image_url_medium || '', - voter_photo_url_tiny: action.res.we_vote_hosted_profile_image_url_tiny || '', - we_vote_hosted_profile_facebook_image_url_large: action.res.we_vote_hosted_profile_facebook_image_url_large || '', - we_vote_hosted_profile_twitter_image_url_large: action.res.we_vote_hosted_profile_twitter_image_url_large || '', - we_vote_hosted_profile_uploaded_image_url_large: action.res.we_vote_hosted_profile_uploaded_image_url_large || '', - }, - voterPhotoTooBig: action.res.voter_photo_too_big || false, - }; - } else { - return { - ...state, - voterPhotoTooBig: action.res.voter_photo_too_big || false, - }; - } - - case 'voterVerifySecretCode': - // console.log('VoterStore, voterVerifySecretCode, action.res:', action.res); - incorrectSecretCodeEntered = (action.res.incorrect_secret_code_entered && action.res.incorrect_secret_code_entered === true); - mergeFromVoterWeVoteId = action.res.merge_from_voter_we_vote_id; - mergeToVoterWeVoteId = action.res.merge_to_voter_we_vote_id; - numberOfTriesRemaining = action.res.number_of_tries_remaining_for_this_code; - secretCodeVerified = (action.res.secret_code_verified && action.res.secret_code_verified === true); - voterMustRequestNewCode = (action.res.voter_must_request_new_code && action.res.voter_must_request_new_code === true); - voterSecretCodeRequestsLocked = (action.res.secret_code_system_locked_for_this_voter_device_id && action.res.secret_code_system_locked_for_this_voter_device_id === true); - // console.log('onVoterStoreChange voterStore secretCodeVerified', secretCodeVerified); - // It is appropriate to keep this call within the Store because the components which trigger the voterVerifySecretCode - // get closed as soon as secretCodeVerified is true - if (mergeFromVoterWeVoteId && mergeToVoterWeVoteId) { - // console.log('VoterStore, voterVerifySecretCode: voterRetrieveMergeTwo mergeFromVoterWeVoteId:', mergeFromVoterWeVoteId, ', mergeToVoterWeVoteId:', mergeToVoterWeVoteId); - if (apiCalming('voterRetrieveMergeTwo', 3000)) { - // This completes the time-consuming process 'voter_merge_two_accounts_action' and then returns voter data - VoterActions.voterRetrieve(mergeFromVoterWeVoteId, mergeToVoterWeVoteId); - } - } - return { - ...state, - secretCodeVerificationStatus: { - incorrectSecretCodeEntered, - numberOfTriesRemaining, - secretCodeVerified, - voterMustRequestNewCode, - voterSecretCodeRequestsLocked, - }, - }; - - case 'appleSignInSave': - if (action.res.success) { - // eslint-disable-next-line camelcase - const { first_name, middle_name, last_name, email, user_code: appleUserCode } = action.res; - VoterActions.voterRetrieve(); - return { - ...state, - voter: { - first_name, - middle_name, - last_name, - email, - appleUserCode, - signed_in_with_apple: true, - }, - }; - } else { - console.log('Received a bad response from appleSignInSave API call'); - return state; - } - - case 'deviceStoreFirebaseCloudMessagingToken': - if (action.res.success) { - // console.log('Received success from deviceStoreFirebaseCloudMessagingToken API call'); - return state; - } else { - console.log('Received a bad response from deviceStoreFirebaseCloudMessagingToken API call, object properties follow:'); - dumpObjProps('action.res', action.res); - return state; - } - - - case 'error-voterRetrieve' || 'error-voterAddressRetrieve' || 'error-voterAddressSave': - // console.log('VoterStore action', action); - return state; - - default: - return state; - } - } -} - -export default new VoterStore(Dispatcher); +// import { ReduceStore } from 'flux/utils'; +// import VoterActions from '../actions/VoterActions'; // eslint-disable-line import/no-cycle +// import Dispatcher from '../common/dispatcher/Dispatcher'; +// import AppObservableStore from './AppObservableStore'; // eslint-disable-line import/no-cycle +// import apiCalming from '../common/utils/apiCalming'; +// import Cookies from '../common/utils/js-cookie/Cookies'; +// import stringContains from '../common/utils/stringContains'; +// import VoterConstants from '../constants/VoterConstants'; +// import { dumpObjProps } from '../utils/appleSiliconUtils'; +// +// class VoterStore extends ReduceStore { +// getInitialState () { +// return { +// voter: { +// interface_status_flags: 0, +// state_code_from_ip_address: '', +// }, +// address: {}, +// emailAddressStatus: {}, +// emailSignInStatus: {}, +// emailAddressList: [], +// externalVoterId: '', +// facebookSignInStatus: {}, +// facebookPhotoRetrieveLoopCount: 0, +// latestGoogleCivicElectionId: 0, +// secretCodeVerificationStatus: { +// incorrectSecretCodeEntered: false, +// numberOfTriesRemaining: 5, +// secretCodeVerified: false, +// voterMustRequestNewCode: false, +// voterSecretCodeRequestsLocked: false, +// }, +// smsPhoneNumberStatus: { +// sms_verify_attempted: false, +// sms_phone_number_already_owned_by_other_voter: false, +// sms_phone_number_already_owned_by_this_voter: false, +// sms_phone_number_created: false, +// sms_phone_number: '', +// sms_phone_number_found: false, +// sms_phone_number_deleted: false, +// make_primary_sms: false, +// sign_in_code_sms_sent: false, +// verification_sms_sent: false, +// }, +// smsPhoneNumberList: [], +// voterContactEmailGoogleCount: 0, +// voterContactEmailList: [], +// voterDeleted: false, +// voterEmailQueuedToSave: '', +// voterEmailQueuedToSaveSet: false, +// voterFirstNameQueuedToSave: '', +// voterFirstNameQueuedToSaveSet: false, +// voterFirstRetrieveCompleted: false, // Has the first retrieve of the voter completed? +// voterFound: false, +// voterExternalIdHasBeenSavedOnce: {}, // Dict with externalVoterId and membershipOrganizationWeVoteId as keys, and true/false as value +// voterLastNameQueuedToSave: '', +// voterLastNameQueuedToSaveSet: false, +// voterNotificationSettingsUpdateStatus: { +// apiResponseReceived: false, +// emailFound: false, +// voterFound: false, +// normalizedEmailAddress: '', +// normalizedSmsPhoneNumber: '', +// notificationSettingsFlags: false, +// }, +// voterPhotoQueuedToSave: '', +// voterPhotoQueuedToSaveSet: false, +// voterPhotoTooBig: false, +// }; +// } +// +// electionId () { +// return this.getState().latestGoogleCivicElectionId || 0; +// } +// +// resetState () { +// return this.getInitialState(); +// } +// +// getAddressObject () { +// return this.getState().address || {}; +// } +// +// getBallotLocationForVoter () { +// // console.log('getBallotLocationForVoter this.getState().address:', this.getState().address); +// if (this.getState().address) { +// return { +// text_for_map_search: this.getTextForMapSearch(), +// ballot_returned_we_vote_id: this.getState().address.ballot_returned_we_vote_id, +// polling_location_we_vote_id: '', +// ballot_location_order: 0, +// ballot_location_display_name: this.getState().address.ballot_location_display_name, +// ballot_location_shortcut: '', +// google_civic_election_id: this.getState().address.google_civic_election_id, +// voter_entered_address: this.getState().address.voter_entered_address || false, // Did the voter save an address? +// voter_specific_ballot_from_google_civic: this.getState().address.voter_specific_ballot_from_google_civic || false, // Did this ballot come back for this specific address? +// }; +// } +// return null; +// } +// +// getEmailAddressList () { +// const { emailAddressList } = this.getState(); +// return emailAddressList; +// } +// +// getEmailAddressesVerifiedCount () { +// const { emailAddressList } = this.getState(); +// let oneEmail = {}; +// let verifiedCount = 0; +// for (let i = 0; i < emailAddressList.length; ++i) { +// oneEmail = emailAddressList[i]; +// if (oneEmail.email_ownership_is_verified === true) { +// verifiedCount += 1; +// } +// } +// return verifiedCount; +// } +// +// getEmailAddressStatus () { +// return this.getState().emailAddressStatus; +// } +// +// getEmailSignInStatus () { +// return this.getState().emailSignInStatus; +// } +// +// getExternalVoterId () { +// return this.getState().externalVoterId; +// } +// +// getFacebookPhoto () { +// return this.getState().voter.facebook_profile_image_url_https || ''; +// } +// +// getFacebookSignInStatus () { +// return this.getState().facebookSignInStatus; +// } +// +// getFirstName () { +// return this.getState().voter.first_name || ''; +// } +// +// getFirstPlusLastName () { +// const storedFirstName = this.getFirstName(); +// const storedLastName = this.getLastName(); +// let displayName = ''; +// if (storedFirstName && String(storedFirstName) !== '') { +// displayName = storedFirstName; +// if (storedLastName && String(storedLastName) !== '') { +// displayName += ' '; +// } +// } +// if (storedLastName && String(storedLastName) !== '') { +// displayName += storedLastName; +// } +// return displayName; +// } +// +// getFullName () { +// return this.getState().voter.full_name || ''; +// } +// +// getLastName () { +// return this.getState().voter.last_name || ''; +// } +// +// getLinkedOrganizationWeVoteId () { +// return this.getState().voter.linked_organization_we_vote_id || ''; +// } +// +// getPrimaryEmailAddressDict () { +// const { emailAddressList } = this.getState(); +// let oneEmail = {}; +// let primaryEmailAddress = {}; +// for (let i = 0; i < emailAddressList.length; ++i) { +// oneEmail = emailAddressList[i]; +// // console.log('getPrimaryEmailAddressDict, oneEmail:', oneEmail); +// if (oneEmail.primary_email_address === true && +// oneEmail.email_permanent_bounce === false && +// oneEmail.email_ownership_is_verified === true) { +// primaryEmailAddress = oneEmail; +// } +// } +// // console.log('getPrimaryEmailAddressDict, primaryEmailAddress:', primaryEmailAddress); +// return primaryEmailAddress; +// } +// +// getSecretCodeVerificationStatus () { +// return this.getState().secretCodeVerificationStatus || {}; +// } +// +// getSMSPhoneNumberStatus () { +// return this.getState().smsPhoneNumberStatus; +// } +// +// getSMSPhoneNumberList () { +// const { smsPhoneNumberList } = this.getState(); +// return smsPhoneNumberList; +// } +// +// getSMSPhoneNumbersVerifiedCount () { +// const { smsPhoneNumberList } = this.getState(); +// let onePhoneNumber = {}; +// let verifiedCount = 0; +// for (let i = 0; i < smsPhoneNumberList.length; ++i) { +// onePhoneNumber = smsPhoneNumberList[i]; +// if (onePhoneNumber.sms_ownership_is_verified === true) { +// verifiedCount += 1; +// } +// } +// return verifiedCount; +// } +// +// getStateCode () { +// // This defaults to state_code_from_ip_address but is overridden by the address the voter defaults to, or enters in text_for_map_search +// return this.getState().voter.state_code || ''; +// } +// +// getStateCodeFromIPAddress () { +// return this.getState().voter.state_code_from_ip_address || ''; +// } +// +// getTextForMapSearch () { +// let textForMapSearch = this.getState().address.text_for_map_search; +// if (textForMapSearch === undefined) { +// // Attaching full address object to voterRetrieve, so we can phase this out +// textForMapSearch = this.getState().voter.text_for_map_search; +// if (textForMapSearch === undefined) return ''; +// } +// if (Array.isArray(textForMapSearch)) return textForMapSearch[0] || ''; +// return textForMapSearch; +// } +// +// getTwitterHandle () { +// return this.getState().voter.twitter_handle || ''; +// } +// +// getTwitterSignInStatus () { +// return this.getState().twitterSignInStatus || {}; +// } +// +// getVoter () { +// return this.getState().voter; +// } +// +// getVoterContactEmailGoogleCount () { +// return this.getState().voterContactEmailGoogleCount || 0; +// } +// +// getVoterContactEmailList () { +// return this.getState().voterContactEmailList || []; +// } +// +// getVoterContactEmailListCount () { +// const voterContactEmailList = this.getState().voterContactEmailList || []; +// return voterContactEmailList.length; +// } +// +// getVoterDeleted () { +// return this.getState().voterDeleted || false; +// } +// +// getVoterEmail () { +// return this.getState().voter.email || ''; +// } +// +// getVoterEmailQueuedToSave () { +// return this.getState().voterEmailQueuedToSave; +// } +// +// getVoterEmailQueuedToSaveSet () { +// return this.getState().voterEmailQueuedToSaveSet; +// } +// +// getVoterFirstName () { +// if (this.getState().voter) { +// return this.getState().voter.first_name || ''; +// } +// return ''; +// } +// +// getVoterFirstNameQueuedToSave () { +// return this.getState().voterFirstNameQueuedToSave; +// } +// +// getVoterFirstNameQueuedToSaveSet () { +// return this.getState().voterFirstNameQueuedToSaveSet; +// } +// +// getVoterIsSignedIn () { +// return this.getState().voter.is_signed_in || false; +// } +// +// getVoterIsSignedInWithEmail () { +// return this.getState().voter.signed_in_with_email || false; +// } +// +// getVoterIsSignedInWithFacebook () { +// return this.getState().voter.signed_in_facebook || false; +// } +// +// getVoterIsSignedInWithTwitter () { +// return this.getState().voter.signed_in_twitter || false; +// } +// +// getVoterLastNameQueuedToSave () { +// return this.getState().voterLastNameQueuedToSave; +// } +// +// getVoterLastNameQueuedToSaveSet () { +// return this.getState().voterLastNameQueuedToSaveSet; +// } +// +// getVoterNotificationSettingsUpdateStatus () { +// return this.getState().voterNotificationSettingsUpdateStatus || {}; +// } +// +// getVoterPhotoQueuedToSave () { +// return this.getState().voterPhotoQueuedToSave; +// } +// +// getVoterPhotoQueuedToSaveSet () { +// return this.getState().voterPhotoQueuedToSaveSet; +// } +// +// getVoterPhotoTooBig () { +// return this.getState().voterPhotoTooBig || false; +// } +// +// // Could be either Facebook photo or Twitter photo +// getVoterPhotoUrlLarge () { +// return this.getState().voter.voter_photo_url_large || ''; +// } +// +// // Could be either Facebook photo or Twitter photo +// getVoterPhotoUrlMedium () { +// return this.getState().voter.voter_photo_url_medium || ''; +// } +// +// // Could be either Facebook photo or Twitter photo +// getVoterPhotoUrlTiny () { +// return this.getState().voter.voter_photo_url_tiny || ''; +// } +// +// getVoterProfileUploadedImageUrlLarge () { +// return this.getState().voter.we_vote_hosted_profile_uploaded_image_url_large || ''; +// } +// +// getVoterSavedAddress () { +// // console.log('VoterStore, getVoterSavedAddress: ', this.getState().address.voter_entered_address); +// return this.getState().address.voter_entered_address || false; +// } +// +// getVoterStateCode () { +// // TODO in getVoterStateCode we check for normalized_state in the address object. We should be +// // capturing the state when we call Google address Auto Complete (search for _placeChanged) +// // and we should also figure out the state_code when we call API server voterAddressSave and put it in the "address" +// // return data. +// // console.log('this.getState().address:', this.getState().address); +// // console.log('this.getState().voter:', this.getState().voter); +// if (this.getState().address && this.getState().address.normalized_state) { +// // console.log('normalized_state:', this.getState().address.normalized_state); +// return this.getState().address.normalized_state; +// } +// if (this.getState().voter && this.getState().voter.state_code_from_ip_address) { +// // console.log('state_code_from_ip_address:', this.getState().voter.state_code_from_ip_address); +// return this.getState().voter.state_code_from_ip_address; +// } +// return ''; +// } +// +// getVoterWeVoteId () { +// return this.getState().voter.we_vote_id || ''; +// } +// +// voterDeviceId () { +// return this.getState().voter.voter_device_id || Cookies.get('voter_device_id'); +// } +// +// setVoterDeviceIdCookie (id) { // eslint-disable-line +// Cookies.remove('voter_device_id'); +// Cookies.remove('voter_device_id', { path: '/' }); +// Cookies.remove('voter_device_id', { path: '/', domain: 'wevote.us' }); +// let { hostname } = window.location; +// hostname = hostname || ''; +// // console.log('setVoterDeviceIdCookie hostname:', hostname, 'cookie id:', id); +// if (hostname && stringContains('wevote.us', hostname)) { +// Cookies.set('voter_device_id', id, { expires: 10000, path: '/', domain: 'wevote.us' }); +// } else { +// Cookies.set('voter_device_id', id, { expires: 10000, path: '/' }); +// } +// } +// +// // Airbnb doesnt like bitwise operators in JavaScript +// getInterfaceFlagState (flag) { +// // Look in js/Constants/VoterConstants.js for list of flag constant definitions +// // console.log('VoterStore getInterfaceFlagState flag: ', flag); +// if (!this.getState().voter) { +// return false; +// } +// +// const interfaceStatusFlags = this.getState().voter.interface_status_flags || 0; +// // console.log('VoterStore getInterfaceFlagState interfaceStatusFlags: ', interfaceStatusFlags); +// // return True if bit specified by the flag is also set in interfaceStatusFlags (voter.interface_status_flags) +// // Eg: if interfaceStatusFlags = 5, then we can confirm that bits representing 1 and 4 are set (i.e., 0101) +// // so for value of flag = 1 and 4, we return a positive integer, +// // but, the bit representing 2 and 8 are not set, so for flag = 2 and 8, we return zero +// // const flagIsSet = interfaceStatusFlags & flag; // eslint-disable-line no-bitwise +// // console.log('VoterStore getInterfaceFlagState flagIsSet: ', flagIsSet); +// return interfaceStatusFlags & flag; // eslint-disable-line no-bitwise +// } +// +// getNotificationSettingConstantFromUnsubscribeModifier (unsubscribeModifier) { +// // New unsubscribe modifiers also need to be added in WeVoteServer +// let notificationSettingConstant = 0; +// // dailyfriendactivity, friendaccept, friendinvite, friendopinions, friendopinionsall, friendmessage, login, newsletter +// // NOT IMPLEMENTED YET: suggestedfriend == NOTIFICATION_SUGGESTED_FRIENDS_EMAIL +// if (unsubscribeModifier === 'dailyfriendactivity') { +// notificationSettingConstant = VoterConstants.NOTIFICATION_VOTER_DAILY_SUMMARY_EMAIL; +// } else if (unsubscribeModifier === 'friendaccept' || unsubscribeModifier === 'friendinvite') { +// notificationSettingConstant = VoterConstants.NOTIFICATION_FRIEND_REQUESTS_EMAIL; // friendaccept: NOTIFICATION_FRIEND_REQUEST_RESPONSES_EMAIL +// } else if (unsubscribeModifier === 'friendopinions' || unsubscribeModifier === 'friendopinionsall') { +// notificationSettingConstant = VoterConstants.NOTIFICATION_FRIEND_OPINIONS_YOUR_BALLOT_EMAIL; // friendopinionsall: NOTIFICATION_FRIEND_OPINIONS_OTHER_REGIONS_EMAIL +// } else if (unsubscribeModifier === 'friendmessage') { +// notificationSettingConstant = VoterConstants.NOTIFICATION_FRIEND_MESSAGES_EMAIL; +// } else if (unsubscribeModifier === 'login') { +// notificationSettingConstant = VoterConstants.NOTIFICATION_LOGIN_EMAIL; +// } else if (unsubscribeModifier === 'newsletter') { +// notificationSettingConstant = VoterConstants.NOTIFICATION_NEWSLETTER_OPT_IN; +// } +// return notificationSettingConstant; +// } +// +// getNotificationSettingsFlagState (flag) { +// // Look in js/Constants/VoterConstants.js for list of flag constant definitions +// if (!this.getState().voter) { +// return false; +// } +// // Notification settings we haven't implemented yet which we show as still turned on +// if ((flag === VoterConstants.NOTIFICATION_FRIEND_MESSAGES_EMAIL) || +// (flag === VoterConstants.NOTIFICATION_FRIEND_OPINIONS_OTHER_REGIONS_EMAIL) || +// (flag === VoterConstants.NOTIFICATION_LOGIN_EMAIL)) { +// return true; +// } +// const notificationSettingsFlags = this.getState().voter.notification_settings_flags || 0; +// // return True if bit specified by the flag is also set +// // in notificationSettingsFlags (voter.notification_settings_flags) +// // Eg: if interfaceStatusFlags = 5, then we can confirm that bits representing 1 and 4 are set (i.e., 0101) +// // so for value of flag = 1 and 4, we return a positive integer, +// // but, the bit representing 2 and 8 are not set, so for flag = 2 and 8, we return zero +// return notificationSettingsFlags & flag; // eslint-disable-line no-bitwise +// } +// +// getNotificationSettingsFlagStateFromSecretKey (flag) { +// // Look in js/Constants/VoterConstants.js for list of flag constant definitions +// if (!this.getState().voterNotificationSettingsUpdateStatus) { +// return false; +// } +// // Notification settings we haven't implemented yet which we show as still turned on +// if ((flag === VoterConstants.NOTIFICATION_FRIEND_MESSAGES_EMAIL) || +// (flag === VoterConstants.NOTIFICATION_FRIEND_OPINIONS_OTHER_REGIONS_EMAIL) || +// (flag === VoterConstants.NOTIFICATION_LOGIN_EMAIL)) { +// return true; +// } +// const { notificationSettingsFlags } = this.getState().voterNotificationSettingsUpdateStatus; +// // return True if bit specified by the flag is also set +// // in notificationSettingsFlags (voter.notification_settings_flags) +// // Eg: if interfaceStatusFlags = 5, then we can confirm that bits representing 1 and 4 are set (i.e., 0101) +// // so for value of flag = 1 and 4, we return a positive integer, +// // but, the bit representing 2 and 8 are not set, so for flag = 2 and 8, we return zero +// return notificationSettingsFlags & flag; // eslint-disable-line no-bitwise +// } +// +// getVoterContactEmailAugmentSequenceComplete () { +// return this.getState().voterContactEmailAugmentSequenceComplete || false; +// } +// +// getVoterContactEmailAugmentSequenceHasNextStep () { +// return this.getState().voterContactEmailAugmentSequenceHasNextStep || false; +// } // voterContactEmailAugmentWithWeVoteDataComplete +// +// getVoterContactEmailAugmentWithWeVoteDataComplete () { +// return this.getState().voterContactEmailAugmentWithWeVoteDataComplete || false; +// } +// +// isVoterFound () { +// return this.getState().voterFound; +// } +// +// voterFirstRetrieveCompleted () { +// return this.getState().voterFirstRetrieveCompleted; +// } +// +// voterExternalIdHasBeenSavedOnce (externalVoterId, membershipOrganizationWeVoteId) { +// if (!externalVoterId || !membershipOrganizationWeVoteId) { +// return false; +// } +// if (this.getState().voterExternalIdHasBeenSavedOnce[externalVoterId]) { +// return this.getState().voterExternalIdHasBeenSavedOnce[externalVoterId][membershipOrganizationWeVoteId] || false; +// } else { +// return false; +// } +// } +// +// voterPhotoAndNameExist () { +// const firstNameExists = !!(this.getState().voter.first_name && this.getState().voter.first_name !== ''); +// const lastNameExists = !!(this.getState().voter.last_name && this.getState().voter.last_name !== ''); +// const nameExists = firstNameExists || lastNameExists; +// const photoExists = !!(this.getState().voter.voter_photo_url_large && this.getState().voter.voter_photo_url_large !== ''); +// return !!(nameExists && photoExists); +// } +// +// reduce (state, action) { +// let facebookPhotoRetrieveLoopCount; +// let address; +// let currentVoterDeviceId; +// // const delayBeforeApiCall = 3000; +// let externalVoterId; +// let googleCivicElectionId; +// let incomingVoter; +// let incorrectSecretCodeEntered; +// let membershipOrganizationWeVoteId; +// let mergeFromVoterWeVoteId; +// let mergeToVoterWeVoteId; +// let numberOfTriesRemaining; +// let revisedState; +// let secretCodeVerified; +// let voterDeviceId; +// let voterContactEmailAugmentWithWeVoteDataComplete; +// let voterExternalIdHasBeenSavedOnce; +// let voterFirstRetrieveCompleted; +// let voterMustRequestNewCode; +// let voterSecretCodeRequestsLocked; +// +// switch (action.type) { +// case 'clearEmailAddressStatus': +// // console.log('VoterStore clearEmailAddressStatus'); +// return { ...state, emailAddressStatus: {} }; +// case 'clearSecretCodeVerificationStatus': +// // console.log('VoterStore clearSecretCodeVerificationStatus'); +// return { +// ...state, +// secretCodeVerificationStatus: { +// incorrectSecretCodeEntered: false, +// numberOfTriesRemaining: 5, +// secretCodeVerified: false, +// voterMustRequestNewCode: false, +// voterSecretCodeRequestsLocked: false, +// }, +// }; +// case 'clearSecretCodeVerificationStatusAndEmail': +// // Does both of the above steps in one call +// // console.log('VoterStore clearSecretCodeVerificationStatusAndEmail'); +// return { +// ...state, +// emailAddressStatus: {}, +// secretCodeVerificationStatus: { +// incorrectSecretCodeEntered: false, +// numberOfTriesRemaining: 5, +// secretCodeVerified: false, +// voterMustRequestNewCode: false, +// voterSecretCodeRequestsLocked: false, +// }, +// }; +// case 'clearSMSPhoneNumberStatus': +// // console.log('VoterStore clearSMSPhoneNumberStatus'); +// return { +// ...state, +// smsPhoneNumberStatus: { +// sms_verify_attempted: false, +// sms_phone_number_already_owned_by_other_voter: false, +// sms_phone_number_already_owned_by_this_voter: false, +// sms_phone_number_created: false, +// sms_phone_number: '', +// sms_phone_number_found: false, +// sms_phone_number_deleted: false, +// make_primary_sms: false, +// sign_in_code_sms_sent: false, +// verification_sms_sent: false, +// }, +// }; +// case 'clearSecretCodeVerificationStatusAndPhone': +// // console.log('VoterStore clearSecretCodeVerificationStatusAndPhone'); +// return { +// ...state, +// secretCodeVerificationStatus: { +// incorrectSecretCodeEntered: false, +// numberOfTriesRemaining: 5, +// secretCodeVerified: false, +// voterMustRequestNewCode: false, +// voterSecretCodeRequestsLocked: false, +// }, +// smsPhoneNumberStatus: { +// sms_verify_attempted: false, +// sms_phone_number_already_owned_by_other_voter: false, +// sms_phone_number_already_owned_by_this_voter: false, +// sms_phone_number_created: false, +// sms_phone_number: '', +// sms_phone_number_found: false, +// sms_phone_number_deleted: false, +// make_primary_sms: false, +// sign_in_code_sms_sent: false, +// verification_sms_sent: false, +// }, +// }; +// case 'clearVoterElectionId': +// // console.log('VoterStore clearVoterElectionId'); +// return { ...state, latestGoogleCivicElectionId: 0 }; +// case 'clearVoterContactEmailImportVariables': +// return { +// ...state, +// voterContactEmailAugmentWithWeVoteDataComplete: false, +// voterContactEmailAugmentSequenceComplete: false, +// voterContactEmailAugmentSequenceHasNextStep: false, +// }; +// case 'organizationSave': +// // console.log('VoterStore organizationSave'); +// // If an organization saves, we want to check to see if it is tied to this voter. If so, +// // refresh the voter data so we have the value linked_organization_we_vote_id in the voter object. +// if (action.res.success) { +// if (action.res.facebook_id === state.voter.facebook_id) { +// VoterActions.voterRetrieve(); +// } else { +// const organizationTwitterHandle = action.res.organization_twitter_handle || ''; +// const twitterScreenName = state.voter.twitter_screen_name !== undefined ? state.voter.twitter_screen_name : ''; +// if (organizationTwitterHandle && organizationTwitterHandle.toLowerCase() === twitterScreenName.toLowerCase()) { +// VoterActions.voterRetrieve(); +// } +// } +// } +// return state; +// +// case 'positionListForVoter': +// // console.log('VoterStore positionListForVoter'); +// if (action.res.show_only_this_election) { +// const positionListForOneElection = action.res.position_list; +// return { +// ...state, +// voter: { +// ...state.voter, +// positionListForOneElection, +// }, +// }; +// } else if (action.res.show_all_other_elections) { +// const positionListForAllExceptOneElection = action.res.position_list; +// return { +// ...state, +// voter: { +// ...state.voter, +// positionListForAllExceptOneElection, +// }, +// }; +// } else { +// const positionList = action.res.position_list; +// return { +// ...state, +// voter: { +// ...state.voter, +// positionList, +// }, +// }; +// } +// +// case 'setExternalVoterId': +// externalVoterId = action.payload; +// membershipOrganizationWeVoteId = AppObservableStore.getSiteOwnerOrganizationWeVoteId(); +// ({ voterExternalIdHasBeenSavedOnce } = state); +// // console.log('VoterStore externalVoterId:', externalVoterId, ', membershipOrganizationWeVoteId:', membershipOrganizationWeVoteId); +// if (externalVoterId && membershipOrganizationWeVoteId) { +// if (!this.voterExternalIdHasBeenSavedOnce(externalVoterId, membershipOrganizationWeVoteId)) { +// // console.log('voterExternalIdHasBeenSavedOnce has NOT been saved before.'); +// VoterActions.voterExternalIdSave(externalVoterId, membershipOrganizationWeVoteId); +// if (!voterExternalIdHasBeenSavedOnce[externalVoterId]) { +// voterExternalIdHasBeenSavedOnce[externalVoterId] = {}; +// } +// voterExternalIdHasBeenSavedOnce[externalVoterId][membershipOrganizationWeVoteId] = true; +// // AnalyticsActions.saveActionBallotVisit(VoterStore.electionId()); +// } else { +// // console.log('voterExternalIdHasBeenSavedOnce has been saved before.'); +// } +// } +// return { +// ...state, +// externalVoterId, +// voterExternalIdHasBeenSavedOnce, +// }; +// +// case 'twitterRetrieveIdsIFollow': +// // console.log('VoterStore twitterRetrieveIdsIFollow'); +// if (action.res.success) { +// VoterActions.organizationSuggestionTasks('UPDATE_SUGGESTIONS_FROM_TWITTER_IDS_I_FOLLOW', +// 'FOLLOW_SUGGESTIONS_FROM_TWITTER_IDS_I_FOLLOW'); +// } +// +// return state; +// +// case 'voterAnalysisForJumpProcess': +// // console.log('VoterStore, voterAnalysisForJumpProcess'); +// VoterActions.voterRetrieve(); +// return { +// ...state, +// emailAddressStatus: { +// email_ownership_is_verified: action.res.email_ownership_is_verified, +// email_secret_key_belongs_to_this_voter: action.res.email_secret_key_belongs_to_this_voter, +// email_verify_attempted: action.res.email_verify_attempted, +// email_address_found: action.res.email_address_found, +// }, +// emailSignInStatus: { +// email_ownership_is_verified: action.res.email_ownership_is_verified, +// email_secret_key_belongs_to_this_voter: action.res.email_secret_key_belongs_to_this_voter, +// email_sign_in_attempted: action.res.email_verify_attempted, +// email_address_found: action.res.email_address_found, +// }, +// }; +// +// case 'voterAddressRetrieve': +// case 'voterAddressOnlyRetrieve': +// // console.log('VoterStore, voterAddressRetrieve, address:', action.res); +// address = action.res || {}; +// return { +// ...state, +// address, +// }; +// +// case 'voterAddressSave': +// // console.log('VoterStore, voterAddressSave, action.res:', action.res); +// revisedState = state; +// if (action.res.status === 'SIMPLE_ADDRESS_SAVE') { +// // Don't do any other refreshing +// } else { +// googleCivicElectionId = action.res.google_civic_election_id || 0; +// if (googleCivicElectionId !== 0) { +// revisedState = { ...revisedState, +// latestGoogleCivicElectionId: googleCivicElectionId, +// }; +// } +// } +// ({ address } = action.res); +// if (!address) { +// address = { +// text_for_map_search: '', +// google_civic_election_id: 0, +// ballot_returned_we_vote_id: '', +// ballot_location_display_name: '', +// voter_entered_address: '', +// voter_specific_ballot_from_google_civic: null, +// }; +// } +// +// return { +// ...revisedState, +// address: { +// text_for_map_search: address.text_for_map_search, +// google_civic_election_id: address.google_civic_election_id, +// ballot_returned_we_vote_id: address.ballot_returned_we_vote_id, +// ballot_location_display_name: address.ballot_location_display_name, +// voter_entered_address: address.voter_entered_address, +// voter_specific_ballot_from_google_civic: address.voter_specific_ballot_from_google_civic, +// }, +// }; +// +// case 'voterBallotItemsRetrieve': +// // console.log('VoterStore voterBallotItemsRetrieve latestGoogleCivicElectionId: ', action.res.google_civic_election_id); +// googleCivicElectionId = action.res.google_civic_election_id || 0; +// if (googleCivicElectionId !== 0) { +// return { +// ...state, +// latestGoogleCivicElectionId: googleCivicElectionId, +// }; +// } +// return state; +// +// case 'voterContactListRetrieve': +// // console.log('VoterStore voterContactListRetrieve action:', action); +// if (action.res.success) { +// const { +// voter_contact_email_google_count: voterContactEmailGoogleCount, +// voter_contact_email_list: voterContactEmailList, +// } = action.res; +// return { +// ...state, +// voterContactEmailGoogleCount, +// voterContactEmailList, +// }; +// } else { +// console.log('response voterContactListRetrieve was not successful'); +// return state; +// } +// +// case 'voterContactListSave': +// // console.log('VoterStore voterContactListSave action.res:', action.res); +// if (action.res.success) { +// ({ voterContactEmailAugmentWithWeVoteDataComplete } = state); +// const { +// augment_voter_contact_emails_with_location: justAugmentedWithLocation, +// augment_voter_contact_emails_with_we_vote_data: justAugmentedWithWeVoteData, +// contacts_stored: googleContactsStored, +// delete_all_voter_contact_emails: voterContactEmailsJustDeleted, +// voter_contact_email_augment_sequence_complete: voterContactEmailAugmentSequenceComplete, +// voter_contact_email_augment_sequence_has_next_step: voterContactEmailAugmentSequenceHasNextStep, +// voter_contact_email_google_count: voterContactEmailGoogleCount, +// voter_contact_email_list: voterContactEmailList, +// we_vote_id_for_google_contacts: weVoteIdForGoogleContacts, +// } = action.res; +// // console.log('googleContactsStored:', googleContactsStored, ', justAugmentedWithWeVoteData:', justAugmentedWithWeVoteData, ',justAugmentedWithLocation:', justAugmentedWithLocation); +// if (voterContactEmailsJustDeleted || justAugmentedWithLocation) { +// // Never call again +// } else if (googleContactsStored && (googleContactsStored > 0)) { +// // console.log('Calling VoterActions.voterContactListAugmentWithWeVoteData'); +// VoterActions.voterContactListAugmentWithWeVoteData(true); +// } else if (justAugmentedWithWeVoteData) { +// // console.log('Calling VoterActions.voterContactListAugmentWithLocation'); +// VoterActions.voterContactListAugmentWithLocation(true); +// } +// if (googleContactsStored) { +// voterContactEmailAugmentWithWeVoteDataComplete = false; +// } else if (justAugmentedWithWeVoteData) { +// voterContactEmailAugmentWithWeVoteDataComplete = true; +// } +// return { +// ...state, +// weVoteIdForGoogleContacts, +// googleContactsStored, +// voterContactEmailAugmentWithWeVoteDataComplete, +// voterContactEmailAugmentSequenceComplete, +// voterContactEmailAugmentSequenceHasNextStep, +// voterContactEmailGoogleCount, +// voterContactEmailList, +// }; +// } else { +// console.log('response voterContactListSave was not successful'); +// return state; +// } +// +// case 'voterEmailAddressRetrieve': +// // console.log('VoterStore voterEmailAddressRetrieve: ', action.res.email_address_list); +// return { +// ...state, +// emailAddressList: action.res.email_address_list, +// }; +// +// case 'voterEmailAddressSave': +// // console.log('VoterStore, voterEmailAddressSave'); +// VoterActions.voterRetrieve(); +// return { +// ...state, +// emailAddressList: action.res.email_address_list, +// emailAddressStatus: { +// email_verify_attempted: action.res.email_verify_attempted, +// email_address_already_owned_by_other_voter: action.res.email_address_already_owned_by_other_voter, +// email_address_already_owned_by_this_voter: action.res.email_address_already_owned_by_this_voter, +// email_address_created: action.res.email_address_created, +// email_address_deleted: action.res.email_address_deleted, +// email_address_not_valid: action.res.email_address_not_valid, +// from_voter_we_vote_id: action.res.from_voter_we_vote_id, +// link_to_sign_in_email_sent: action.res.link_to_sign_in_email_sent, +// make_primary_email: action.res.make_primary_email, +// sign_in_code_email_sent: action.res.sign_in_code_email_sent, +// secret_code_system_locked_for_this_voter_device_id: action.res.secret_code_system_locked_for_this_voter_device_id, +// to_voter_we_vote_id: action.res.to_voter_we_vote_id, +// verification_email_sent: action.res.verification_email_sent, +// }, +// }; +// +// case 'voterEmailAddressSignIn': +// // console.log('VoterStore, voterEmailAddressSignIn'); +// VoterActions.voterRetrieve(); +// return { +// ...state, +// emailSignInStatus: { +// email_sign_in_attempted: action.res.email_sign_in_attempted, +// email_ownership_is_verified: action.res.email_ownership_is_verified, +// email_secret_key_belongs_to_this_voter: action.res.email_secret_key_belongs_to_this_voter, +// email_address_found: action.res.email_address_found, +// yes_please_merge_accounts: action.res.yes_please_merge_accounts, +// voter_we_vote_id_from_secret_key: action.res.voter_we_vote_id_from_secret_key, +// voter_merge_two_accounts_attempted: false, +// }, +// }; +// +// case 'voterEmailAddressVerify': +// // console.log('VoterStore, voterEmailAddressVerify'); +// VoterActions.voterRetrieve(); +// return { +// ...state, +// emailAddressStatus: { +// email_ownership_is_verified: action.res.email_ownership_is_verified, +// email_secret_key_belongs_to_this_voter: action.res.email_secret_key_belongs_to_this_voter, +// email_verify_attempted: action.res.email_verify_attempted, +// email_address_found: action.res.email_address_found, +// }, +// emailSignInStatus: { +// email_ownership_is_verified: action.res.email_ownership_is_verified, +// email_secret_key_belongs_to_this_voter: action.res.email_secret_key_belongs_to_this_voter, +// email_sign_in_attempted: action.res.email_verify_attempted, +// email_address_found: action.res.email_address_found, +// }, +// }; +// +// case 'voterEmailQueuedToSave': +// // console.log('VoterStore voterEmailQueuedToSave: ', action.payload); +// if (action.payload === undefined) { +// return { +// ...state, +// voterEmailQueuedToSave: '', +// voterEmailQueuedToSaveSet: false, +// }; +// } else { +// return { +// ...state, +// voterEmailQueuedToSave: action.payload, +// voterEmailQueuedToSaveSet: true, +// }; +// } +// +// case 'voterFacebookSaveToCurrentAccount': +// // console.log('VoterStore, voterFacebookSaveToCurrentAccount'); +// VoterActions.voterRetrieve(); +// return { +// ...state, +// facebookSignInStatus: { +// facebook_account_created: action.res.facebook_account_created, +// }, +// }; +// +// case 'voterFirstNameQueuedToSave': +// // console.log('VoterStore voterFirstNameQueuedToSave: ', action.payload); +// if (action.payload === undefined) { +// return { +// ...state, +// voterFirstNameQueuedToSave: '', +// voterFirstNameQueuedToSaveSet: false, +// }; +// } else { +// return { +// ...state, +// voterFirstNameQueuedToSave: action.payload, +// voterFirstNameQueuedToSaveSet: true, +// }; +// } +// +// case 'voterLastNameQueuedToSave': +// // console.log('VoterStore voterLastNameQueuedToSave: ', action.payload); +// if (action.payload === undefined) { +// return { +// ...state, +// voterLastNameQueuedToSave: '', +// voterLastNameQueuedToSaveSet: false, +// }; +// } else { +// return { +// ...state, +// voterLastNameQueuedToSave: action.payload, +// voterLastNameQueuedToSaveSet: true, +// }; +// } +// +// case 'voterMergeTwoAccounts': +// // console.log('VoterStore, voterMergeTwoAccounts'); +// // On the server we just switched (linked) this voterDeviceId to a new voter record, so we want to the voter. +// // refresh a lot of data -- December 2022, but as little as absolutely required, and no more +// VoterActions.voterRetrieve(); +// // // And set a timer for 3 seconds from now to refresh again +// // this.timer = setTimeout(() => { +// // VoterActions.voterRetrieve(); +// // }, delayBeforeApiCall); +// VoterActions.voterEmailAddressRetrieve(); // TODO: December 2022, Is this necessary? +// VoterActions.voterSMSPhoneNumberRetrieve(); // TODO: December 2022, Is this necessary? +// if (action.res.merge_from_voter_we_vote_id && action.res.merge_to_voter_we_vote_id) { +// if (apiCalming('voterRetrieveMergeTwo', 3000)) { +// // This completes the time-consuming process 'voter_merge_two_accounts_action' and then returns voter data +// console.log('VoterStore: voterMergeTwoAccounts: Completing voterRetrieveMergeTwo process'); +// VoterActions.voterRetrieve(action.res.merge_from_voter_we_vote_id, action.res.merge_to_voter_we_vote_id); +// } +// } +// return { +// ...state, +// emailSignInStatus: { +// email_ownership_is_verified: true, +// email_secret_key_belongs_to_this_voter: true, +// email_sign_in_attempted: true, +// email_address_found: true, +// yes_please_merge_accounts: false, +// voter_we_vote_id_from_secret_key: '', +// voter_merge_two_accounts_attempted: true, +// }, +// facebookSignInStatus: { +// voter_merge_two_accounts_attempted: true, +// }, +// twitterSignInStatus: { +// voter_merge_two_accounts_attempted: true, +// }, +// }; +// +// case 'voterNotificationSettingsUpdate': +// // console.log('VoterStore, voterNotificationSettingsUpdate'); +// if (!action.res) { +// return { +// ...state, +// voterNotificationSettingsUpdateStatus: { +// apiResponseReceived: true, +// emailFound: false, +// voterFound: false, +// normalizedEmailAddress: '', +// normalizedSmsPhoneNumber: '', +// notificationSettingsFlags: false, +// }, +// }; +// } +// return { +// ...state, +// voterNotificationSettingsUpdateStatus: { +// apiResponseReceived: true, +// emailFound: action.res.email_found, +// voterFound: action.res.voter_found, +// normalizedEmailAddress: action.res.normalized_email_address, +// normalizedSmsPhoneNumber: action.res.normalized_sms_phone_number, +// notificationSettingsFlags: action.res.notification_settings_flags, +// }, +// }; +// +// case 'voterPhotoQueuedToSave': +// // console.log('VoterStore voterPhotoQueuedToSave: ', action.payload); +// if (action.payload === undefined) { +// return { +// ...state, +// voterPhotoQueuedToSave: '', +// voterPhotoQueuedToSaveSet: false, +// }; +// } else { +// return { +// ...state, +// voterPhotoQueuedToSave: action.payload, +// voterPhotoQueuedToSaveSet: true, +// }; +// } +// +// case 'voterPhotoSave': +// // console.log('VoterStore, voterPhotoSave'); +// return { +// ...state, +// voter: { ...state.voter, facebook_profile_image_url_https: action.res.facebook_profile_image_url_https }, +// }; +// +// case 'voterPhotoTooBigReset': +// // console.log('VoterStore, voterPhotoTooBigReset'); +// return { +// ...state, +// voterPhotoTooBig: false, +// }; +// +// case 'voterRetrieve': +// // console.log('VoterStore, voterRetrieve state on entry: ', state); +// // console.log('VoterStore, voterRetrieve state on entry: ', state.voter); +// +// // Preserve address within voter +// incomingVoter = action.res; +// ({ facebookPhotoRetrieveLoopCount, voterFirstRetrieveCompleted } = state); +// if (!voterFirstRetrieveCompleted) { +// voterFirstRetrieveCompleted = Boolean(action.res.success); +// } +// +// currentVoterDeviceId = Cookies.get('voter_device_id'); +// // console.log('VoterStore, voterRetrieve stored Cookie value for voter_device_id value on entry: ', currentVoterDeviceId); +// if (!action.res.voter_found) { +// console.log(`This voter_device_id is not in the db and is invalid, so delete it: ${currentVoterDeviceId}`); +// +// // Attempt to delete the voter_device_id cookie in a variety of ways +// Cookies.remove('voter_device_id'); +// Cookies.remove('voter_device_id', { path: '/' }); +// Cookies.remove('voter_device_id', { path: '/', domain: 'wevote.us' }); +// +// // ...and then ask for a new voter. When it returns a voter with a new voter_device_id, we will set new cookie +// if (!Cookies.get('voter_device_id')) { +// console.log('voter_device_id gone -- calling voterRetrieve'); +// VoterActions.voterRetrieve(); +// } else { +// // console.log('voter_device_id still exists -- did not call voterRetrieve'); +// } +// } else { +// voterDeviceId = action.res.voter_device_id; +// if (voterDeviceId) { +// if (currentVoterDeviceId !== voterDeviceId) { +// console.log('Setting new voter_device_id'); +// this.setVoterDeviceIdCookie(voterDeviceId); +// } +// // FriendsInvitationList.jsx is choking on this because calling this +// // results in an infinite loop cycling between voterRetrieve and getFaceProfilePicture which +// // resolves to FACEBOOK_RECEIVED_PICTURE which then attempts to save using voterFacebookSignInPhoto +// // which in turn resolves to voterFacebookSignInSave which finally attempts to call +// // voterRetrieve again +// // console.log('VoterStore, voterRetrieve, action.res: ', action.res); +// } else { +// // console.log('voter_device_id not returned by voterRetrieve'); +// } +// } +// // April 29, 2021 TODO: We should make a combined Voter and Organization retrieve +// // because this fires on the initial page load and takes almost a full second to return, blocking one of six available http channels +// // Firing actions from stores should be avoided +// // The following (new) condition blocks a organizationRetrieve on the first voterRetrieve +// +// // if (incomingVoter.signed_in_with_apple) { +// // // Completing the logical OR that can't be conveniently made in the server, since Sign in with Apple is device_id specific +// // incomingVoter.is_signed_in = incomingVoter.signed_in_with_apple; +// // const { voter_photo_url_medium: statePhotoMed } = state.voter; +// // const { voter_photo_url_medium: incomingPhotoMed } = incomingVoter; +// // if (!statePhotoMed && !incomingPhotoMed) { +// // incomingVoter.voter_photo_url_medium = 'https://wevote.us/img/global/logos/Apple_logo_grey.svg'; // TODO: Switch over to wevote.us once live server is updated +// // } +// // } +// if (incomingVoter && incomingVoter.we_vote_id) { +// if (incomingVoter.we_vote_id !== AppObservableStore.getOpenReplayVoterWeVoteId()) { +// // console.log('tracker.setUserId:', incomingVoter.we_vote_id); +// const tracker = AppObservableStore.getOpenReplayTracker(); +// if (tracker) { +// console.log('OpenReplay setting id: ', incomingVoter.we_vote_id); +// AppObservableStore.setOpenReplayVoterWeVoteId(incomingVoter.we_vote_id); +// tracker.setUserID(incomingVoter.we_vote_id); +// } +// } +// if (incomingVoter.is_signed_in && !AppObservableStore.getOpenReplayVoterIsSignedIn()) { +// const tracker = AppObservableStore.getOpenReplayTracker(); +// if (tracker) { +// console.log('OpenReplay setting voterIsSignedIn'); +// AppObservableStore.setOpenReplayVoterIsSignedIn(true); +// tracker.setMetadata('voterIsSignedIn', 'true'); +// } +// } +// if (this.getStateCode() && !AppObservableStore.getOpenReplayStateCode()) { +// // getStateCode defaults to state_code_from_ip_address but is overridden by the state in text_for_map_search +// const tracker = AppObservableStore.getOpenReplayTracker(); +// const stateCode = this.getStateCode().toUpperCase(); +// if (tracker && stateCode) { +// console.log('OpenReplay setting stateCode'); +// AppObservableStore.setOpenReplayStateCode(stateCode); +// tracker.setMetadata('stateCode', stateCode); +// } +// } +// if (incomingVoter.state_code_from_ip_address && !AppObservableStore.getOpenReplayStateCodeFromIpAddress()) { +// const tracker = AppObservableStore.getOpenReplayTracker(); +// const stateCodeFromIpAddress = incomingVoter.state_code_from_ip_address.toUpperCase(); +// if (tracker && stateCodeFromIpAddress) { +// console.log('OpenReplay setting stateCodeFromIpAddress'); +// AppObservableStore.setOpenReplayStateCodeFromIpAddress(stateCodeFromIpAddress); +// tracker.setMetadata('stateCodeFromIpAddress', stateCodeFromIpAddress); +// } +// } +// } +// revisedState = state; +// revisedState = { +// ...revisedState, +// facebookPhotoRetrieveLoopCount: facebookPhotoRetrieveLoopCount + 1, +// voter: incomingVoter, +// voterFirstRetrieveCompleted, +// voterFound: action.res.voter_found, +// }; +// if (incomingVoter.address) { +// // console.log('incomingVoter.address:', incomingVoter.address); +// revisedState = { ...revisedState, address: incomingVoter.address }; +// } +// return revisedState; +// +// case 'voterSignOut': +// // console.log('VoterStore resetting voterStore via voterSignOut'); +// VoterActions.voterRetrieve(); +// VoterActions.voterEmailAddressRetrieve(); +// VoterActions.voterSMSPhoneNumberRetrieve(); +// revisedState = state; +// revisedState = { ...revisedState, ...this.getInitialState() }; +// return revisedState; +// +// case 'voterSMSPhoneNumberRetrieve': +// // console.log('VoterStore voterSMSPhoneNumberRetrieve: ', action.res.sms_phone_number_list); +// return { +// ...state, +// smsPhoneNumberList: action.res.sms_phone_number_list, +// }; +// +// case 'voterSMSPhoneNumberSave': +// // console.log('VoterStore voterSMSPhoneNumberSave action.res:', action.res); +// VoterActions.voterRetrieve(); +// VoterActions.voterSMSPhoneNumberRetrieve(); +// return { +// ...state, +// smsPhoneNumberList: action.res.sms_phone_number_list, +// smsPhoneNumberStatus: { +// sms_verify_attempted: action.res.sms_verify_attempted, +// sms_phone_number_already_owned_by_other_voter: action.res.sms_phone_number_already_owned_by_other_voter, +// sms_phone_number_already_owned_by_this_voter: action.res.sms_phone_number_already_owned_by_this_voter, +// sms_phone_number_created: action.res.sms_phone_number_created, +// sms_phone_number: action.res.sms_phone_number, +// sms_phone_number_found: action.res.sms_phone_number_found, +// sms_phone_number_deleted: action.res.sms_phone_number_deleted, +// make_primary_sms: action.res.make_primary_sms, +// secret_code_system_locked_for_this_voter_device_id: action.res.secret_code_system_locked_for_this_voter_device_id, +// sign_in_code_sms_sent: action.res.sign_in_code_sms_sent, +// verification_sms_sent: action.res.verification_sms_sent, +// }, +// }; +// +// case 'voterSplitIntoTwoAccounts': +// // console.log('VoterStore voterSplitIntoTwoAccounts '); +// VoterActions.voterRetrieve(); +// return state; +// +// case 'voterTwitterSaveToCurrentAccount': +// // console.log('VoterStore voterTwitterSaveToCurrentAccount '); +// VoterActions.voterRetrieve(); +// return { +// ...state, +// twitterSignInStatus: { +// twitter_account_created: action.res.twitter_account_created, +// }, +// }; +// +// case 'voterUpdate': // Formerly voterDeleteAccount +// if (action.res.success && action.res.voter_deleted) { +// revisedState = state; +// revisedState = { ...revisedState, +// voterDeleted: true, +// voterNotDeleted: false, +// }; +// return revisedState; +// } else if (action.res.success && action.res.voter_not_deleted) { +// revisedState = state; +// revisedState = { ...revisedState, +// voterDeleted: false, +// voterNotDeleted: true, +// }; +// return revisedState; +// } else if (action.res.success) { +// let interfaceStatusFlags = action.res.interface_status_flags; +// if (interfaceStatusFlags === undefined) { +// interfaceStatusFlags = state.voter.interface_status_flags; +// } +// let notificationSettingsFlags = action.res.notification_settings_flags; +// if (notificationSettingsFlags === undefined) { +// notificationSettingsFlags = state.voter.notification_settings_flags; +// } +// return { +// ...state, +// voter: { +// ...state.voter, +// // With this we are only updating the values we change with a voterUpdate call. +// facebook_email: action.res.email || state.voter.email, +// first_name: action.res.first_name, +// interface_status_flags: interfaceStatusFlags, +// last_name: action.res.last_name, +// notification_settings_flags: notificationSettingsFlags, +// profile_image_type_currently_active: action.res.profile_image_type_currently_active || '', +// voter_donation_history_list: action.res.voter_donation_history_list || state.voter.voter_donation_history_list, +// voter_photo_url_large: action.res.we_vote_hosted_profile_image_url_large || '', +// voter_photo_url_medium: action.res.we_vote_hosted_profile_image_url_medium || '', +// voter_photo_url_tiny: action.res.we_vote_hosted_profile_image_url_tiny || '', +// we_vote_hosted_profile_facebook_image_url_large: action.res.we_vote_hosted_profile_facebook_image_url_large || '', +// we_vote_hosted_profile_twitter_image_url_large: action.res.we_vote_hosted_profile_twitter_image_url_large || '', +// we_vote_hosted_profile_uploaded_image_url_large: action.res.we_vote_hosted_profile_uploaded_image_url_large || '', +// }, +// voterPhotoTooBig: action.res.voter_photo_too_big || false, +// }; +// } else { +// return { +// ...state, +// voterPhotoTooBig: action.res.voter_photo_too_big || false, +// }; +// } +// +// case 'voterVerifySecretCode': +// // console.log('VoterStore, voterVerifySecretCode, action.res:', action.res); +// incorrectSecretCodeEntered = (action.res.incorrect_secret_code_entered && action.res.incorrect_secret_code_entered === true); +// mergeFromVoterWeVoteId = action.res.merge_from_voter_we_vote_id; +// mergeToVoterWeVoteId = action.res.merge_to_voter_we_vote_id; +// numberOfTriesRemaining = action.res.number_of_tries_remaining_for_this_code; +// secretCodeVerified = (action.res.secret_code_verified && action.res.secret_code_verified === true); +// voterMustRequestNewCode = (action.res.voter_must_request_new_code && action.res.voter_must_request_new_code === true); +// voterSecretCodeRequestsLocked = (action.res.secret_code_system_locked_for_this_voter_device_id && action.res.secret_code_system_locked_for_this_voter_device_id === true); +// // console.log('onVoterStoreChange voterStore secretCodeVerified', secretCodeVerified); +// // It is appropriate to keep this call within the Store because the components which trigger the voterVerifySecretCode +// // get closed as soon as secretCodeVerified is true +// if (mergeFromVoterWeVoteId && mergeToVoterWeVoteId) { +// // console.log('VoterStore, voterVerifySecretCode: voterRetrieveMergeTwo mergeFromVoterWeVoteId:', mergeFromVoterWeVoteId, ', mergeToVoterWeVoteId:', mergeToVoterWeVoteId); +// if (apiCalming('voterRetrieveMergeTwo', 3000)) { +// // This completes the time-consuming process 'voter_merge_two_accounts_action' and then returns voter data +// VoterActions.voterRetrieve(mergeFromVoterWeVoteId, mergeToVoterWeVoteId); +// } +// } +// return { +// ...state, +// secretCodeVerificationStatus: { +// incorrectSecretCodeEntered, +// numberOfTriesRemaining, +// secretCodeVerified, +// voterMustRequestNewCode, +// voterSecretCodeRequestsLocked, +// }, +// }; +// +// case 'appleSignInSave': +// if (action.res.success) { +// // eslint-disable-next-line camelcase +// const { first_name, middle_name, last_name, email, user_code: appleUserCode } = action.res; +// VoterActions.voterRetrieve(); +// return { +// ...state, +// voter: { +// first_name, +// middle_name, +// last_name, +// email, +// appleUserCode, +// signed_in_with_apple: true, +// }, +// }; +// } else { +// console.log('Received a bad response from appleSignInSave API call'); +// return state; +// } +// +// case 'deviceStoreFirebaseCloudMessagingToken': +// if (action.res.success) { +// // console.log('Received success from deviceStoreFirebaseCloudMessagingToken API call'); +// return state; +// } else { +// console.log('Received a bad response from deviceStoreFirebaseCloudMessagingToken API call, object properties follow:'); +// dumpObjProps('action.res', action.res); +// return state; +// } +// +// +// case 'error-voterRetrieve' || 'error-voterAddressRetrieve' || 'error-voterAddressSave': +// // console.log('VoterStore action', action); +// return state; +// +// default: +// return state; +// } +// } +// } +// +// export default new VoterStore(Dispatcher); diff --git a/src/js/utils/service.js b/src/js/utils/service.js index d970fc1..4885867 100644 --- a/src/js/utils/service.js +++ b/src/js/utils/service.js @@ -1,106 +1,106 @@ -import assign from 'object-assign'; -import webAppConfig from '../config'; -import Cookies from '../common/utils/js-cookie/Cookies'; -import { httpLog } from '../common/utils/logging'; -/* eslint no-param-reassign: 0 */ - - -const defaults = { - dataType: 'json', - baseUrl: webAppConfig.STAFF_API_SERVER_API_ROOT_URL, - baseCdnUrl: webAppConfig.STAFF_API_SERVER_API_CDN_ROOT_URL, - url: webAppConfig.STAFF_API_SERVER_API_ROOT_URL, - query: {}, - method: 'GET', - data () { - // console.log('----------- voter_device_id sent with request in service.js/data: ', Cookies.get('voter_device_id')); - return Cookies.get('voter_device_id') ? { - // csrfmiddlewaretoken: cookies.getItem('csrftoken'), - voter_device_id: Cookies.get('voter_device_id'), - } : {}; - }, - - success: (res) => console.warn('Success function not defined:', res), - error: (err) => console.error(`Ajax error: ${err.message}`), -}; - -/* - * 2021: This function uses jQuery, to do deferred fetches from endpoints, and is already loaded with React - * i.e. making sure jQuery is loaded right away becomes less important - * React fetch is a more up to date way of doing this: - * https://reactjs.org/docs/faq-ajax.html - * - * 2016: The idea of this APIS.js file is to abstract away the details - * of many repetitive service calls that we will be using. - * @author Nick Fiorini - */ - - -function innerAjax (options) { - const { $ } = window; - if (!options.endpoint) throw new Error('$ajax missing endpoint option'); - if (!defaults.baseCdnUrl) throw new Error('$ajax missing base CDN url option'); - if (!defaults.baseUrl) throw new Error('$ajax missing base url option'); - - options.crossDomain = true; - options.success = options.success || defaults.success; - options.error = options.error || defaults.error; - // console.log('service.js, options.endpoint: ', options.endpoint); - if (options.endpoint === 'campaignStartSave' || - // options.endpoint === 'challengeSave' || // TBD - options.endpoint === 'challengeStartSave' || - options.endpoint === 'organizationPhotosSave' || - options.endpoint === 'reactionLikeStatusRetrieve' || - options.endpoint === 'voterContactListSave' || - options.endpoint === 'voterUpdate') { - options.method = 'POST'; - } else { - options.method = 'GET'; - } - // Switch between master API server and CDN - if (options.endpoint === 'allBallotItemsRetrieve' || - options.endpoint === 'voterGuidesUpcomingRetrieve' || - options.endpoint === 'voterGuidesRetrieve' - ) { - // Retrieve API data from CDN - options.data = assign({}, options.data || {}); // Do not pass voter_device_id - if (options.endpoint && !options.endpoint.endsWith('/')) { - options.endpoint += '/'; - } - options.url = new URL(options.endpoint, defaults.baseCdnUrl); // `${URL.resolve(defaults.baseCdnUrl, options.endpoint)}/`; - } else { - // Retrieve API from API Server Pool - options.data = assign({}, options.data || {}, defaults.data()); - if (options.endpoint && !options.endpoint.endsWith('/')) { - options.endpoint += '/'; - } - options.url = new URL(options.endpoint, defaults.baseUrl); // `${URL.resolve(defaults.baseUrl, options.endpoint)}/`; - } - - httpLog(`AJAX URL: ${options.url} -- voter_device_id: ${Cookies.get('voter_device_id')}`); - if (options.method === 'POST') { - httpLog(JSON.stringify(options.data)); - } - if (['voterRetrieve', 'deviceStoreFirebaseCloudMessagingToken', 'siteConfigurationRetrieve'].includes(options.endpoint)) { - httpLog('AJAX voter_device_id: ', Cookies.get('voter_device_id')); - } - return $.ajax(options); -} - -export default function $ajax (options) { - if (typeof window.$ !== 'undefined') { - innerAjax(options); - } else { - let loop = 0; - // eslint-disable-next-line consistent-return - const waitForJQuery = setInterval(() => { - if (typeof window.$ !== 'undefined') { - clearInterval(waitForJQuery); - innerAjax(options); - } - if (loop++ > 400 && loop < 405) { - throw new Error('$ajax could not load jQuery within 20 seconds'); - } - }, 10); - } -} +// import assign from 'object-assign'; +// import webAppConfig from '../config'; +// import Cookies from '../common/utils/js-cookie/Cookies'; +// import { httpLog } from '../common/utils/logging'; +// /* eslint no-param-reassign: 0 */ +// +// +// const defaults = { +// dataType: 'json', +// baseUrl: webAppConfig.STAFF_API_SERVER_API_ROOT_URL, +// baseCdnUrl: webAppConfig.STAFF_API_SERVER_API_CDN_ROOT_URL, +// url: webAppConfig.STAFF_API_SERVER_API_ROOT_URL, +// query: {}, +// method: 'GET', +// data () { +// // console.log('----------- voter_device_id sent with request in service.js/data: ', Cookies.get('voter_device_id')); +// return Cookies.get('voter_device_id') ? { +// // csrfmiddlewaretoken: cookies.getItem('csrftoken'), +// voter_device_id: Cookies.get('voter_device_id'), +// } : {}; +// }, +// +// success: (res) => console.warn('Success function not defined:', res), +// error: (err) => console.error(`Ajax error: ${err.message}`), +// }; +// +// /* +// * 2021: This function uses jQuery, to do deferred fetches from endpoints, and is already loaded with React +// * i.e. making sure jQuery is loaded right away becomes less important +// * React fetch is a more up to date way of doing this: +// * https://reactjs.org/docs/faq-ajax.html +// * +// * 2016: The idea of this APIS.js file is to abstract away the details +// * of many repetitive service calls that we will be using. +// * @author Nick Fiorini +// */ +// +// +// function innerAjax (options) { +// const { $ } = window; +// if (!options.endpoint) throw new Error('$ajax missing endpoint option'); +// if (!defaults.baseCdnUrl) throw new Error('$ajax missing base CDN url option'); +// if (!defaults.baseUrl) throw new Error('$ajax missing base url option'); +// +// options.crossDomain = true; +// options.success = options.success || defaults.success; +// options.error = options.error || defaults.error; +// // console.log('service.js, options.endpoint: ', options.endpoint); +// if (options.endpoint === 'campaignStartSave' || +// // options.endpoint === 'challengeSave' || // TBD +// options.endpoint === 'challengeStartSave' || +// options.endpoint === 'organizationPhotosSave' || +// options.endpoint === 'reactionLikeStatusRetrieve' || +// options.endpoint === 'voterContactListSave' || +// options.endpoint === 'voterUpdate') { +// options.method = 'POST'; +// } else { +// options.method = 'GET'; +// } +// // Switch between master API server and CDN +// if (options.endpoint === 'allBallotItemsRetrieve' || +// options.endpoint === 'voterGuidesUpcomingRetrieve' || +// options.endpoint === 'voterGuidesRetrieve' +// ) { +// // Retrieve API data from CDN +// options.data = assign({}, options.data || {}); // Do not pass voter_device_id +// if (options.endpoint && !options.endpoint.endsWith('/')) { +// options.endpoint += '/'; +// } +// options.url = new URL(options.endpoint, defaults.baseCdnUrl); // `${URL.resolve(defaults.baseCdnUrl, options.endpoint)}/`; +// } else { +// // Retrieve API from API Server Pool +// options.data = assign({}, options.data || {}, defaults.data()); +// if (options.endpoint && !options.endpoint.endsWith('/')) { +// options.endpoint += '/'; +// } +// options.url = new URL(options.endpoint, defaults.baseUrl); // `${URL.resolve(defaults.baseUrl, options.endpoint)}/`; +// } +// +// httpLog(`AJAX URL: ${options.url} -- voter_device_id: ${Cookies.get('voter_device_id')}`); +// if (options.method === 'POST') { +// httpLog(JSON.stringify(options.data)); +// } +// if (['voterRetrieve', 'deviceStoreFirebaseCloudMessagingToken', 'siteConfigurationRetrieve'].includes(options.endpoint)) { +// httpLog('AJAX voter_device_id: ', Cookies.get('voter_device_id')); +// } +// return $.ajax(options); +// } +// +// export default function $ajax (options) { +// if (typeof window.$ !== 'undefined') { +// innerAjax(options); +// } else { +// let loop = 0; +// // eslint-disable-next-line consistent-return +// const waitForJQuery = setInterval(() => { +// if (typeof window.$ !== 'undefined') { +// clearInterval(waitForJQuery); +// innerAjax(options); +// } +// if (loop++ > 400 && loop < 405) { +// throw new Error('$ajax could not load jQuery within 20 seconds'); +// } +// }, 10); +// } +// }