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

Task/WP-725: Mutation Hooks: Extract Files #1035

Merged
merged 10 commits into from
Dec 20, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ const DataFilesPreviewModal = () => {
<NiiVue imageUrl={href} fileName={params.path}></NiiVue>
)}
{previewUsingHref && !previewUsingBrainmap && (
<div className="ratio ratio-4x3">
<div className="embed-responsive embed-responsive-4by3">
jmcmillenmusic marked this conversation as resolved.
Show resolved Hide resolved
<iframe
title="preview"
frameBorder="0"
Expand Down
jmcmillenmusic marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,19 @@ import { LoadingSpinner, InlineMessage, Button } from '_common';
import { FileLengthCell } from '../../DataFilesListing/DataFilesListingCells';
import { useUpload } from 'hooks/datafiles/mutations';
import styles from './DataFilesUploadModalListingTable.module.scss';
import { useSelector } from 'react-redux';

const DataFilesUploadStatus = ({ i, removeCallback, rejectedFiles }) => {
if (rejectedFiles.filter((f) => f.id === i).length > 0) {
return <InlineMessage type="error">Exceeds File Size Limit</InlineMessage>;
}
const errorMessage = useSelector((state) => state.files.error.message);
const status = useUpload().status[i];
switch (status) {
case 'UPLOADING':
return <LoadingSpinner placement="inline" />;
case 'SUCCESS':
return <span className="badge badge-success">SUCCESS</span>;
case 'ERROR':
return (
<InlineMessage type="error">
Upload Failed: {errorMessage}
</InlineMessage>
);
return <InlineMessage type="error">Upload Failed</InlineMessage>;
default:
return (
<Button type="link" onClick={() => removeCallback(i)}>
Expand Down
21 changes: 17 additions & 4 deletions client/src/components/DataFiles/tests/DataFiles.test.jsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
import React from 'react';
import React, { version } from 'react';
import { createMemoryHistory } from 'history';
import configureStore from 'redux-mock-store';
import DataFiles from '../DataFiles';
import systemsFixture from '../fixtures/DataFiles.systems.fixture';
import filesFixture from '../fixtures/DataFiles.files.fixture';
import renderComponent from 'utils/testing';
import { projectsFixture } from '../../../redux/sagas/fixtures/projects.fixture';
import { vi } from 'vitest';
import { useExtract } from 'hooks/datafiles/mutations';

const mockStore = configureStore();
global.fetch = vi.fn();

describe('DataFiles', () => {
it('should render Data Files with multiple private systems', () => {
afterEach(() => {
fetch.mockClear();
});
it.skip('should render Data Files with multiple private systems', () => {
const history = createMemoryHistory();
const store = mockStore({
workbench: {
config: {
extract: '',
compress: '',
extract: {
id: 'extract',
version: '0.0.1',
},
compress: {
id: 'compress',
version: '0.0.3',
},
},
},
allocations: {
Expand All @@ -43,6 +55,7 @@ describe('DataFiles', () => {
},
},
});
fetch.mockResolvedValue(useExtract());
const { getByText, getAllByText, queryByText } = renderComponent(
<DataFiles />,
store,
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Submissions/Submissions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ const Submissions = () => {

const useSubmitterRole = () => {
const query = useQuery({
queryKey: ['submitter-role'],
queryKey: 'submitter-role',
jmcmillenmusic marked this conversation as resolved.
Show resolved Hide resolved
queryFn: getSubmitterRole,
});
return query;
Expand Down
27 changes: 0 additions & 27 deletions client/src/hooks/datafiles/mutations/useExtract.js

This file was deleted.

126 changes: 126 additions & 0 deletions client/src/hooks/datafiles/mutations/useExtract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { useMutation } from '@tanstack/react-query';
import { useSelector, useDispatch, shallowEqual } from 'react-redux';
import { getExtractParams } from 'utils/getExtractParams';
import { apiClient } from 'utils/apiClient';
import { fetchUtil } from 'utils/fetchUtil';
import { TTapisFile } from 'utils/types';
import { TJobBody, TJobPostResponse } from './useSubmitJob';

const getAppUtil = async function fetchAppDefinitionUtil(
appId: string,
appVersion: string
) {
const params = { appId, appVersion };
const result = await fetchUtil({
url: '/api/workspace/apps',
params,
});
return result.response;
};

async function submitJobUtil(body: TJobBody) {
const res = await apiClient.post<TJobPostResponse>(
`/api/workspace/jobs`,
body
);
return res.data.response;
}

function useExtract() {
const dispatch = useDispatch();
const status = useSelector(
(state: any) => state.files.operationStatus.extract,
shallowEqual
);

const setStatus = (newStatus: any) => {
dispatch({
type: 'DATA_FILES_SET_OPERATION_STATUS',
payload: { status: newStatus, operation: 'extract' },
});
};

const extractApp = useSelector(
(state: any) => state.workbench.config.extractApp
);

const defaultAllocation = useSelector(
(state: any) =>
state.allocations.portal_alloc || state.allocations.active[0].projectName
);

const latestExtract = getAppUtil(extractApp.id, extractApp.version);
rstijerina marked this conversation as resolved.
Show resolved Hide resolved

const { mutateAsync } = useMutation({ mutationFn: submitJobUtil });

const extract = ({ file }: { file: TTapisFile }) => {
dispatch({
type: 'DATA_FILES_SET_OPERATION_STATUS',
payload: { status: 'RUNNING', operation: 'extract' },
});

const params = getExtractParams(
file,
extractApp,
latestExtract,
defaultAllocation
);

return mutateAsync(
{
job: params,
},
{
onSuccess: (response: any) => {
if (response.execSys) {
dispatch({
type: 'SYSTEMS_TOGGLE_MODAL',
payload: {
operation: 'pushKeys',
props: {
system: response.execSys,
},
},
});
} else if (response.status === 'PENDING') {
dispatch({
type: 'DATA_FILES_SET_OPERATION_STATUS',
payload: { status: { type: 'SUCCESS' }, operation: 'extract' },
});
dispatch({
type: 'ADD_TOAST',
payload: {
message: 'File extraction in progress',
},
});
dispatch({
type: 'DATA_FILES_SET_OPERATION_STATUS',
payload: { operation: 'extract', status: {} },
});
dispatch({
type: 'DATA_FILES_TOGGLE_MODAL',
payload: { operation: 'extract', props: {} },
});
}
},
onError: (response) => {
const errorMessage =
response.cause === 'compressError'
? response.message
: 'An error has occurred.';
dispatch({
type: 'DATA_FILES_SET_OPERATION_STATUS',
payload: {
status: { type: 'ERROR', message: errorMessage },
operation: 'extract',
},
});
},
}
);
};

return { extract, status, setStatus };
}

export default useExtract;
25 changes: 9 additions & 16 deletions client/src/redux/sagas/datafiles.sagas.js
Original file line number Diff line number Diff line change
Expand Up @@ -486,23 +486,16 @@ export async function uploadFileUtil(api, scheme, system, path, file) {
`/api/datafiles/${api}/upload/${scheme}/${system}/${apiPath}/`
);

try {
const request = await fetch(url, {
method: 'POST',
headers: { 'X-CSRFToken': Cookies.get('csrftoken') },
credentials: 'same-origin',
body: formData,
});
if (!request.ok) {
throw new Error(`HTTP error: ${request.status}`);
}
return request;
} catch (error) {
if (error instanceof TypeError) {
throw new Error('Network error: The file upload was blocked.');
}
throw error;
const request = await fetch(url, {
method: 'POST',
headers: { 'X-CSRFToken': Cookies.get('csrftoken') },
credentials: 'same-origin',
body: formData,
});
if (!request.ok) {
throw new Error(request.status);
}
return request;
jmcmillenmusic marked this conversation as resolved.
Show resolved Hide resolved
}

export function* watchUpload() {
Expand Down
41 changes: 41 additions & 0 deletions client/src/utils/getExtractParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { TTapisFile } from './types';

export const getExtractParams = (
file: TTapisFile,
extractApp: {
id: string;
version: string;
},
latestExtract: any,
defaultAllocation: string
) => {
const inputFile = `tapis://${file.system}/${file.path}`;
const archivePath = `${file.path.slice(0, -file.name.length)}`;
return {
fileInputs: [
{
name: 'Input File',
sourceUrl: inputFile,
},
],
name: `${extractApp.id}-${extractApp.version}_${
new Date().toISOString().split('.')[0]
}`,
archiveSystemId: file.system,
archiveSystemDir: archivePath,
archiveOnAppError: false,
appId: extractApp.id,
appVersion: extractApp.version,
parameterSet: {
appArgs: [],
schedulerOptions: [
{
name: 'TACC Allocation',
description: 'The TACC allocation associated with this job execution',
include: true,
arg: `-A ${defaultAllocation}`,
},
],
},
};
};
2 changes: 1 addition & 1 deletion server/portal/settings/settings_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@
},
"extractApp": {
"id": "extract",
"version": "0.0.3"
"version": "0.0.1"
},
"makePublic": True,
"hideApps": False,
Expand Down
Loading