Skip to content

Commit

Permalink
added hide and unhide job functionality (#356)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaeestee authored Apr 4, 2024
1 parent e7b5735 commit c501566
Show file tree
Hide file tree
Showing 16 changed files with 26,578 additions and 34 deletions.
26,274 changes: 26,241 additions & 33 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions src/tapis-api/jobs/hideJob.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Jobs } from '@tapis/tapis-typescript';
import { apiGenerator, errorDecoder } from 'tapis-api/utils';

const hideJob = (jobUuid: string, basePath: string, jwt: string) => {
const api: Jobs.JobsApi = apiGenerator<Jobs.JobsApi>(
Jobs,
Jobs.JobsApi,
basePath,
jwt
);
return errorDecoder<Jobs.RespHideJob>(() => api.hideJob({ jobUuid }));
};

export default hideJob;
2 changes: 2 additions & 0 deletions src/tapis-api/jobs/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 submit } from './submit';
export { default as cancel } from './cancel';
export { default as hideJob } from './hideJob';
export { default as unhideJob } from './unhideJob';
14 changes: 14 additions & 0 deletions src/tapis-api/jobs/unhideJob.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Jobs } from '@tapis/tapis-typescript';
import { apiGenerator, errorDecoder } from 'tapis-api/utils';

const unhideJob = (jobUuid: string, basePath: string, jwt: string) => {
const api: Jobs.JobsApi = apiGenerator<Jobs.JobsApi>(
Jobs,
Jobs.JobsApi,
basePath,
jwt
);
return errorDecoder<Jobs.RespHideJob>(() => api.unhideJob({ jobUuid }));
};

