Skip to content

Commit

Permalink
ISPN-14305 Execute a task
Browse files Browse the repository at this point in the history
  • Loading branch information
dpanshug committed Jan 19, 2023
1 parent 063fed0 commit 2efdf64
Show file tree
Hide file tree
Showing 6 changed files with 285 additions and 121 deletions.
222 changes: 115 additions & 107 deletions src/app/CacheManagers/TasksTableDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ import {
EmptyStateIcon,
EmptyStateVariant,
Pagination,
Stack,
StackItem,
Text,
TextContent,
TextVariants,
Title
Title,
Toolbar,
ToolbarItem,
ToolbarContent,
ToolbarItemVariant
} from '@patternfly/react-core';
import { TableComposable, Thead, Tr, Th, Tbody, Td, IAction, ActionsColumn } from '@patternfly/react-table';
import { SearchIcon } from '@patternfly/react-icons';
import displayUtils from '@services/displayUtils';
import {
Expand All @@ -25,71 +28,66 @@ import {
global_spacer_xs
} from '@patternfly/react-tokens';
import { useTranslation } from 'react-i18next';
import { ConsoleServices } from '@services/ConsoleServices';
import { useFetchTask } from '@app/services/tasksHook';
import { ExecuteTasks } from '@app/Tasks/ExecuteTasks';

const TasksTableDisplay = (props: { setTasksCount: (number) => void; isVisible: boolean }) => {
const [tasks, setTasks] = useState<Task[]>([]);
const { tasks, loading, error, reload } = useFetchTask();
const [filteredTasks, setFilteredTasks] = useState<Task[]>([]);

const [tasksPagination, setTasksPagination] = useState({
page: 1,
perPage: 10
});
const [rows, setRows] = useState<(string | any)[]>([]);
const [taskToExecute, setTaskToExecute] = useState<Task>();
const { t } = useTranslation();
const brandname = t('brandname.brandname');

const columns = [
{ title: t('cache-managers.task-name') },
{
title: t('cache-managers.task-type')
},
{
title: t('cache-managers.context-name')
},
{
title: t('cache-managers.operation-name')
},
{
title: t('cache-managers.parameters')
},
const columnNames = {
name: t('cache-managers.tasks.task-name'),
type: t('cache-managers.tasks.task-type'),
context: t('cache-managers.tasks.context-name'),
operation: t('cache-managers.tasks.operation-name'),
parameters: t('cache-managers.tasks.parameters'),
allowedRoles: t('cache-managers.tasks.allowed-role')
};

const rowActionItem = (row): IAction[] => [
{
title: t('cache-managers.allowed-role')
title: t('cache-managers.tasks.execute'),
onClick: () => {
setTaskToExecute(row);
}
}
];

useEffect(() => {
ConsoleServices.tasks()
.getTasks()
.then((maybeTasks) => {
if (maybeTasks.isRight()) {
setTasks(maybeTasks.value);
setFilteredTasks(maybeTasks.value);
props.setTasksCount(maybeTasks.value.length);
const initSlice = (tasksPagination.page - 1) * tasksPagination.perPage;
updateRows(maybeTasks.value.slice(initSlice, initSlice + tasksPagination.perPage));
} else {
// TODO: deal loading, error, empty status
}
});
}, []);
if (tasks) {
setFilteredTasks(tasks);
props.setTasksCount(tasks.length);
}
}, [loading, tasks, error]);

useEffect(() => {
if (filteredTasks) {
const initSlice = (tasksPagination.page - 1) * tasksPagination.perPage;
const updateRows = filteredTasks.slice(initSlice, initSlice + tasksPagination.perPage);
updateRows.length > 0 ? setRows(updateRows) : setRows([]);
}
}, [tasksPagination, filteredTasks]);

const onSetPage = (_event, pageNumber) => {
setTasksPagination({
page: pageNumber,
perPage: tasksPagination.perPage
...tasksPagination,
page: pageNumber
});
const initSlice = (pageNumber - 1) * tasksPagination.perPage;
updateRows(filteredTasks.slice(initSlice, initSlice + tasksPagination.perPage));
};

const onPerPageSelect = (_event, perPage) => {
setTasksPagination({
page: tasksPagination.page,
page: 1,
perPage: perPage
});
const initSlice = (tasksPagination.page - 1) * perPage;
updateRows(filteredTasks.slice(initSlice, initSlice + perPage));
};

const taskType = (type: string) => {
Expand All @@ -112,6 +110,9 @@ const TasksTableDisplay = (props: { setTasksCount: (number) => void; isVisible:
};

const taskParameters = (params: [string]) => {
if (params.length == 0) {
return <TextContent>{'-'}</TextContent>;
}
return (
<TextContent>
{params.map((param, index) => (
Expand All @@ -125,7 +126,7 @@ const TasksTableDisplay = (props: { setTasksCount: (number) => void; isVisible:

const taskAllowedRoles = (allowedRole: string) => {
if (allowedRole == null || allowedRole.trim().length == 0) {
return <TextContent>{t('cache-managers.allowed-role-null')}</TextContent>;
return <TextContent>{t('cache-managers.tasks.allowed-role-null')}</TextContent>;
}
return (
<TextContent>
Expand All @@ -134,78 +135,85 @@ const TasksTableDisplay = (props: { setTasksCount: (number) => void; isVisible:
);
};

const updateRows = (tasks: Task[]) => {
let rows: { heightAuto: boolean; cells: (string | any)[] }[];
if (!props.isVisible) {
return <span />;
}

if (tasks.length == 0) {
rows = [
{
heightAuto: true,
cells: [
{
props: { colSpan: 8 },
title: (
return (
<React.Fragment>
<Toolbar id="counters-table-toolbar">
<ToolbarContent>
<ToolbarItem variant={ToolbarItemVariant.pagination}>
<Pagination
itemCount={filteredTasks.length}
perPage={tasksPagination.perPage}
page={tasksPagination.page}
onSetPage={onSetPage}
widgetId="pagination-tasks"
onPerPageSelect={onPerPageSelect}
isCompact
/>
</ToolbarItem>
</ToolbarContent>
</Toolbar>
<TableComposable
className={'tasks-table'}
aria-label={t('cache-managers.tasks.tasks-table-label')}
variant={'compact'}
>
<Thead>
<Tr>
<Th colSpan={1}>{columnNames.name}</Th>
<Th colSpan={1}>{columnNames.type}</Th>
<Th colSpan={1}>{columnNames.context}</Th>
<Th colSpan={1}>{columnNames.operation}</Th>
<Th colSpan={1}>{columnNames.parameters}</Th>
<Th colSpan={1}>{columnNames.allowedRoles}</Th>
</Tr>
</Thead>
<Tbody>
{tasks.length == 0 ? (
<Tr>
<Td colSpan={6}>
<Bullseye>
<EmptyState variant={EmptyStateVariant.small}>
<EmptyStateIcon icon={SearchIcon} />
<Title headingLevel="h2" size="lg">
{t('cache-managers.no-tasks-status')}
{t('cache-managers.tasks.no-tasks-status')}
</Title>
<EmptyStateBody>{t('cache-managers.no-tasks-body')}</EmptyStateBody>
<EmptyStateBody>{t('cache-managers.tasks.no-tasks-body')}</EmptyStateBody>
</EmptyState>
</Bullseye>
)
}
]
}
];
} else {
rows = tasks.map((task) => {
return {
heightAuto: true,
cells: [
{ title: task.name },
{ title: taskType(task.type) },
{ title: task.task_context_name },
{ title: task.task_operation_name },
{ title: taskParameters(task.parameters) },
{ title: taskAllowedRoles(task.allowed_role) }
]
//TODO {title: <TasksActionLinks name={task.name}/>}]
};
});
}
setRows(rows);
};

if (!props.isVisible) {
return <span />;
}

return (
<Stack>
<StackItem>
<Pagination
itemCount={filteredTasks.length}
perPage={tasksPagination.perPage}
page={tasksPagination.page}
onSetPage={onSetPage}
widgetId="pagination-tasks"
onPerPageSelect={onPerPageSelect}
isCompact
/>
<Table
aria-label={t('cache-managers.tasks-table-label')}
cells={columns}
rows={rows}
className={'tasks-table'}
variant={TableVariant.compact}
>
<TableHeader />
<TableBody />
</Table>
</StackItem>
</Stack>
</Td>
</Tr>
) : (
rows.map((row) => {
return (
<Tr key={row.name}>
<Td dataLabel={columnNames.name}>{row.name}</Td>
<Td dataLabel={columnNames.type}>{taskType(row.type)}</Td>
<Td dataLabel={columnNames.context}>{row.task_context_name}</Td>
<Td dataLabel={columnNames.operation}>{row.task_operation_name}</Td>
<Td dataLabel={columnNames.parameters}>{taskParameters(row.parameters)}</Td>
<Td dataLabel={columnNames.allowedRoles}>{taskAllowedRoles(row.allowed_role)}</Td>
<Td isActionCell>
<ActionsColumn items={rowActionItem(row)} />
</Td>
</Tr>
);
})
)}
</Tbody>
</TableComposable>
<ExecuteTasks
task={taskToExecute}
isModalOpen={taskToExecute != undefined}
closeModal={() => {
setTaskToExecute(undefined);
reload();
}}
/>
</React.Fragment>
);
};

Expand Down
81 changes: 81 additions & 0 deletions src/app/Tasks/ExecuteTasks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { useEffect, useState } from 'react';
import {
Button,
ButtonVariant,
Form,
FormGroup,
Modal,
ModalVariant,
Text,
TextContent,
TextInput
} from '@patternfly/react-core';
import { useExecuteTask } from '@app/services/tasksHook';
import { useTranslation } from 'react-i18next';

const ExecuteTasks = (props: { task; isModalOpen: boolean; closeModal: () => void }) => {
const { t } = useTranslation();
const [paramsValue, setParamsValue] = useState({});
const { onExecute } = useExecuteTask(props.task?.name, paramsValue);

useEffect(() => {
const obj = props.task?.parameters?.reduce((o, key) => ({ ...o, [key]: '' }), {});
setParamsValue(obj);
}, [props.task]);

const onValueChange = (parameter, value) => {
setParamsValue((prevState) => ({
...prevState,
[parameter]: value
}));
};

return (
<Modal
height={'1000px'}
id={'execute-task-modal'}
variant={ModalVariant.medium}
isOpen={props.isModalOpen}
title={t('cache-managers.tasks.execution')}
onClose={props.closeModal}
aria-label={t('cache-managers.tasks.execution')}
disableFocusTrap={true}
actions={[
<Button
key={'Confirm'}
aria-label={'Confirm'}
variant={ButtonVariant.primary}
onClick={() => {
onExecute();
props.closeModal();
}}
>
{t('cache-managers.tasks.execute')}
</Button>,
<Button key={'Cancel'} aria-label={'Cancel'} variant={ButtonVariant.link} onClick={props.closeModal}>
{t('cache-managers.tasks.cancel')}
</Button>
]}
>
<TextContent>
<Text>
There are multiple parameters on the script <strong>{props.task?.name}</strong>. Select a parameter to run
script.
</Text>
</TextContent>
{props.task !== undefined && (
<Form style={{ paddingTop: '3%' }} isHorizontal onSubmit={(e) => e.preventDefault()}>
{props.task.parameters?.map((p) => {
return (
<FormGroup key={p} isStack label={p}>
<TextInput type="text" onChange={(val) => onValueChange(p, val)} />
</FormGroup>
);
})}
</Form>
)}
</Modal>
);
};

export { ExecuteTasks };
Loading

0 comments on commit 2efdf64

Please sign in to comment.