Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MPDX-8344 Tools Sources #1118

Merged
merged 15 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { DateTime } from 'luxon';
import { useTranslation } from 'react-i18next';
import { useLocale } from 'src/hooks/useLocale';
import { dateFormat } from 'src/lib/intlFormat';
import { sourceToStr } from 'src/utils/sourceToStr';
import { sourceToStr } from 'src/utils/sourceHelper';
import {
ContactDetailContext,
ContactDetailsType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
} from 'src/components/common/Modal/ActionButtons/ActionButtons';
import { AddressUpdateInput } from 'src/graphql/types.generated';
import { useUpdateCache } from 'src/hooks/useUpdateCache';
import { isEditableSource } from 'src/utils/sourceHelper';
import Modal from '../../../../../common/Modal/Modal';
import {
ContactDetailsTabDocument,
Expand Down Expand Up @@ -65,8 +66,6 @@ const LoadingIndicator = styled(CircularProgress)(({ theme }) => ({
margin: theme.spacing(0, 1, 0, 0),
}));

export const editableSources = ['MPDX', 'manual', 'TntImport'];

interface EditContactAddressModalProps {
accountListId: string;
address: ContactMailingFragment['addresses']['nodes'][0];
Expand Down Expand Up @@ -171,7 +170,7 @@ export const EditContactAddressModal: React.FC<
handleClose();
};

const editingDisabled = editableSources.indexOf(address.source) === -1;
const editingDisabled = !isEditableSource(address.source);
const { data: emailData } = useDonationServicesEmailQuery({
variables: {
accountListId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
PersonEmailAddressInput,
PersonUpdateInput,
} from 'src/graphql/types.generated';
import { isEditableSource } from 'src/utils/sourceHelper';
import { ModalSectionContainer } from '../ModalSectionContainer/ModalSectionContainer';
import { ModalSectionDeleteIcon } from '../ModalSectionDeleteIcon/ModalSectionDeleteIcon';
import { NewSocial } from '../PersonModal';
Expand All @@ -33,7 +34,7 @@
emailAddresses: InputMaybe<PersonEmailAddressInput[]> | undefined;
setFieldValue: (
field: string,
value: any,

Check warning on line 37 in src/components/Contacts/ContactDetails/ContactDetailsTab/People/Items/PersonModal/PersonEmail/PersonEmailItem.tsx

View workflow job for this annotation

GitHub Actions / eslint

Unexpected any. Specify a different type
shouldValidate?: boolean | undefined,
) => void;
errors: FormikErrors<(PersonUpdateInput | PersonCreateInput) & NewSocial>;
Expand Down Expand Up @@ -69,7 +70,7 @@

const source = sources?.find((email) => email.id === emailAddress.id)?.source;

const locked = source !== 'MPDX' && source !== undefined;
const locked = !isEditableSource(source);

React.useEffect(() => {
setIsEmailPrimaryChecked(index === primaryIndex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
PersonPhoneNumberInput,
PersonUpdateInput,
} from 'src/graphql/types.generated';
import { isEditableSource } from 'src/utils/sourceHelper';
import { ModalSectionContainer } from '../ModalSectionContainer/ModalSectionContainer';
import { ModalSectionDeleteIcon } from '../ModalSectionDeleteIcon/ModalSectionDeleteIcon';
import { NewSocial } from '../PersonModal';
Expand Down Expand Up @@ -70,7 +71,7 @@ export const PersonPhoneNumberItem: React.FC<Props> = ({
(number) => number.id === phoneNumber.id,
)?.source;

const locked = source !== 'MPDX' && source !== undefined;
const locked = !isEditableSource(source);

React.useEffect(() => {
setIsPrimaryChecked(index === primaryIndex);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useLoadConstantsQuery } from 'src/components/Constants/LoadConstants.ge
import { useLocale } from 'src/hooks/useLocale';
import { dateFormat } from 'src/lib/intlFormat';
import { getLocalizedPledgeFrequency } from 'src/utils/functions/getLocalizedPledgeFrequency';
import { sourceToStr } from 'src/utils/sourceHelper';
import { currencyFormat } from '../../../../../lib/intlFormat';
import { HandshakeIcon } from '../../ContactDetailsHeader/ContactHeaderSection/HandshakeIcon';
import { ContactDonorAccountsFragment } from '../ContactDonationsTab.generated';
Expand Down Expand Up @@ -111,7 +112,9 @@ export const PartnershipInfo: React.FC<PartnershipInfoProp> = ({ contact }) => {
t('No Frequency Set')
}`}
</LabelsAndText>
<LabelsAndText variant="subtitle1">{contact?.source}</LabelsAndText>
<LabelsAndText variant="subtitle1">
{sourceToStr(t, contact?.source)}
</LabelsAndText>
</Box>
</IconAndTextContainer>
<IconAndTextContainerCenter>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Contacts/ContactsMap/ContactsMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useTranslation } from 'react-i18next';
import { StatusEnum } from 'src/graphql/types.generated';
import { useContactPartnershipStatuses } from 'src/hooks/useContactPartnershipStatuses';
import theme from 'src/theme';
import { sourceToStr } from 'src/utils/sourceToStr';
import { sourceToStr } from 'src/utils/sourceHelper';
import {
ContactsContext,
ContactsType,
Expand Down
2 changes: 1 addition & 1 deletion src/components/Contacts/ContactsMap/ContactsMapPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { useTranslation } from 'react-i18next';
import { PhaseEnum, StatusEnum } from 'src/graphql/types.generated';
import { useContactPartnershipStatuses } from 'src/hooks/useContactPartnershipStatuses';
import theme from 'src/theme';
import { sourceToStr } from 'src/utils/sourceToStr';
import { sourceToStr } from 'src/utils/sourceHelper';
import { Coordinates } from './coordinates';

interface ContactMapsPanelProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { useLocale } from 'src/hooks/useLocale';
import { dateFormatShort } from 'src/lib/intlFormat';
import theme from 'src/theme';
import { getLocalizedContactStatus } from 'src/utils/functions/getLocalizedContactStatus';
import { sourceToStr } from 'src/utils/sourceHelper';
import Modal from '../../../common/Modal/Modal';
import {
ContactsContext,
Expand Down Expand Up @@ -165,7 +166,8 @@ export const MassActionsMergeModal: React.FC<MassActionsMergeModalProps> = ({
{contact.primaryAddress.state}{' '}
{contact.primaryAddress.postalCode}
<br />
{t('From')}: {contact.primaryAddress.source}
{t('From')}:{' '}
{sourceToStr(t, contact.primaryAddress.source)}
<br />
</>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { useLocale } from 'src/hooks/useLocale';
import i18n from 'src/lib/i18n';
import { dateFormatShort } from 'src/lib/intlFormat';
import theme from 'src/theme';
import { isEditableSource, sourceToStr } from 'src/utils/sourceHelper';
import EmailValidationForm from '../EmailValidationForm';
import { EmailAddressData, PersonEmailAddresses } from '../FixEmailAddresses';
import { PersonInvalidEmailFragment } from '../FixEmailAddresses.generated';
Expand Down Expand Up @@ -359,7 +360,10 @@ export const FixEmailAddressPerson: React.FC<FixEmailAddressPersonProps> = ({
</Typography>
</Hidden>
<Typography display="inline" variant="body2">
{`${email.source} (${dateFormatShort(
{`${sourceToStr(
t,
email.source,
)} (${dateFormatShort(
DateTime.fromISO(email.updatedAt),
locale,
)})`}
Expand Down Expand Up @@ -453,7 +457,7 @@ export const FixEmailAddressPerson: React.FC<FixEmailAddressPersonProps> = ({
setFieldValue('newEmail', e.target.value);
handleSubmit();
}}
disabled={email.source !== appName}
disabled={!isEditableSource(email.source)}
/>
<FormHelperText
error={true}
Expand All @@ -463,7 +467,7 @@ export const FixEmailAddressPerson: React.FC<FixEmailAddressPersonProps> = ({
</FormHelperText>
</FormControl>

{email.source === appName ? (
{isEditableSource(email.source) ? (
<Box
display="flex"
alignItems="center"
Expand Down
12 changes: 2 additions & 10 deletions src/components/Tool/FixEmailAddresses/FixEmailAddresses.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -596,11 +596,7 @@ describe('FixEmailAddresses-Home', () => {
} as { [key: string]: PersonEmailAddresses };
const defaultSource = 'MPDX';

const dataToSend = determineBulkDataToSend(
dataState,
defaultSource,
'MPDX',
);
const dataToSend = determineBulkDataToSend(dataState, defaultSource);

const emails = dataToSend[0].emailAddresses ?? [];
expect(emails[0].primary).toEqual(true);
Expand All @@ -625,11 +621,7 @@ describe('FixEmailAddresses-Home', () => {
} as { [key: string]: PersonEmailAddresses };
const defaultSource = 'DonorHub';

const dataToSend = determineBulkDataToSend(
dataState,
defaultSource,
'MPDX',
);
const dataToSend = determineBulkDataToSend(dataState, defaultSource);
expect(dataToSend.length).toEqual(0);
});
});
Expand Down
41 changes: 23 additions & 18 deletions src/components/Tool/FixEmailAddresses/FixEmailAddresses.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ import {
PersonEmailAddressInput,
PersonUpdateInput,
} from 'src/graphql/types.generated';
import {
manualSourceValue,
sourceToStr,
sourcesMatch,
} from 'src/utils/sourceHelper';
import theme from '../../../theme';
import { ConfirmButtonIcon } from '../ConfirmButtonIcon';
import NoData from '../NoData';
Expand Down Expand Up @@ -105,15 +110,12 @@ export const determineBulkDataToSend = (
[key: string]: PersonEmailAddresses;
},
defaultSource: string,
appName: string,
): PersonUpdateInput[] => {
const dataToSend = [] as PersonUpdateInput[];

Object.entries(dataState).forEach((value) => {
const primaryEmailAddress = value[1].emailAddresses.find(
(email) =>
email.source === defaultSource ||
(defaultSource === appName && email.source === 'MPDX'),
const primaryEmailAddress = value[1].emailAddresses.find((email) =>
sourcesMatch(defaultSource, email.source),
);
if (primaryEmailAddress) {
dataToSend.push({
Expand All @@ -137,8 +139,7 @@ export const FixEmailAddresses: React.FC<FixEmailAddressesProps> = ({
accountListId,
setContactFocus,
}) => {
const appName = process.env.APP_NAME ?? 'MPDX';
const [defaultSource, setDefaultSource] = useState(appName);
const [defaultSource, setDefaultSource] = useState(manualSourceValue);
const [showBulkConfirmModal, setShowBulkConfirmModal] = useState(false);
const { t } = useTranslation();
const { enqueueSnackbar } = useSnackbar();
Expand All @@ -152,12 +153,15 @@ export const FixEmailAddresses: React.FC<FixEmailAddressesProps> = ({
const [dataState, setDataState] = useState<{
[key: string]: PersonEmailAddresses;
}>({});
const [sourceOptions, setSourceOptions] = useState<string[]>([appName]);

const [sourceOptions, setSourceOptions] = useState<string[]>([
manualSourceValue,
]);

// Create a mutable copy of the query data and store in the state
useEffect(() => {
const existingSources = new Set<string>();
existingSources.add(appName);
existingSources.add(manualSourceValue);

const newDataState = data
? data.people.nodes?.reduce<{ [key: string]: PersonEmailAddresses }>(
Expand Down Expand Up @@ -255,11 +259,7 @@ export const FixEmailAddresses: React.FC<FixEmailAddressesProps> = ({
};

const handleBulkConfirm = async () => {
const dataToSend = determineBulkDataToSend(
dataState,
defaultSource ?? '',
appName,
);
const dataToSend = determineBulkDataToSend(dataState, defaultSource ?? '');

if (dataToSend.length) {
await updatePeople({
Expand Down Expand Up @@ -289,7 +289,9 @@ export const FixEmailAddresses: React.FC<FixEmailAddressesProps> = ({
});
} else {
enqueueSnackbar(
t(`No ${defaultSource} primary email address exists to update`),
t(`No {{source}} primary email address exists to update`, {
source: sourceToStr(t, defaultSource),
}),
{
variant: 'warning',
autoHideDuration: 7000,
Expand Down Expand Up @@ -328,7 +330,7 @@ export const FixEmailAddresses: React.FC<FixEmailAddressesProps> = ({
>
{sourceOptions.map((source) => (
<MenuItem key={source} value={source}>
{source}
{sourceToStr(t, source)}
</MenuItem>
))}
</SourceSelect>
Expand All @@ -339,7 +341,7 @@ export const FixEmailAddresses: React.FC<FixEmailAddressesProps> = ({
<ConfirmButtonIcon />
{t('Confirm {{amount}} as {{source}}', {
amount: data.people.nodes.length,
source: defaultSource,
source: sourceToStr(t, defaultSource),
})}
</ConfirmButton>
</DefaultSourceWrapper>
Expand Down Expand Up @@ -416,7 +418,10 @@ export const FixEmailAddresses: React.FC<FixEmailAddressesProps> = ({
handleClose={() => setShowBulkConfirmModal(false)}
mutation={handleBulkConfirm}
title={t('Confirm')}
message={t(`You are updating all contacts visible on this page, setting the first ${defaultSource} email address as the
message={t(`You are updating all contacts visible on this page, setting the first ${sourceToStr(
t,
defaultSource,
)} email address as the
primary email address. If no such email address exists the contact will not be updated.
Are you sure you want to do this?`)}
/>
Expand Down
19 changes: 8 additions & 11 deletions src/components/Tool/FixMailingAddresses/Contact.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { useSnackbar } from 'notistack';
import { useTranslation } from 'react-i18next';
import { makeStyles } from 'tss-react/mui';
import { SetContactFocus } from 'pages/accountLists/[accountListId]/tools/useToolsHelper';
import { editableSources } from 'src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/EditContactAddressModal/EditContactAddressModal';
import { useSetContactPrimaryAddressMutation } from 'src/components/Contacts/ContactDetails/ContactDetailsTab/Mailing/SetPrimaryAddress.generated';
import {
AddButton,
Expand All @@ -37,6 +36,7 @@ import { useContactPartnershipStatuses } from 'src/hooks/useContactPartnershipSt
import { useLocale } from 'src/hooks/useLocale';
import { useUpdateCache } from 'src/hooks/useUpdateCache';
import { dateFormatShort } from 'src/lib/intlFormat';
import { isEditableSource, sourceToStr } from 'src/utils/sourceHelper';
import theme from '../../../theme';
import { HandleSingleConfirmProps, emptyAddress } from './FixMailingAddresses';
import { ContactAddressFragment } from './GetInvalidAddresses.generated';
Expand Down Expand Up @@ -112,7 +112,6 @@ interface Props {
name: string;
status: string;
addresses: ContactAddressFragment[];
appName: string;
openEditAddressModal: (address: ContactAddressFragment, id: string) => void;
openNewAddressModal: (address: ContactAddressFragment, id: string) => void;
setContactFocus: SetContactFocus;
Expand All @@ -128,7 +127,6 @@ const Contact: React.FC<Props> = ({
name,
status,
addresses,
appName,
openEditAddressModal,
openNewAddressModal,
setContactFocus,
Expand Down Expand Up @@ -245,7 +243,7 @@ const Contact: React.FC<Props> = ({
</Typography>
</Hidden>
<Typography display="inline">
{address.source}{' '}
{sourceToStr(t, address.source)}{' '}
</Typography>
<Typography display="inline">
{dateFormatShort(
Expand Down Expand Up @@ -296,14 +294,16 @@ const Contact: React.FC<Props> = ({
>
<Box className={classes.address}>
<Typography>
{`${address.street}, ${address.city} ${
address.state ? address.state : ''
}. ${address.postalCode}`}
{`${address.street ? address.street : ''}, ${
address.city ? address.city : ''
} ${address.state ? address.state : ''} ${
address.postalCode ? address.postalCode : ''
}`}
</Typography>
</Box>

<ContactIconContainer aria-label={t('Edit Icon')}>
{editableSources.indexOf(address.source) > -1 ? (
{isEditableSource(address.source) ? (
<EditIcon />
) : (
<LockIcon />
Expand All @@ -321,9 +321,6 @@ const Contact: React.FC<Props> = ({
<strong>{t('Source')}: </strong>
</Typography>
</Hidden>
<Typography display="inline">
{t('{{appName}}', { appName })}
</Typography>
</Box>
Comment on lines 335 to 336
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've removed the source?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is not needed there.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed. As we allow users to create new addresses, this source was letting the user know that the add address they would create would be on MPDX and not on DonorHub or a third party like that.
Screenshot 2024-10-08 at 8 23 58 AM
Screenshot 2024-10-08 at 8 26 22 AM

Copy link
Contributor Author

@caleballdrin caleballdrin Oct 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think it made sense to have it there with the old UI. But now that we have a button, I don't think it makes sense from a UX perspective. The button is not a part of the table from a users point of view. So the "MPDX" text over there becomes more confusing than helpful.

If we really need the user to know that they are making an address in MPDX, then we should do it a different way.

In my opinion, I think it is self explanatory that if they create the address in MPDX, then the source will be MPDX. Just like if they create a new contact or person or donation or anything.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dropdown will be filled in with values that existing addresses have, and they can choose which source to create the address in. So, if they already have a DonorHub and an MPDX address, both will appear in the dropdown to choose. This impacts the logic for primary when saving as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is what Bill is referring to with the dropdown. There are 2 MPDX values. I assume this is due to one being something else like MPDX6 but then being changed to MPDX on the UI.

Screenshot 2024-10-09 at 9 24 25 AM

Copy link
Contributor

@dr-bizz dr-bizz Oct 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, I think it is self explanatory that if they create the address in MPDX, then the source will be MPDX. Just like if they create a new contact or person or donation or anything

I think it's best if we make sure the user knows they are creating the address on MPDX. As there are other sources listed, and hopefully to avoid confusion.

I'm open to changing how we tell the user a new address will be created on MPDX.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I will add the source to the Add Address button so it will look like: Add Address (MPDX)

</Box>
</Grid>
Expand Down
Loading
Loading