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

Pushing previous ability to create a system, fixes of jobLauncher, and new Delete and Undelete functionality to Tapis UI #345

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
14 changes: 14 additions & 0 deletions src/tapis-api/systems/deleteSystem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Systems } from '@tapis/tapis-typescript';
import { apiGenerator, errorDecoder } from 'tapis-api/utils';

const deleteSystem = (systemId: string, basePath: string, jwt: string) => {
const api: Systems.SystemsApi = apiGenerator<Systems.SystemsApi>(
Systems,
Systems.SystemsApi,
basePath,
jwt
);
return errorDecoder<Systems.RespBasic>(() => api.deleteSystem({ systemId }));
};

export default deleteSystem;
2 changes: 2 additions & 0 deletions src/tapis-api/systems/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ export { default as list } from './list';
export { default as details } from './details';
export { default as listSchedulerProfiles } from './schedulerProfiles';
export { default as makeNewSystem } from './makeNewSystem';
export { default as deleteSystem } from './deleteSystem';
export { default as undeleteSystem } from './undeleteSystem';
16 changes: 16 additions & 0 deletions src/tapis-api/systems/undeleteSystem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Systems } from '@tapis/tapis-typescript';
import { apiGenerator, errorDecoder } from 'tapis-api/utils';

const undeleteSystem = (systemId: string, basePath: string, jwt: string) => {
const api: Systems.SystemsApi = apiGenerator<Systems.SystemsApi>(
Systems,
Systems.SystemsApi,
basePath,
jwt
);
return errorDecoder<Systems.RespBasic>(() =>
api.undeleteSystem({ systemId })
);
};

export default undeleteSystem;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.modal-settings {
max-height: 38rem;
overflow-y: scroll;
}

.item {
border: 1px dotted lightgray;
padding: 0.5em 0.5em 0.5em 0.5em;
margin-bottom: 1em;
}

.array {
border: 1px solid gray;
padding: 0.5em 0.5em 0.5em 0.5em;
margin-bottom: 0.5em;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { Button } from 'reactstrap';
import { Systems } from '@tapis/tapis-typescript';
import { GenericModal } from 'tapis-ui/_common';
import { SubmitWrapper } from 'tapis-ui/_wrappers';
import { ToolbarModalProps } from '../SystemToolbar';
import { Form, Formik } from 'formik';
import { FormikSelect } from 'tapis-ui/_common/FieldWrapperFormik';
import { useDeleteSystem, useList } from 'tapis-hooks/systems';
import { useEffect, useCallback } from 'react';
import styles from './DeleteSystemModal.module.scss';
import * as Yup from 'yup';
import { useQueryClient } from 'react-query';
import { default as queryKeys } from 'tapis-hooks/systems/queryKeys';
import { useTapisConfig } from 'tapis-hooks';

const DeleteSystemModal: React.FC<ToolbarModalProps> = ({ toggle }) => {
const { claims } = useTapisConfig();
const effectiveUserId = claims['sub'].substring(
0,
claims['sub'].lastIndexOf('@')
);
const { data } = useList({ search: `owner.like.${effectiveUserId}` }); //{search: `owner.like.${''}`,}
const systems: Array<Systems.TapisSystem> = data?.result ?? [];

//Allows the system list to update without the user having to refresh the page
const queryClient = useQueryClient();
const onSuccess = useCallback(() => {
queryClient.invalidateQueries(queryKeys.list);
}, [queryClient]);

const { deleteSystem, isLoading, error, isSuccess, reset } =
useDeleteSystem();

useEffect(() => {
reset();
}, [reset]);

const validationSchema = Yup.object({
systemId: Yup.string(),
});

const initialValues = {
systemId: '',
};

const onSubmit = ({ systemId }: { systemId: string }) => {
deleteSystem(systemId, { onSuccess });
};

return (
<GenericModal
toggle={toggle}
title="Delete System"
body={
<div className={styles['modal-settings']}>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmit}
>
{() => (
<Form id="newsystem-form">
<FormikSelect
name="systemId"
description="The system id"
label="System ID"
required={true}
data-testid="systemId"
>
<option disabled value={''}>
Select a system to delete
</option>
{systems.length ? (
systems.map((system) => {
return <option>{system.id}</option>;
})
) : (
<i>No systems found</i>
)}
</FormikSelect>
</Form>
)}
</Formik>
</div>
}
footer={
<SubmitWrapper
className={styles['modal-footer']}
isLoading={isLoading}
error={error}
success={isSuccess ? `Successfully deleted a system` : ''}
reverse={true}
>
<Button
form="newsystem-form"
color="primary"
disabled={isLoading || isSuccess}
aria-label="Submit"
type="submit"
>
Delete system
</Button>
</SubmitWrapper>
}
/>
);
};

export default DeleteSystemModal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import DeleteSystemModal from './DeleteSystemModal';

export default DeleteSystemModal;
20 changes: 20 additions & 0 deletions src/tapis-app/Systems/_components/SystemToolbar/SystemToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { Icon } from 'tapis-ui/_common';
import styles from './SystemToolbar.module.scss';
import { useLocation } from 'react-router-dom';
import CreateSystemModal from './CreateSystemModal';
import DeleteSystemModal from './DeleteSystemModal';
import UndeleteSystemModal from './UndeleteSystemModal';

