Skip to content

Commit

Permalink
♻️ Add support for NCIT fence
Browse files Browse the repository at this point in the history
  • Loading branch information
evans-g-crsj committed Nov 10, 2023
1 parent 708dcc8 commit be0eb54
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 66 deletions.
4 changes: 3 additions & 1 deletion src/store/fenceConnection/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { FENCE_NAMES } from 'common/fenceTypes';
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';

import { FENCE_NAMES } from 'common/fenceTypes';

import { fenceConnectionSelector } from './selector';
import { checkFenceAuthStatus, checkFencesAuthStatus } from './thunks';

Expand Down
80 changes: 35 additions & 45 deletions src/store/fenceConnection/thunks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,7 @@ const checkFenceAuthStatus = createAsyncThunk<
error,
data: {
auth: data!,
acls: [
'phs001138.c1',
'phs001138.c2',
'phs001138.c999',
'phs002330.c1',
'phs002330.c2',
'phs002330.c999',
],
acls: fenceAcls,
},
reject: thunkAPI.rejectWithValue,
});
Expand All @@ -71,50 +64,47 @@ const connectToFence = createAsyncThunk<
{
state: RootState;
}
>(
'fence/connection',
async (fence, thunkAPI) => {
const { fenceConnection } = thunkAPI.getState();
let fenceInfo = fenceConnection.fencesInfo[fence];
>('fence/connection', async (fence, thunkAPI) => {
const { fenceConnection } = thunkAPI.getState();
let fenceInfo = fenceConnection.fencesInfo[fence];

if (!fenceInfo) {
const { data } = await FenceApi.fetchInfo(fence);
fenceInfo = data;
}
if (!fenceInfo) {
const { data } = await FenceApi.fetchInfo(fence);
fenceInfo = data;
}

const authWindow = window.open(fenceInfo?.authorize_uri)!;

const authWindow = window.open(fenceInfo?.authorize_uri)!;
return new Promise((resolve, reject) => {
const interval = setInterval(async () => {
if (authWindow.closed) {
let fenceAcls: string[] = [];
const { data } = await FenceApi.isAuthenticated(fence);

return new Promise((resolve, reject) => {
const interval = setInterval(async () => {
if (authWindow.closed) {
let fenceAcls: string[] = [];
const { data } = await FenceApi.isAuthenticated(fence);
if (data?.authenticated) {
clearInterval(interval);

if (data?.authenticated) {
clearInterval(interval);

if (data?.authenticated) {
const { data: aclData } = await FenceApi.fetchAcls(fence);
fenceAcls = aclData?.acl || [];
}

resolve({
info: fenceInfo!,
acls: fenceAcls,
});
} else {
clearInterval(interval);
reject('failed authenticating');
const { data: aclData } = await FenceApi.fetchAcls(fence);
fenceAcls = aclData?.acl || [];
}

resolve({
info: fenceInfo!,
acls: fenceAcls,
});
} else {
clearInterval(interval);
reject('failed authenticating');
}
}, 1000);
setTimeout(() => {
clearInterval(interval);
reject('nothing');
}, TEN_MINUTES_IN_MS);
});
},
);
}
}, 1000);
setTimeout(() => {
clearInterval(interval);
reject('nothing');
}, TEN_MINUTES_IN_MS);
});
});

const disconnectFromFence = createAsyncThunk<any, FENCE_NAMES>(
'fence/disconnection',
Expand Down
13 changes: 6 additions & 7 deletions src/store/fenceStudies/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,18 @@ import { computeAllFencesAuthStudies } from './thunks';
export type { initialState as fenceStudiesInitialState } from './types';
export { default, FenceStudiesState } from './slice';

export const useFenceStudies = () => {
export const useFenceStudies = (fence: FENCE_NAMES) => {
const state = useSelector(fenceStudiesSelector);
const { connectionStatus, fencesConnectError, loadingFences } = useFenceConnection(
FENCE_NAMES.gen3,
);

const { connectionStatus, fencesConnectError, loadingFences } = useFenceConnection(fence);
const isConnected = (status: FENCE_CONNECTION_STATUSES) =>
status === FENCE_CONNECTION_STATUSES.connected;

return {
...state,
fenceStudiesAcls: computeAllFencesAuthStudies(state.studies),
isConnected: isConnected(connectionStatus.gen3),
connectionLoading: loadingFences.includes(FENCE_NAMES.gen3),
hasErrors: fencesConnectError.includes(FENCE_NAMES.gen3) || !isEmpty(state.fencesError),
isConnected: isConnected(connectionStatus[fence]),
connectionLoading: loadingFences.includes(fence),
hasErrors: fencesConnectError.includes(fence) || !isEmpty(state.fencesError),
};
};
12 changes: 10 additions & 2 deletions src/store/fenceStudies/thunks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ const getAuthStudyIdsAndCounts = async (
content: [
{
op: TermOperators.in,
content: { field: 'access_control', value: [FileAccessType.REGISTERED] },
content: { field: 'controlled_access', value: [FileAccessType.REGISTERED] },
},
],
},
Expand Down Expand Up @@ -246,7 +246,15 @@ export const computeAllFencesAuthStudies = (fenceStudies: TFenceStudies) => {
if (isEmpty(fenceStudies)) {
return [];
}
return flatMap(Object.values(fenceStudies), (studies) => studies.authorizedStudies);

return Object.values(fenceStudies)
.map((x) => x.authorizedStudies)
.flat()
.reduce((xs: TFenceStudy[], x: TFenceStudy) => {
// remove duplicates
const sId = x.id;
return xs.some((s) => s.id === sId) ? xs : [...xs, { ...x }];
}, []);
};

const replaceDashByUnderscore = (value: string) => value.replaceAll('-', '');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import CardErrorPlaceholder from 'views/Dashboard/components/CardErrorPlaceHolde
import CardHeader from 'views/Dashboard/components/CardHeader';
import { DashboardCardProps } from 'views/Dashboard/components/DashboardCards';

import { FENCE_NAMES } from 'common/fenceTypes';
import PopoverContentLink from 'components/uiKit/PopoverContentLink';
import { fenceConnectionActions } from 'store/fenceConnection/slice';
import { useFenceStudies } from 'store/fenceStudies';
Expand All @@ -23,16 +24,34 @@ import styles from './index.module.scss';

const AuthorizedStudies = ({ id, className = '' }: DashboardCardProps) => {
const dispatch = useDispatch();
const { loadingStudiesForFences, fenceStudiesAcls, isConnected, hasErrors, connectionLoading } =
useFenceStudies();
const {
loadingStudiesForFences,
fenceStudiesAcls,
isConnected: isGen3Connected,
hasErrors: hasGen3Errors,
connectionLoading: connectionGen3Loading,
} = useFenceStudies(FENCE_NAMES.gen3);

const {
//Shared: loadingStudiesForFences,
//Shared: fenceStudiesAcls,
isConnected: isDcfConnected,
hasErrors: hasDcfErrors,
connectionLoading: connectionDcfLoading,
} = useFenceStudies(FENCE_NAMES.dcf);

const fenceStudiesLoading = loadingStudiesForFences.length > 0;

const isOneFenceAtLeastConnected = isGen3Connected || isDcfConnected;
const hasAtLeastOneFenceWithErrors = hasGen3Errors || hasDcfErrors;
const connectionLoadingForAtLeastOneFence = connectionGen3Loading || connectionDcfLoading;

useEffect(() => {
if (isConnected) {
if (isOneFenceAtLeastConnected) {
dispatch(fetchAllFenceStudies());
}
// eslint-disable-next-line
}, [isConnected]);
}, [isOneFenceAtLeastConnected]);

return (
<GridCard
Expand All @@ -42,7 +61,7 @@ const AuthorizedStudies = ({ id, className = '' }: DashboardCardProps) => {
<CardHeader
id={id}
title={intl.get('screen.dashboard.cards.authorizedStudies.title', {
count: isConnected ? fenceStudiesAcls.length : 0,
count: isOneFenceAtLeastConnected ? fenceStudiesAcls.length : 0,
})}
infoPopover={{
title: intl.get('screen.dashboard.cards.authorizedStudies.infoPopover.title'),
Expand All @@ -66,7 +85,7 @@ const AuthorizedStudies = ({ id, className = '' }: DashboardCardProps) => {
}
content={
<div className={styles.authorizedWrapper}>
{isConnected && !hasErrors && !fenceStudiesLoading && (
{isOneFenceAtLeastConnected && !hasAtLeastOneFenceWithErrors && !fenceStudiesLoading && (
<Space className={styles.authenticatedHeader} direction="horizontal">
<Space align="start">
<SafetyOutlined className={styles.safetyIcon} />
Expand All @@ -81,7 +100,7 @@ const AuthorizedStudies = ({ id, className = '' }: DashboardCardProps) => {
dispatch(fenceConnectionActions.setConnectionModalParams({ open: true }))
}
className={styles.disconnectBtn}
loading={connectionLoading}
loading={connectionLoadingForAtLeastOneFence}
>
{intl.get('screen.dashboard.cards.authorizedStudies.manageConnections')}
</Button>
Expand All @@ -93,11 +112,11 @@ const AuthorizedStudies = ({ id, className = '' }: DashboardCardProps) => {
className={styles.authorizedStudiesList}
bordered
itemLayout="vertical"
loading={fenceStudiesLoading || connectionLoading}
loading={fenceStudiesLoading || connectionLoadingForAtLeastOneFence}
locale={{
emptyText: hasErrors ? (
emptyText: hasAtLeastOneFenceWithErrors ? (
<CardErrorPlaceholder />
) : isConnected ? (
) : isOneFenceAtLeastConnected ? (
<Empty
imageType="grid"
description={intl.get(
Expand All @@ -117,7 +136,9 @@ const AuthorizedStudies = ({ id, className = '' }: DashboardCardProps) => {
/>
),
}}
dataSource={isConnected && !hasErrors ? fenceStudiesAcls : []}
dataSource={
isOneFenceAtLeastConnected && !hasAtLeastOneFenceWithErrors ? fenceStudiesAcls : []
}
renderItem={(item) => <AuthorizedStudiesListItem id={item.id} data={item} />}
></List>
</div>
Expand Down

0 comments on commit be0eb54

Please sign in to comment.