The tasks page now display my assignments
This commit is contained in:
parent
4ed3545e42
commit
a456fbbdbc
65
src/modules/manager/tasks/components/tasksTable.tsx
Normal file
65
src/modules/manager/tasks/components/tasksTable.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import React, { useCallback, useMemo } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Namespaces } from "../../../../i18n/i18n";
|
||||||
|
import Column from "../../../../components/common/columns";
|
||||||
|
import Table, {
|
||||||
|
PublishedTableProps,
|
||||||
|
} from "../../../../components/common/Table";
|
||||||
|
import { GetMyAssignments } from "../services/tasksService";
|
||||||
|
import TaskTypeAndNameDisplayPanel from "../../workflowTemplates/components/TaskTypeAndNameDisplayPanel";
|
||||||
|
|
||||||
|
export interface TasksTableProps extends PublishedTableProps<GetMyAssignments> {}
|
||||||
|
|
||||||
|
const TasksTable: React.FC<TasksTableProps> = ({
|
||||||
|
data,
|
||||||
|
sortColumn,
|
||||||
|
onChangePage,
|
||||||
|
onSearch,
|
||||||
|
onDelete,
|
||||||
|
onSort,
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation(Namespaces.Common);
|
||||||
|
|
||||||
|
const columns: Column<GetMyAssignments>[] = useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
key: "taskName",
|
||||||
|
label: t("Name"),
|
||||||
|
content: (item) => {
|
||||||
|
return (
|
||||||
|
<TaskTypeAndNameDisplayPanel
|
||||||
|
taskName={item.taskName}
|
||||||
|
taskType={item.taskType}
|
||||||
|
showValidationErrorIcon={false}
|
||||||
|
allowWordWrap={false}
|
||||||
|
reserveValidationErrorIconSpace={false}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
order: "asc",
|
||||||
|
},
|
||||||
|
{ key: "user", label: t("User"), order: "asc" },
|
||||||
|
{ key: "role", label: t("Role"), order: "asc" },
|
||||||
|
{ key: "startDateTime", label: t("StartDateTime"), order: "asc" },
|
||||||
|
],
|
||||||
|
[t],
|
||||||
|
);
|
||||||
|
|
||||||
|
const raiseSort = (sortCol: Column<GetMyAssignments>) => {
|
||||||
|
if (onSort !== undefined) onSort(sortCol);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
data={data}
|
||||||
|
keyName="id"
|
||||||
|
columns={columns}
|
||||||
|
sortColumn={sortColumn}
|
||||||
|
onSort={raiseSort}
|
||||||
|
onChangePage={onChangePage}
|
||||||
|
onSearch={onSearch}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TasksTable;
|
||||||
@ -5,7 +5,16 @@ import MapToJson from "../../../../utils/MapToJson";
|
|||||||
|
|
||||||
const apiEndpoint = "/Tasks";
|
const apiEndpoint = "/Tasks";
|
||||||
|
|
||||||
export interface GetMyTasks {}
|
export interface GetMyAssignments {
|
||||||
|
Id: bigint;
|
||||||
|
Guid: string;
|
||||||
|
|
||||||
|
taskType: string;
|
||||||
|
taskName: string;
|
||||||
|
user?: GeneralIdRef;
|
||||||
|
role?: GeneralIdRef;
|
||||||
|
startDateTime?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
export async function myTasks(
|
export async function myTasks(
|
||||||
page: number,
|
page: number,
|
||||||
@ -13,9 +22,9 @@ export async function myTasks(
|
|||||||
sortKey: string,
|
sortKey: string,
|
||||||
sortAscending: boolean,
|
sortAscending: boolean,
|
||||||
filters?: Map<string, string> | undefined,
|
filters?: Map<string, string> | undefined,
|
||||||
): Promise<Paginated<GetMyTasks>> {
|
): Promise<Paginated<GetMyAssignments>> {
|
||||||
const filterString = MapToJson(filters);
|
const filterString = MapToJson(filters);
|
||||||
const response = await httpService.get<Paginated<GetMyTasks>>(
|
const response = await httpService.get<Paginated<GetMyAssignments>>(
|
||||||
apiEndpoint + "/myTasks",
|
apiEndpoint + "/myTasks",
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
|
|||||||
@ -7,19 +7,20 @@ import Button, { ButtonType } from "../../../components/common/Button";
|
|||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
import Loading from "../../../components/common/Loading";
|
import Loading from "../../../components/common/Loading";
|
||||||
import Permission from "../../../components/common/Permission";
|
import Permission from "../../../components/common/Permission";
|
||||||
import tasksService, { GetMyTasks } from "./services/tasksService";
|
import tasksService, { GetMyAssignments } from "./services/tasksService";
|
||||||
|
import TasksTable from "./components/tasksTable";
|
||||||
|
|
||||||
const Tasks: React.FC = () => {
|
const Tasks: React.FC = () => {
|
||||||
const { t } = useTranslation(Namespaces.Common);
|
const { t } = useTranslation(Namespaces.Common);
|
||||||
const [loaded, setLoaded] = useState(false);
|
const [loaded, setLoaded] = useState(false);
|
||||||
const [pagedData, setPagedData] = useState<Paginated<GetMyTasks>>({
|
const [pagedData, setPagedData] = useState<Paginated<GetMyAssignments>>({
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
count: 0,
|
count: 0,
|
||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
data: [],
|
data: [],
|
||||||
});
|
});
|
||||||
const [sortColumn, setSortColumn] = useState<Column<GetMyTasks>>({
|
const [sortColumn, setSortColumn] = useState<Column<GetMyAssignments>>({
|
||||||
key: "displayName",
|
key: "displayName",
|
||||||
label: t("Name"),
|
label: t("Name"),
|
||||||
order: "asc",
|
order: "asc",
|
||||||
@ -47,7 +48,7 @@ const Tasks: React.FC = () => {
|
|||||||
[filters, sortColumn.key, sortColumn.order],
|
[filters, sortColumn.key, sortColumn.order],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onSort = async (newSortColumn: Column<GetMyTasks>) => {
|
const onSort = async (newSortColumn: Column<GetMyAssignments>) => {
|
||||||
const { page, pageSize } = pagedData;
|
const { page, pageSize } = pagedData;
|
||||||
const data = await tasksService.myTasks(
|
const data = await tasksService.myTasks(
|
||||||
page,
|
page,
|
||||||
@ -114,18 +115,14 @@ const Tasks: React.FC = () => {
|
|||||||
{t("CreateActivity")}
|
{t("CreateActivity")}
|
||||||
</Button>
|
</Button>
|
||||||
</Permission>
|
</Permission>
|
||||||
<>My Tasks go here</>
|
|
||||||
<Loading loaded={loaded}>
|
<Loading loaded={loaded}>
|
||||||
My Tasks go here
|
<TasksTable
|
||||||
{/* <UsersTable
|
data={pagedData}
|
||||||
data={pagedData}
|
sortColumn={sortColumn}
|
||||||
sortColumn={sortColumn}
|
onChangePage={changePage}
|
||||||
onChangePage={changePage}
|
onSort={onSort}
|
||||||
onSort={onSort}
|
onSearch={onSearch}
|
||||||
onSearch={onSearch}
|
/>
|
||||||
onDelete={onDelete}
|
|
||||||
resendConfirmEmail={resentConfirmEmail}
|
|
||||||
/> */}
|
|
||||||
</Loading>
|
</Loading>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,99 +1,30 @@
|
|||||||
import { useEffect } from "react";
|
|
||||||
import templateVersionsService, {
|
|
||||||
TaskMetadata,
|
|
||||||
TaskDefinition,
|
|
||||||
} from "../services/WorkflowTemplateService";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import FontAwesomeStringIcon from "../../../../components/common/FontAwesomeStringIcon";
|
import { TaskDefinition } from "../services/WorkflowTemplateService";
|
||||||
import ValidationErrorIcon from "../../../../components/validationErrorIcon";
|
import TaskTypeAndNameDisplayPanel from "./TaskTypeAndNameDisplayPanel";
|
||||||
|
|
||||||
export interface TaskNameDisplayPanel {
|
export interface TaskNameDisplayPanelProps {
|
||||||
task: TaskDefinition;
|
task: TaskDefinition;
|
||||||
showValidationErrorIcon: boolean;
|
showValidationErrorIcon: boolean;
|
||||||
allowWordWrap?: boolean;
|
allowWordWrap?: boolean;
|
||||||
reserveValidationErrorIconSpace?: boolean;
|
reserveValidationErrorIconSpace?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TaskNameDisplayPanel: React.FC<TaskNameDisplayPanel> = ({
|
const TaskNameDisplayPanel: React.FC<TaskNameDisplayPanelProps> = ({
|
||||||
task,
|
task,
|
||||||
showValidationErrorIcon = false,
|
showValidationErrorIcon = false,
|
||||||
allowWordWrap = false,
|
allowWordWrap = false,
|
||||||
reserveValidationErrorIconSpace = false,
|
reserveValidationErrorIconSpace = false,
|
||||||
}) => {
|
}) => {
|
||||||
const [tasksMetadata, setTasksMetadata] = React.useState<TaskMetadata[]>([]);
|
|
||||||
const [isNameTruncated, setIsNameTruncated] = React.useState(false);
|
|
||||||
const taskNameRef = React.useRef<HTMLSpanElement | null>(null);
|
|
||||||
const taskName = task.config.name as string;
|
const taskName = task.config.name as string;
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const fetchTaskMetadata = async () => {
|
|
||||||
const meta = await templateVersionsService.getTaskMetadata("GeneralTask");
|
|
||||||
setTasksMetadata(meta);
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchTaskMetadata();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const taskMetadataByType = React.useMemo(() => {
|
|
||||||
const map = new Map<string, TaskMetadata>();
|
|
||||||
tasksMetadata.forEach((meta) => {
|
|
||||||
map.set(meta.taskType, meta);
|
|
||||||
});
|
|
||||||
return map;
|
|
||||||
}, [tasksMetadata]);
|
|
||||||
|
|
||||||
const meta = taskMetadataByType.get(task.type);
|
|
||||||
const panelClassName = allowWordWrap
|
|
||||||
? "task-name-display-panel task-name-display-panel--wrap"
|
|
||||||
: "task-name-display-panel";
|
|
||||||
|
|
||||||
const updateTruncationState = React.useCallback(() => {
|
|
||||||
const el = taskNameRef.current;
|
|
||||||
|
|
||||||
if (!el || allowWordWrap) {
|
|
||||||
setIsNameTruncated(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsNameTruncated(el.scrollWidth > el.clientWidth);
|
|
||||||
}, [allowWordWrap]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
updateTruncationState();
|
|
||||||
}, [taskName, allowWordWrap, updateTruncationState]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const el = taskNameRef.current;
|
|
||||||
if (!el || allowWordWrap || typeof ResizeObserver === "undefined") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const observer = new ResizeObserver(() => {
|
|
||||||
updateTruncationState();
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.observe(el);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
observer.disconnect();
|
|
||||||
};
|
|
||||||
}, [allowWordWrap, updateTruncationState]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={panelClassName}>
|
<TaskTypeAndNameDisplayPanel
|
||||||
<FontAwesomeStringIcon icon={meta?.icon} />
|
taskName={taskName}
|
||||||
<span
|
taskType={task.type}
|
||||||
ref={taskNameRef}
|
showValidationErrorIcon={showValidationErrorIcon}
|
||||||
className="task-name-display-panel__name"
|
allowWordWrap={allowWordWrap}
|
||||||
title={isNameTruncated ? taskName : undefined}
|
reserveValidationErrorIconSpace={reserveValidationErrorIconSpace}
|
||||||
>
|
/>
|
||||||
{taskName}
|
|
||||||
</span>
|
|
||||||
<ValidationErrorIcon
|
|
||||||
visible={showValidationErrorIcon}
|
|
||||||
reserveSpace={reserveValidationErrorIconSpace}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,101 @@
|
|||||||
|
import React, { useEffect } from "react";
|
||||||
|
import templateVersionsService, {
|
||||||
|
TaskMetadata,
|
||||||
|
} from "../services/WorkflowTemplateService";
|
||||||
|
import FontAwesomeStringIcon from "../../../../components/common/FontAwesomeStringIcon";
|
||||||
|
import ValidationErrorIcon from "../../../../components/validationErrorIcon";
|
||||||
|
|
||||||
|
export interface TaskTypeAndNameDisplayPanelProps {
|
||||||
|
taskName: string;
|
||||||
|
taskType: string;
|
||||||
|
showValidationErrorIcon: boolean;
|
||||||
|
allowWordWrap?: boolean;
|
||||||
|
reserveValidationErrorIconSpace?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TaskTypeAndNameDisplayPanel: React.FC<
|
||||||
|
TaskTypeAndNameDisplayPanelProps
|
||||||
|
> = ({
|
||||||
|
taskName,
|
||||||
|
taskType,
|
||||||
|
showValidationErrorIcon = false,
|
||||||
|
allowWordWrap = false,
|
||||||
|
reserveValidationErrorIconSpace = false,
|
||||||
|
}) => {
|
||||||
|
const [tasksMetadata, setTasksMetadata] = React.useState<TaskMetadata[]>([]);
|
||||||
|
const [isNameTruncated, setIsNameTruncated] = React.useState(false);
|
||||||
|
const taskNameRef = React.useRef<HTMLSpanElement | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchTaskMetadata = async () => {
|
||||||
|
const meta = await templateVersionsService.getTaskMetadata("GeneralTask");
|
||||||
|
setTasksMetadata(meta);
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchTaskMetadata();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const taskMetadataByType = React.useMemo(() => {
|
||||||
|
const map = new Map<string, TaskMetadata>();
|
||||||
|
tasksMetadata.forEach((meta) => {
|
||||||
|
map.set(meta.taskType, meta);
|
||||||
|
});
|
||||||
|
return map;
|
||||||
|
}, [tasksMetadata]);
|
||||||
|
|
||||||
|
const meta = taskMetadataByType.get(taskType);
|
||||||
|
const panelClassName = allowWordWrap
|
||||||
|
? "task-name-display-panel task-name-display-panel--wrap"
|
||||||
|
: "task-name-display-panel";
|
||||||
|
|
||||||
|
const updateTruncationState = React.useCallback(() => {
|
||||||
|
const el = taskNameRef.current;
|
||||||
|
|
||||||
|
if (!el || allowWordWrap) {
|
||||||
|
setIsNameTruncated(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsNameTruncated(el.scrollWidth > el.clientWidth);
|
||||||
|
}, [allowWordWrap]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
updateTruncationState();
|
||||||
|
}, [taskName, allowWordWrap, updateTruncationState]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const el = taskNameRef.current;
|
||||||
|
if (!el || allowWordWrap || typeof ResizeObserver === "undefined") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer = new ResizeObserver(() => {
|
||||||
|
updateTruncationState();
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(el);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
observer.disconnect();
|
||||||
|
};
|
||||||
|
}, [allowWordWrap, updateTruncationState]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={panelClassName}>
|
||||||
|
<FontAwesomeStringIcon icon={meta?.icon} />
|
||||||
|
<span
|
||||||
|
ref={taskNameRef}
|
||||||
|
className="task-name-display-panel__name"
|
||||||
|
title={isNameTruncated ? taskName : undefined}
|
||||||
|
>
|
||||||
|
{taskName}
|
||||||
|
</span>
|
||||||
|
<ValidationErrorIcon
|
||||||
|
visible={showValidationErrorIcon}
|
||||||
|
reserveSpace={reserveValidationErrorIconSpace}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TaskTypeAndNameDisplayPanel;
|
||||||
Loading…
Reference in New Issue
Block a user