type ToolbarButtonProps = {
text: string;
Expand Down Expand Up @@ -56,8 +58,26 @@ const SystemToolbar: React.FC = () => {
onClick={() => setModal('createsystem')}
aria-label="createSystem"
/>
<ToolbarButton
text="Delete a System"
icon="trash"
disabled={false}
onClick={() => setModal('deletesystem')}
aria-label="deleteSystem"
/>
<ToolbarButton
text="Re-Add a System"
icon="add"
disabled={false}
onClick={() => setModal('undeletesystem')}
aria-label="undeleteSystem"
/>

{modal === 'createsystem' && <CreateSystemModal toggle={toggle} />}
{modal === 'deletesystem' && <DeleteSystemModal toggle={toggle} />}
{modal === 'undeletesystem' && (
<UndeleteSystemModal toggle={toggle} />
)}
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.modal-settings {
max-height: 38rem;
overflow-y: scroll;
}

.item {
border: 1px dotted lightgray;
padding: 0.5em 0.5em 0.5em 0.5em;
margin-bottom: 1em;
}

.array {
border: 1px solid gray;
padding: 0.5em 0.5em 0.5em 0.5em;
margin-bottom: 0.5em;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { Button } from 'reactstrap';
import { Systems } from '@tapis/tapis-typescript';
import { GenericModal } from 'tapis-ui/_common';
import { SubmitWrapper } from 'tapis-ui/_wrappers';
import { ToolbarModalProps } from '../SystemToolbar';
import { Form, Formik } from 'formik';
import { FormikSelect } from 'tapis-ui/_common/FieldWrapperFormik';
import { useUndeleteSystem, useDeletedList } from 'tapis-hooks/systems';
import { useEffect, useCallback } from 'react';
import styles from './UndeleteSystemModal.module.scss';
import * as Yup from 'yup';
import { useQueryClient } from 'react-query';
import { default as queryKeys } from 'tapis-hooks/systems/queryKeys';

const UndeleteSystemModal: React.FC<ToolbarModalProps> = ({ toggle }) => {
const { data } = useDeletedList();
const systems: Array<Systems.TapisSystem> = data?.result ?? [];

//Allows the system list to update without the user having to refresh the page
const queryClient = useQueryClient();
const onSuccess = useCallback(() => {
queryClient.invalidateQueries(queryKeys.list);
}, [queryClient]);

const { undeleteSystem, isLoading, error, isSuccess, reset } =
useUndeleteSystem();

useEffect(() => {
reset();
}, [reset]);

const validationSchema = Yup.object({
systemId: Yup.string(),
});

const initialValues = {
systemId: '',
};

const onSubmit = ({ systemId }: { systemId: string }) => {
undeleteSystem(systemId, { onSuccess });
};

return (
<GenericModal
toggle={toggle}
title="Re-add a System"
body={
<div className={styles['modal-settings']}>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmit}
>
{() => (
<Form id="newsystem-form">
<FormikSelect
name="systemId"
description="The system id"
label="System ID"
required={true}
data-testid="systemId"
>
<option disabled value={''}>
Select a system to re-add
</option>
{systems.length ? (
systems.map((system) => {
return <option>{system.id}</option>;
})
) : (
<i>No systems found</i>
)}
</FormikSelect>
</Form>
)}
</Formik>
</div>
}
footer={
<SubmitWrapper
className={styles['modal-footer']}
isLoading={isLoading}
error={error}
success={isSuccess ? `Successfully re-added a system` : ''}
reverse={true}
>
<Button
form="newsystem-form"
color="primary"
disabled={isLoading || isSuccess}
aria-label="Submit"
type="submit"
>
Re-add system
</Button>
</SubmitWrapper>
}
/>
);
};

export default UndeleteSystemModal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import UndeleteSystemModal from './UndeleteSystemModal';

export default UndeleteSystemModal;
3 changes: 3 additions & 0 deletions src/tapis-hooks/systems/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export { default as useList } from './useList';
export { default as useDeletedList } from './useDeletedList';
export { default as useDetails } from './useDetails';
export { default as useSchedulerProfiles } from './useSchedulerProfiles';
export { default as useMakeNewSystem } from './useMakeNewSystem';
export { default as useDeleteSystem } from './useDeleteSystem';
export { default as useUndeleteSystem } from './useUndeleteSystem';
1 change: 1 addition & 0 deletions src/tapis-hooks/systems/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const QueryKeys = {
details: 'systems/details',
listSchedulerProfiles: 'systems/listScehdulerProfiles',
makeNewSystem: 'systems/makeNewSystem',
deleteSystem: 'systems/deleteSystem',
};

export default QueryKeys;
44 changes: 44 additions & 0 deletions src/tapis-hooks/systems/useDeleteSystem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useMutation, MutateOptions } from 'react-query';
import { Systems } from '@tapis/tapis-typescript';
import { deleteSystem } from '../../tapis-api/systems';
import { useTapisConfig } from '../context';
import QueryKeys from './queryKeys';

type DeleteSystemHookParams = {
systemId: string;
};

const useDeleteSystem = () => {
const { basePath, accessToken } = useTapisConfig();
const jwt = accessToken?.access_token || '';

// The useMutation react-query hook is used to call operations that make server-side changes
// (Other hooks would be used for data retrieval)
//
// In this case, mkdir helper is called to perform the operation
const { mutate, isLoading, isError, isSuccess, data, error, reset } =
useMutation<Systems.RespBasic, Error, DeleteSystemHookParams>(
[QueryKeys.deleteSystem, basePath, jwt],
({ systemId }) => deleteSystem(systemId, basePath, jwt)
);

// Return hook object with loading states and login function
return {
isLoading,
isError,
isSuccess,
data,
error,
reset,
deleteSystem: (
systemId: string,
// react-query options to allow callbacks such as onSuccess
options?: MutateOptions<Systems.RespBasic, Error, DeleteSystemHookParams>
) => {
// Call mutate to trigger a single post-like API operation
return mutate({ systemId }, options);
},
};
};

export default useDeleteSystem;
Loading
Loading