hide related feature
This commit is contained in:
1 parent
3343a10c32
commit
49c013f3d7
12 files changed
+156
-69
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import React, { useState, SyntheticEvent, useRef, useEffect } from "react";
|
||||
import { ViewMode, GanttProps } from "../../types/public-types";
|
||||
import { ViewMode, GanttProps, Task } from "../../types/public-types";
|
||||
import { GridProps } from "../grid/grid";
|
||||
import { ganttDateRange, seedDates } from "../../helpers/date-helper";
|
||||
import { CalendarProps } from "../calendar/calendar";
|
||||
@@ -16,6 +16,7 @@ import { GanttEvent } from "../../types/gantt-task-actions";
|
||||
import { DateSetup } from "../../types/date-setup";
|
||||
import styles from "./gantt.module.css";
|
||||
import { HorizontalScroll } from "../other/horizontal-scroll";
|
||||
import { removeHiddenTasks } from "../../helpers/other-helper";
|
||||
|
||||
export const Gantt: React.FunctionComponent<GanttProps> = ({
|
||||
tasks,
|
||||
@@ -54,6 +55,7 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
|
||||
onDoubleClick,
|
||||
onDelete,
|
||||
onSelect,
|
||||
onExpanderClick,
|
||||
}) => {
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
const taskListRef = useRef<HTMLDivElement>(null);
|
||||
@@ -83,7 +85,8 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
|
||||
|
||||
// task change events
|
||||
useEffect(() => {
|
||||
const [startDate, endDate] = ganttDateRange(tasks, viewMode);
|
||||
const filteredTasks = removeHiddenTasks(tasks);
|
||||
const [startDate, endDate] = ganttDateRange(filteredTasks, viewMode);
|
||||
let newDates = seedDates(startDate, endDate, viewMode);
|
||||
if (rtl) {
|
||||
newDates = newDates.reverse();
|
||||
@@ -94,7 +97,7 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
|
||||
setDateSetup({ dates: newDates, viewMode });
|
||||
setBarTasks(
|
||||
convertToBarTasks(
|
||||
tasks,
|
||||
filteredTasks,
|
||||
newDates,
|
||||
columnWidth,
|
||||
rowHeight,
|
||||
@@ -322,7 +325,11 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
|
||||
}
|
||||
setSelectedTask(newSelectedTask);
|
||||
};
|
||||
|
||||
const handleExpanderClick = (task: Task) => {
|
||||
if (onExpanderClick && task.hideChildren !== undefined) {
|
||||
onExpanderClick({ ...task, hideChildren: !task.hideChildren });
|
||||
}
|
||||
};
|
||||
const gridProps: GridProps = {
|
||||
columnWidth,
|
||||
svgWidth,
|
||||
@@ -380,6 +387,7 @@ export const Gantt: React.FunctionComponent<GanttProps> = ({
|
||||
selectedTask,
|
||||
taskListRef,
|
||||
setSelectedTask: handleSelectedTask,
|
||||
onExpanderClick: handleExpanderClick,
|
||||
TaskListHeader,
|
||||
TaskListTable,
|
||||
};
|
||||
|
||||
@@ -20,3 +20,19 @@
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.taskListNameWrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.taskListExpander {
|
||||
color: rgb(86 86 86);
|
||||
font-size: 0.6rem;
|
||||
padding: 0.15rem 0.2rem 0rem 0.2rem;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.taskListEmptyExpander {
|
||||
font-size: 0.6rem;
|
||||
padding-left: 1rem;
|
||||
user-select: none;
|
||||
}
|
||||
@@ -11,7 +11,16 @@ export const TaskListTableDefault: React.FC<{
|
||||
tasks: Task[];
|
||||
selectedTaskId: string;
|
||||
setSelectedTask: (taskId: string) => void;
|
||||
}> = ({ rowHeight, rowWidth, tasks, fontFamily, fontSize, locale }) => {
|
||||
onExpanderClick: (task: Task) => void;
|
||||
}> = ({
|
||||
rowHeight,
|
||||
rowWidth,
|
||||
tasks,
|
||||
fontFamily,
|
||||
fontSize,
|
||||
locale,
|
||||
onExpanderClick,
|
||||
}) => {
|
||||
const dateTimeOptions: Intl.DateTimeFormatOptions = {
|
||||
weekday: "short",
|
||||
year: "numeric",
|
||||
@@ -27,6 +36,13 @@ export const TaskListTableDefault: React.FC<{
|
||||
}}
|
||||
>
|
||||
{tasks.map(t => {
|
||||
let expanderSymbol = "";
|
||||
if (t.hideChildren === false) {
|
||||
expanderSymbol = "▼";
|
||||
} else if (t.hideChildren === true) {
|
||||
expanderSymbol = "▶";
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.taskListTableRow}
|
||||
@@ -41,7 +57,19 @@ export const TaskListTableDefault: React.FC<{
|
||||
}}
|
||||
title={t.name}
|
||||
>
|
||||
{t.name}
|
||||
<div className={styles.taskListNameWrapper}>
|
||||
<div
|
||||
className={
|
||||
expanderSymbol
|
||||
? styles.taskListExpander
|
||||
: styles.taskListEmptyExpander
|
||||
}
|
||||
onClick={() => onExpanderClick(t)}
|
||||
>
|
||||
{expanderSymbol}
|
||||
</div>
|
||||
<div>{t.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={styles.taskListCell}
|
||||
|
||||
@@ -16,6 +16,7 @@ export type TaskListProps = {
|
||||
horizontalContainerClass?: string;
|
||||
selectedTask: BarTask | undefined;
|
||||
setSelectedTask: (task: string) => void;
|
||||
onExpanderClick: (task: Task) => void;
|
||||
TaskListHeader: React.FC<{
|
||||
headerHeight: number;
|
||||
rowWidth: string;
|
||||
@@ -31,6 +32,7 @@ export type TaskListProps = {
|
||||
tasks: Task[];
|
||||
selectedTaskId: string;
|
||||
setSelectedTask: (taskId: string) => void;
|
||||
onExpanderClick: (task: Task) => void;
|
||||
}>;
|
||||
};
|
||||
|
||||
@@ -44,6 +46,7 @@ export const TaskList: React.FC<TaskListProps> = ({
|
||||
tasks,
|
||||
selectedTask,
|
||||
setSelectedTask,
|
||||
onExpanderClick,
|
||||
locale,
|
||||
ganttHeight,
|
||||
taskListRef,
|
||||
@@ -74,6 +77,7 @@ export const TaskList: React.FC<TaskListProps> = ({
|
||||
locale,
|
||||
selectedTaskId: selectedTaskId,
|
||||
setSelectedTask,
|
||||
onExpanderClick,
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -63,6 +63,19 @@ export const convertToBarTasks = (
|
||||
}
|
||||
return task;
|
||||
});
|
||||
// normalize flags for hideChildren
|
||||
barTasks = barTasks.map(task => {
|
||||
if (task.barChildren.length > 0) {
|
||||
if (!task.hideChildren) {
|
||||
task.hideChildren = false;
|
||||
}
|
||||
} else if (!task.hideChildren && task.type === "project") {
|
||||
task.hideChildren = false;
|
||||
} else if (!task.hideChildren) {
|
||||
task.hideChildren = undefined;
|
||||
}
|
||||
return task;
|
||||
});
|
||||
|
||||
return barTasks;
|
||||
};
|
||||
|
||||
@@ -16,3 +16,33 @@ export function isMouseEvent(
|
||||
export function isBarTask(task: Task | BarTask): task is BarTask {
|
||||
return (task as BarTask).x1 !== undefined;
|
||||
}
|
||||
|
||||
export function removeHiddenTasks(tasks: Task[]) {
|
||||
const groupedTasks = tasks.filter(t => t.hideChildren);
|
||||
if (groupedTasks.length > 0) {
|
||||
for (let i = 0; groupedTasks.length > i; i++) {
|
||||
const groupedTask = groupedTasks[i];
|
||||
const children = getChildren(tasks, groupedTask);
|
||||
tasks = tasks.filter(t => children.indexOf(t) === -1);
|
||||
}
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
|
||||
function getChildren(taskList: Task[], task: Task) {
|
||||
let tasks: Task[] = [];
|
||||
if (task.type !== "project") {
|
||||
tasks = taskList.filter(
|
||||
t => t.dependencies && t.dependencies.indexOf(task.id) !== -1
|
||||
);
|
||||
} else {
|
||||
tasks = taskList.filter(t => t.project && t.project === task.id);
|
||||
}
|
||||
const taskChildren = tasks.reduce(
|
||||
(children: Task[], t) =>
|
||||
children.concat(children, getChildren(taskList, t)),
|
||||
[]
|
||||
);
|
||||
tasks = tasks.concat(tasks, taskChildren);
|
||||
return tasks;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
export function foo() {
|
||||
return 1;
|
||||
}
|
||||
// import { BarTask } from "../types/bar-task";
|
||||
// export type TaskListAction =
|
||||
// | { type: GanttContentMoveAction; task: BarTask }
|
||||
// | { type: "update"; tasks: BarTask[] };
|
||||
|
||||
// export type TaskListState = {
|
||||
// tasks: BarTask[];
|
||||
// changedTask?: BarTask;
|
||||
// originalTask?: BarTask;
|
||||
// selectedTask?: BarTask;
|
||||
// activeAction: GanttContentMoveAction;
|
||||
// };
|
||||
|
||||
// export function taskListReducer(state: TaskListState, action: TaskListAction) {
|
||||
// switch (action.type) {
|
||||
// case "update":
|
||||
// return { ...state, tasks: action.tasks };
|
||||
// case "select":
|
||||
// return { ...state, selectedTask: action.task };
|
||||
// default:
|
||||
// return state;
|
||||
// }
|
||||
// }
|
||||
@@ -26,6 +26,7 @@ export interface Task {
|
||||
isDisabled?: boolean;
|
||||
project?: string;
|
||||
dependencies?: string[];
|
||||
hideChildren?: boolean;
|
||||
}
|
||||
|
||||
export interface EventOption {
|
||||
@@ -57,6 +58,10 @@ export interface EventOption {
|
||||
* Invokes on delete selected task. Chart undoes operation if method return false or error.
|
||||
*/
|
||||
onDelete?: (task: Task) => void | boolean | Promise<void> | Promise<boolean>;
|
||||
/**
|
||||
* Invokes on expander on task list
|
||||
*/
|
||||
onExpanderClick?: (task: Task) => void;
|
||||
}
|
||||
|
||||
export interface DisplayOption {
|
||||
@@ -119,6 +124,7 @@ export interface StylingOption {
|
||||
* Sets selected task by id
|
||||
*/
|
||||
setSelectedTask: (taskId: string) => void;
|
||||
onExpanderClick: (task: Task) => void;
|
||||
}>;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user