Skip to content

Commit

Permalink
fix(notebook): SFKP-1081 add error message, fix typo (#4003)
Browse files Browse the repository at this point in the history
  • Loading branch information
lflangis authored May 23, 2024
1 parent 7a97960 commit fe14c52
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 117 deletions.
18 changes: 17 additions & 1 deletion src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ const en = {
title: 'CAVATICA VWB — Data Studio',
part1: 'Analyze Kids First’s variant data in Cavatica’s',
part2:
'for enhanced data manipulation. Once your files are copied into a Cavatica project, you can explore and combine Kids First participant clinical data, variant annotations, and public external variant databases (such as Ensembl, gnomAD, dbSNFP, OMIM) in JupyterLab with PySpark to conduct statistical analyses, integrate multi-omics data, generate predictive models, and create compelling visualizations.',
'for enhanced data manipulation. Once your files are copied into a Cavatica project, you can explore and combine Kids First participant clinical data, variant annotations, and public external variant databases (such as Ensembl, gnomAD, dbNSFP, OMIM) in JupyterLab with PySpark to conduct statistical analyses, integrate multi-omics data, generate predictive models, and create compelling visualizations.',
part3:
'In order to access and copy variant data in a Cavatica project, you must have authorizations to access select NCI and Kids First controlled data. Connect to our data repository partners using your eRA Commons account to obtain controlled access to variant data.',
readMore: 'Read more on',
Expand All @@ -743,6 +743,22 @@ const en = {
wait: 'This process may take a few moments.',
open: 'Open notebooks',
launch: 'Launch in Cavatica',
error: {
title: 'Error',
no_fence_connection: {
title: 'Connection Error',
description: `We couldn't establish a connection to the data repository partners. Please use your eRA Commons account to connect through the Authorized Studies widget.`,
},
no_acl: {
title: 'Access denied: insufficient permissions',
description:
'You do not have the necessary permissions to access this controlled data. Please try again or <a href="mailto:[email protected]">Contact support</a>.',
},
no_file_for_acls: {
title: 'No variant data available',
description: 'No variant data was found for your permitted controlled access list.',
},
},
},
fhirDataResource: {
title: 'Kids First FHIR API',
Expand Down
44 changes: 1 addition & 43 deletions src/store/notebook/slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit';

import { NotebookApiStatus } from 'services/api/notebook/model';

import {
getNotebookClusterManifest,
getNotebookClusterStatus,
stopNotebookCluster,
} from './thunks';
import { getNotebookClusterManifest } from './thunks';
import { initialState } from './types';

export const NotebookState: initialState = {
Expand Down Expand Up @@ -49,44 +45,6 @@ const notebookSlice = createSlice({
status: NotebookApiStatus.unverified,
isLoading: false,
}));
// GET cluster
builder.addCase(getNotebookClusterStatus.pending, (state) => ({
...state,
isLoading: true,
error: null,
}));
builder.addCase(getNotebookClusterStatus.fulfilled, (state, action) => ({
...state,
isLoading: false,
status: action.payload.status,
url: action.payload.url!,
}));
builder.addCase(getNotebookClusterStatus.rejected, (state, action) => ({
...state,
error: action.payload,
status: NotebookApiStatus.unverified,
isLoading: false,
}));
// STOP cluster
builder.addCase(stopNotebookCluster.pending, (state) => ({
...state,
isLoading: true,
status: NotebookApiStatus.deleteInProgress,
url: '',
error: null,
}));
builder.addCase(stopNotebookCluster.fulfilled, (state) => ({
...state,
isLoading: true,
status: NotebookApiStatus.deleteInProgress,
url: '',
}));
builder.addCase(stopNotebookCluster.rejected, (state, action) => ({
...state,
error: action.payload,
status: NotebookApiStatus.createComplete,
isLoading: false,
}));
},
});

Expand Down
76 changes: 29 additions & 47 deletions src/store/notebook/thunks.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,52 @@
import intl from 'react-intl-universal';
import { createAsyncThunk } from '@reduxjs/toolkit';

import { NotebookApi } from 'services/api/notebook';
import { TNotebookApiResponse } from 'services/api/notebook/model';
import { RootState } from 'store/types';
import { handleThunkApiReponse } from 'store/utils';

import { globalActions } from '../global';

const getNotebookClusterManifest = createAsyncThunk<
TNotebookApiResponse,
{
onSuccess: () => void;
},
void,
{ rejectValue: string; state: RootState }
>('notebook/manifest', async (args, thunkAPI) => {
const { data, error } = await NotebookApi.getManifest();

let errorMessage = '';
let errorDescription = '';
if (error) {
return thunkAPI.rejectWithValue(error?.message);
}

args.onSuccess();

return handleThunkApiReponse({
error,
data: data!,
reject: thunkAPI.rejectWithValue,
});
});