export default unhideJob;
3 changes: 2 additions & 1 deletion src/tapis-app/Jobs/_Layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { JobsNav } from '../_components';
import { JobsNav, JobsLayoutToolbar } from '../_components';
import { Router } from '../_Router';
import {
PageLayout,
Expand All @@ -12,6 +12,7 @@ const Layout: React.FC = () => {
const header = (
<LayoutHeader>
<div>Jobs</div>
<JobsLayoutToolbar />
</LayoutHeader>
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React, { useState } from 'react';
import { Button } from 'reactstrap';
import { Icon } from 'tapis-ui/_common';
import styles from './JobsToolbar.module.scss';
import { useLocation } from 'react-router-dom';
import ConfirmModal from 'tapis-ui/_common/ConfirmModal';
import useHideJob from 'tapis-hooks/jobs/useHideJob';
import UnhideJobModal from './UnhideJobModal';

type ToolbarButtonProps = {
text: string;
icon: string;
onClick: () => void;
disabled: boolean;
};

export type ToolbarModalProps = {
toggle: () => void;
};

export const ToolbarButton: React.FC<ToolbarButtonProps> = ({
text,
icon,
onClick,
disabled = true,
...rest
}) => {
return (
<div>
<Button
disabled={disabled}
onClick={onClick}
className={styles['toolbar-btn']}
{...rest}
>
<Icon name={icon}></Icon>
<span> {text}</span>
</Button>
</div>
);
};

const JobsLayoutToolbar: React.FC = () => {
const url = window.location.href;
const jobUuid = url.substring(url.indexOf('jobs/') + 5);
console.log(jobUuid.includes('jobs'));
const [modal, setModal] = useState<string | undefined>(undefined);
const { pathname } = useLocation();
const { isLoading, isError, isSuccess, error, hideJob } = useHideJob();

const toggle = () => {
setModal(undefined);
};

return (
<div id="file-operation-toolbar">
{pathname && (
<div className={styles['toolbar-wrapper']}>
<ToolbarButton
text="Hide Job"
icon="trash"
disabled={jobUuid.includes('jobs')}
onClick={() => setModal('ConfirmModal')}
aria-label="hideJob"
/>
<ToolbarButton
text="Unhide Job"
icon="trash"
disabled={false}
onClick={() => setModal('UnhideJobModal')}
aria-label="unhideJob"
/>

{modal === 'ConfirmModal' && (
<ConfirmModal
toggle={toggle}
onConfirm={() => {
hideJob(jobUuid);
}}
isLoading={isLoading}
isError={isError}
isSuccess={isSuccess}
error={error}
/>
)}
{modal === 'UnhideJobModal' && <UnhideJobModal toggle={toggle} />}
</div>
)}
</div>
);
};

export default JobsLayoutToolbar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.toolbar-wrapper {
padding: 0;
margin: 0;
margin-top: 0.5em;
display: flex !important;
}

.toolbar-btn {
height: 2rem;
align-items: center;
margin-left: 0.5em;
font-size: 0.7em !important;
border-radius: 0 !important;
background-color: #f4f4f4 !important;
color: #333333 !important;
}

.toolbar-btn:disabled {
color: #999999 !important;
}
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,77 @@
import { Button } from 'reactstrap';
import { GenericModal } from 'tapis-ui/_common';
import { SubmitWrapper } from 'tapis-ui/_wrappers';
import { ToolbarModalProps } from '../JobsLayoutToolbar';
import { Formik, Form } from 'formik';
import { FormikInput } from 'tapis-ui/_common/FieldWrapperFormik';
import { useEffect } from 'react';
import styles from './UnhideJobModal.module.scss';
import * as Yup from 'yup';
import { useUnhideJob } from 'tapis-hooks/jobs';

const UnhideJobModal: React.FC<ToolbarModalProps> = ({ toggle }) => {
const { unhideJob, isLoading, error, isSuccess, reset } = useUnhideJob();

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

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

const initialValues = {
jobUuid: '',
};

const onSubmit = ({ jobUuid }: { jobUuid: string }) => {
unhideJob(jobUuid);
};

return (
<GenericModal
toggle={toggle}
title="Unhide a Job"
body={
<div className={styles['modal-settings']}>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onSubmit}
>
<Form id="unhideJob-form">
<FormikInput
name="jobUuid"
label="Job Uuid"
required={true}
description={`Job Uuid`}
aria-label="Input"
/>
</Form>
</Formik>
</div>
}
footer={
<SubmitWrapper
className={styles['modal-footer']}
isLoading={isLoading}
error={error}
success={isSuccess ? `Successfully unhid a job` : ''}
reverse={true}
>
<Button
form="unhideJob-form"
color="primary"
disabled={isLoading || isSuccess}
aria-label="Submit"
type="submit"
>
Unhide job
</Button>
</SubmitWrapper>
}
/>
);
};

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

export default UnhideJobModal;
3 changes: 3 additions & 0 deletions src/tapis-app/Jobs/_components/JobsLayoutToolbar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import JobsLayoutToolbar from './JobsLayoutToolbar';

export default JobsLayoutToolbar;
1 change: 1 addition & 0 deletions src/tapis-app/Jobs/_components/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as JobsNav } from './JobsNav';
export { default as JobsToolbar } from './JobsToolbar';
export { default as JobsLayoutToolbar } from './JobsLayoutToolbar';
2 changes: 2 additions & 0 deletions src/tapis-hooks/jobs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ export { default as useList } from './useList';
export { default as useDetails } from './useDetails';
export { default as useSubmit } from './useSubmit';
export { default as useCancel } from './useCancel';
export { default as useHideJob } from './useHideJob';
export { default as useUnhideJob } from './useUnhideJob';
2 changes: 2 additions & 0 deletions src/tapis-hooks/jobs/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const QueryKeys = {
details: 'jobs/details',
submit: 'jobs/submit',
cancel: 'jobs/cancel',
hideJob: 'jobs/hideJob',
unhideJob: 'jobs/unhideJob',
};

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

type HideJobHookParams = {
jobUuid: string;
};

const useHideJob = () => {
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<Jobs.RespHideJob, Error, HideJobHookParams>(
[QueryKeys.hideJob, basePath, jwt],
({ jobUuid }) => hideJob(jobUuid, basePath, jwt)
);

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

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

type UnhideJobHookParams = {
jobUuid: string;
};

const useUnhideJob = () => {
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<Jobs.RespHideJob, Error, UnhideJobHookParams>(
[QueryKeys.unhideJob, basePath, jwt],
({ jobUuid }) => unhideJob(jobUuid, basePath, jwt)
);

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

export default useUnhideJob;

0 comments on commit c501566

Please sign in to comment.