Skip to content

Commit

Permalink
Organizations add account for oauth done. import tntconnect mostly do…
Browse files Browse the repository at this point in the history
…ne without graphQL and done all that I can without Graphql mutations
  • Loading branch information
dr-bizz committed Jul 25, 2023
1 parent d9a43b8 commit 4f2e977
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 44 deletions.
1 change: 1 addition & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ module.exports = withPlugins([
REST_API_URL:
process.env.REST_API_URL ?? 'https://api.stage.mpdx.org/api/v2/',
SITE_URL: siteUrl,
OAUTH_URL: process.env.OAUTH_URL ?? 'https://auth.stage.mpdx.org',
CLIENT_ID: process.env.CLIENT_ID ?? '4027334344069527005',
CLIENT_SECRET: process.env.CLIENT_SECRET,
BEACON_TOKEN: process.env.BEACON_TOKEN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { styled } from '@mui/material/styles';
import { Button, Typography, List, ListItemText, Alert } from '@mui/material';
import { StyledFormLabel } from '../../../../src/components/Shared/Forms/Field';
import { Confirmation } from 'src/components/common/Modal/Confirmation/Confirmation';
import { TheKeyAccordian } from 'src/components/Settings/integrations/TheKeyAccordian';
import { TheKeyAccordian } from 'src/components/Settings/integrations/Key/TheKeyAccordian';
import { OrganizationAccordian } from 'src/components/Settings/integrations/Organization/OrganizationAccordian';

const StyledListItem = styled(ListItemText)(() => ({
Expand Down Expand Up @@ -55,7 +55,7 @@ const Integrations: React.FC = () => {
pageTitle={t('Connect Services')}
pageHeading={t('Connect Services')}
>
<AccordionGroup title={t('')}>
<AccordionGroup title="">
<TheKeyAccordian
handleAccordionChange={handleAccordionChange}
expandedPanel={expandedPanel}
Expand Down
7 changes: 7 additions & 0 deletions src/components/Settings/integrations/Key/Key.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
query GetKeyAccounts {
user {
keyAccounts {
email
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useTranslation } from 'react-i18next';
import { Box, TextField } from '@mui/material';
import Skeleton from '@mui/material/Skeleton';
import { AccordionItem } from 'src/components/Shared/Forms/Accordions/AccordionItem';
import { FormWrapper } from 'src/components/Shared/Forms/Fields/FormWrapper';
import { FieldWrapper } from 'src/components/Shared/Forms/FieldWrapper';
import { StyledOutlinedInput } from 'src/components/Shared/Forms/Field';
import { useGetKeyAccountsQuery } from './Key.generated';

interface TheKeyAccordianProps {
handleAccordionChange: (panel: string) => void;
Expand All @@ -14,11 +15,8 @@ export const TheKeyAccordian: React.FC<TheKeyAccordianProps> = ({
expandedPanel,
}) => {
const { t } = useTranslation();

const handleSubmit = () => {
return;
};

const { data, loading } = useGetKeyAccountsQuery();
const keyAccounts = data?.user?.keyAccounts;

This comment has been minimized.

Copy link
@wrandall22

wrandall22 Jul 25, 2023

Contributor

Is this referring to accounts in The Key? If so, how much rewording to Okta makes sense?

return (
<AccordionItem
onAccordionChange={handleAccordionChange}
Expand All @@ -32,11 +30,19 @@ export const TheKeyAccordian: React.FC<TheKeyAccordianProps> = ({
/>
}
>
<FormWrapper onSubmit={handleSubmit} isValid={true} isSubmitting={false}>
<FieldWrapper labelText={t('Email Address')} helperText={''}>
<StyledOutlinedInput />
</FieldWrapper>
</FormWrapper>
{loading && <Skeleton height="90px" />}
{!loading &&
keyAccounts?.map((account, idx) => (
<Box style={{ marginTop: '20px' }} key={`email-${idx}`}>
<FieldWrapper>
<TextField
label={t('Email Address')}
value={account.email}
disabled={true}
/>
</FieldWrapper>
</Box>
))}
</AccordionItem>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { OrganizationAddAccountModal } from './OrganizationAddAccountModal';
import { OrganizationImportDataSyncModal } from './OrganizationImportDataSyncModal';
import { useGetUsersOrganizationsQuery } from './Organizations.generated';
import { Organization } from '../../../../../graphql/types.generated';
import { oAuth, sync } from './OrganizationService';

interface OrganizationAccordianProps {
handleAccordionChange: (panel: string) => void;
Expand Down Expand Up @@ -80,13 +81,37 @@ export const OrganizationAccordian: React.FC<OrganizationAccordianProps> = ({
const [selectedOrganization, setSelectedOrganization] =
useState<Omit<Organization, 'createdAt' | 'updatedAt'>>();
const [showAddAccountModal, setShowAddAccountModal] = useState(false);
const [showSyncAccountModal, setShowSyncAccountModal] = useState(false);
const [showImportDataSyncModal, setShowImportDataSyncModal] = useState(false);
const [showReconnectModal, setShowReconnectModal] = useState(false);

const { data, loading } = useGetUsersOrganizationsQuery();
const organizations = data?.userOrganizationAccounts;

const handleReconnect = async (organizationId) => {
// TODO
await oAuth(organizationId);
};

const handleSync = async (
organization: Omit<Organization, 'createdAt' | 'updatedAt'>,
) => {
// TODO
await sync();
return organization;
};

const handleEdit = async (
organization: Omit<Organization, 'createdAt' | 'updatedAt'>,
) => {
// TODO
return organization;
};
const handleDelete = async (
organization: Omit<Organization, 'createdAt' | 'updatedAt'>,
) => {
// TODO
return organization;
};

return (
<AccordionItem
onAccordionChange={handleAccordionChange}
Expand Down Expand Up @@ -158,7 +183,7 @@ export const OrganizationAccordian: React.FC<OrganizationAccordianProps> = ({
sx={{ m: '0 0 0 10px' }}
onClick={() => {
setSelectedOrganization(organization);
setShowSyncAccountModal(true);
handleSync(organization);
}}
>
Sync
Expand All @@ -184,20 +209,21 @@ export const OrganizationAccordian: React.FC<OrganizationAccordianProps> = ({
variant="contained"
size="small"
sx={{ m: '0 0 0 10px' }}
onClick={() => {
setSelectedOrganization(organization);
setShowReconnectModal(true);
}}
onClick={() => handleReconnect(organization.id)}
>
Reconnect
</StyledServicesButton>
)}
{type === OrganizationTypesEnum.LOGIN && (
<OrganizationDeleteIconButton>
<OrganizationDeleteIconButton
onClick={() => handleEdit(organization)}
>
<Edit />
</OrganizationDeleteIconButton>
)}
<OrganizationDeleteIconButton>
<OrganizationDeleteIconButton
onClick={() => handleDelete(organization)}
>
<DeleteIcon />
</OrganizationDeleteIconButton>
</Box>
Expand Down Expand Up @@ -246,22 +272,12 @@ export const OrganizationAccordian: React.FC<OrganizationAccordianProps> = ({
handleClose={() => setShowAddAccountModal(false)}
/>
)}
{showSyncAccountModal && (
<OrganizationAddAccountModal
handleClose={() => setShowSyncAccountModal(false)}
/>
)}
{showImportDataSyncModal && (
<OrganizationImportDataSyncModal
handleClose={() => setShowImportDataSyncModal(false)}
organization={selectedOrganization}
/>
)}
{showReconnectModal && (
<OrganizationAddAccountModal
handleClose={() => setShowSyncAccountModal(false)}
/>
)}
</AccordionItem>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
getOrganizationType,
OrganizationTypesEnum,
} from './OrganizationAccordian';
import { oAuth } from './OrganizationService';

interface OrganizationAddAccountModalProps {
handleClose: () => void;
Expand All @@ -51,13 +52,27 @@ export const OrganizationAddAccountModal: React.FC<
OrganizationAddAccountModalProps
> = ({ handleClose }) => {
const { t } = useTranslation();
const [showWarning, setShowWarning] = useState<OrganizationTypesEnum>();
const [organizationType, setOrganizationType] =
useState<OrganizationTypesEnum>();
const { data: organizations, loading } = useGetOrganizationsQuery();

const onSubmit = (attributes) => {
// TODO
return attributes;
const onSubmit = async (attributes) => {
const { apiClass, oauth, id } = attributes.selectedOrganization;
const type = getOrganizationType(apiClass, oauth);

if (type === OrganizationTypesEnum.OAUTH) {
window.location.href = await oAuth(id);
return;
}
if (type === OrganizationTypesEnum.LOGIN) {
// TODO - Add GraphQl to Update account by Mutating organization
return;
}

// TODO - Add GraphQl to creating an account by Mutating organization

handleClose();
return;
};

const showOrganizationHelp = () => {
Expand Down Expand Up @@ -85,7 +100,7 @@ export const OrganizationAddAccountModal: React.FC<
.string()
.when('selectedOrganization', (organization, schema) => {
if (
getOrganizationType(organization.apiClass, organization.oauth) ===
getOrganizationType(organization?.apiClass, organization?.oauth) ===
OrganizationTypesEnum.LOGIN
) {
return schema.required('Must enter username');
Expand All @@ -96,7 +111,7 @@ export const OrganizationAddAccountModal: React.FC<
.string()
.when('selectedOrganization', (organization, schema) => {
if (
getOrganizationType(organization.apiClass, organization.oauth) ===
getOrganizationType(organization?.apiClass, organization?.oauth) ===
OrganizationTypesEnum.LOGIN
) {
return schema.required('Must enter password');
Expand Down Expand Up @@ -138,7 +153,7 @@ export const OrganizationAddAccountModal: React.FC<
loading={loading}
value={selectedOrganization}
onChange={(_, value) => {
setShowWarning(
setOrganizationType(
getOrganizationType(value?.apiClass, value?.oauth),
);
setFieldValue('selectedOrganization', value);
Expand Down Expand Up @@ -171,7 +186,7 @@ export const OrganizationAddAccountModal: React.FC<
</Button>
)}

{showWarning === OrganizationTypesEnum.MINISTRY && (
{organizationType === OrganizationTypesEnum.MINISTRY && (
<WarningBox>
<Typography
variant="h6"
Expand Down Expand Up @@ -226,7 +241,7 @@ export const OrganizationAddAccountModal: React.FC<
</WarningBox>
)}

{showWarning === OrganizationTypesEnum.OAUTH && (
{organizationType === OrganizationTypesEnum.OAUTH && (
<WarningBox>
<Typography color={theme.palette.mpdxYellow.contrastText}>
{t(
Expand All @@ -236,7 +251,7 @@ export const OrganizationAddAccountModal: React.FC<
</WarningBox>
)}

{showWarning === OrganizationTypesEnum.LOGIN && (
{organizationType === OrganizationTypesEnum.LOGIN && (
<>
<StyledBox marginTop={4}>
<FieldWrapper>
Expand Down Expand Up @@ -271,7 +286,10 @@ export const OrganizationAddAccountModal: React.FC<
<DialogActions>
<CancelButton onClick={handleClose} disabled={isSubmitting} />
<SubmitButton disabled={!isValid || isSubmitting}>
{t('Add Account')}
{organizationType !== OrganizationTypesEnum.OAUTH &&
t('Add Account')}
{organizationType === OrganizationTypesEnum.OAUTH &&
t('Connect')}
</SubmitButton>
</DialogActions>
</form>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { getSession } from 'next-auth/react';
import Router from 'next/router';
import { getQueryParam } from 'src/utils/queryParam';

export const oAuth = async (
organizationId,
route = 'preferences/integrations?selectedTab=organization',
) => {
const session = await getSession();
const redirectUrl = encodeURIComponent(`${window.location.origin}/${route}`);
const token = session?.user.apiToken;
const accountListId = getQueryParam(Router.query, 'accountListId');
return (
`${process.env.OAUTH_URL}/auth/user/donorhub?account_list_id=${accountListId}` +
`&redirect_to=${redirectUrl}` +
`&access_token=${token}` +
`&organization_id=${organizationId}`
);
};

export const sync = async () => {
// TODO
return new Promise((resolve) => {
return resolve;
});
};

0 comments on commit 4f2e977

Please sign in to comment.