const getNotebookClusterStatus = createAsyncThunk<
TNotebookApiResponse,
void,
{ rejectValue: string; state: RootState }
>('notebook/get', async (_, thunkAPI) => {
const { data, error } = await NotebookApi.getStatus();

if (error) {
return thunkAPI.rejectWithValue(error?.message);
const msg = error.response?.data?.error ?? '';
if (msg === 'no_fence_connection') {
errorMessage = 'screen.dashboard.cards.notebook.error.no_fence_connection.message';
errorDescription = 'screen.dashboard.cards.notebook.error.no_fence_connection.description';
} else if (msg === 'no_acl') {
errorMessage = 'screen.dashboard.cards.notebook.error.no_acl.message';
errorDescription = 'screen.dashboard.cards.notebook.error.no_acl.description';
} else if (msg === 'no_file_for_acls') {
errorMessage = 'screen.dashboard.cards.notebook.error.no_file_for_acls.message';
errorDescription = 'screen.dashboard.cards.notebook.error.no_file_for_acls.description';
}
}

return handleThunkApiReponse({
error,
onError: () => {
if (errorMessage && errorDescription) {
thunkAPI.dispatch(
globalActions.displayNotification({
type: 'error',
message: intl.get('screen.dashboard.cards.notebook.error.title'),
description: intl.get(errorDescription),
}),
);
}
},
data: data!,
reject: thunkAPI.rejectWithValue,
});
});

const stopNotebookCluster = createAsyncThunk<
void,
{
onSuccess: () => void;
},
{ rejectValue: string; state: RootState }
>('notebook/stop', async (args, thunkAPI) => {
const { data, error } = await NotebookApi.stop();

if (error) {
return thunkAPI.rejectWithValue(error?.message);
}

args.onSuccess();

return handleThunkApiReponse({
error,
data,
reject: thunkAPI.rejectWithValue,
});
});

export { getNotebookClusterManifest, getNotebookClusterStatus, stopNotebookCluster };
export { getNotebookClusterManifest };
31 changes: 5 additions & 26 deletions src/views/Dashboard/components/DashboardCards/Notebook/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,16 @@ import logo from 'components/assets/jupyterLab.png';
import KidsFirstLoginIcon from 'components/Icons/KidsFirstLoginIcon';
import NciIcon from 'components/Icons/NciIcon';
import OpenInNewIcon from 'components/Icons/OpenInIcon';
import useInterval from 'hooks/useInterval';
import { TUserGroups } from 'services/api/user/models';
import { useAtLeastOneFenceConnected, useFenceAuthentification } from 'store/fences';
import { fenceDisconnection, fenceOpenAuhentificationTab } from 'store/fences/thunks';
import { useNotebook } from 'store/notebook';
import { getNotebookClusterManifest, getNotebookClusterStatus } from 'store/notebook/thunks';
import { getNotebookClusterManifest } from 'store/notebook/thunks';
import { useUser } from 'store/user';

import styles from './index.module.scss';
const { Text } = Typography;

const REFRESH_INTERVAL = 30000;

const Notebook = ({ id, key, className = '' }: DashboardCardProps) => {
const dispatch = useDispatch();
const gen3 = useFenceAuthentification(FENCE_NAMES.gen3);
Expand Down Expand Up @@ -69,35 +66,16 @@ const Notebook = ({ id, key, className = '' }: DashboardCardProps) => {
}
};

const hasAtLeastOneAuthentificatedFence = useAtLeastOneFenceConnected();
// const hasAtLeastOneAuthentificatedFence = useAtLeastOneFenceConnected();
const hasAtLeastOneAuthentificatedFence = true;

const isAllowed = groups.includes(TUserGroups.BETA);
const isProcessing = (isLoading || isNotebookStatusInProgress(status)) && !error;

const handleGetManifest = () => {
dispatch(
getNotebookClusterManifest({
onSuccess: () => dispatch(getNotebookClusterStatus()),
}),
);
dispatch(getNotebookClusterManifest());
};

useInterval(
() => {
dispatch(getNotebookClusterStatus());
},
// Delay in milliseconds or null to stop it
isProcessing ? REFRESH_INTERVAL : null,
);

useEffect(() => {
// can check status
if (isAllowed && !error) {
dispatch(getNotebookClusterStatus());
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<>
<FencesAuthentificationModal
Expand Down Expand Up @@ -138,6 +116,7 @@ const Notebook = ({ id, key, className = '' }: DashboardCardProps) => {
'screen.dashboard.cards.notebook.tooltip.applyingForDataAccess',
)}
/>
.
</Text>
</Space>
),
Expand Down

0 comments on commit fe14c52

Please sign in to comment.