Skip to content

Commit

Permalink
Merge pull request #221 from melfore/219-feature-task-color
Browse files Browse the repository at this point in the history
[Task] Added custom color for single task
  • Loading branch information
CrisGrud authored Aug 27, 2024
2 parents 1e7b560 + 0e63ab2 commit cea953f
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 13 deletions.
76 changes: 76 additions & 0 deletions src/KonvaTimeline/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -274,3 +274,79 @@ export const CustomTooltip: Story = {
customToolTip: customToolTip,
},
};

export const CustomColor: Story = {
args: {
...Primary.args,
resources,
resolution: "2weeks",
range: {
start: 1698357600000,
end: 1702095200000,
},
tasks: [
{
id: "4",
label: "Task4",
resourceId: "2",
time: {
start: 1698357600000,
end: 1698557900000,
},
},
{
id: "6",
label: "Task6",
resourceId: "2",
time: {
start: 1698599900000,
end: 1698793200000,
},
taskColor: "#fc0303",
},
{
id: "1",
label: "Task1",
resourceId: "1",
time: {
start: 1698793200000,
end: 1699434800000,
},
},
{
id: "3",
label: "Task3",
resourceId: "3",
time: {
start: 1699734800000,
end: 1700234800000,
},
},
{
id: "2",
label: "Task2",
resourceId: "2",
time: {
start: 1700434800000,
end: 1700934800000,
},
},
{
id: "5",
label: "Task5",
resourceId: "1",
time: {
start: 1701505200000,
end: 1702105200000,
},
},
],
},
};

export const ResourceClickable: Story = {
args: {
...Primary.args,
onResourceClick: (resource) => alert(`OnResourceClick handler, ResourceLabel: ${resource.label}`),
},
};
31 changes: 24 additions & 7 deletions src/resources/components/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { memo, useMemo } from "react";
import React, { memo, useCallback, useMemo } from "react";
import { Group, Rect } from "react-konva";

import { KonvaGroup, KonvaLine, KonvaRect, KonvaText } from "../../../@konva";
import { KonvaLine, KonvaRect, KonvaText } from "../../../@konva";
import { useTimelineContext } from "../../../timeline/TimelineContext";
import { DEFAULT_TEXT_SIZE } from "../../../utils/dimensions";
import {
Expand All @@ -25,15 +26,24 @@ interface ResourceHeaderProps {
* The resource object to handle
*/
resource: Resource;
/**
* On click event
*/
onClick?: () => void;
/**
* Prop that idicate if resource is header
*/
header?: boolean;
}

/**
* This component renders a resource header. It displays a text (`resource.label`) and a delimiter line.
*/
const ResourceHeader = ({ index, isLast = false, resource }: ResourceHeaderProps) => {
const ResourceHeader = ({ index, isLast = false, resource, header }: ResourceHeaderProps) => {
const {
rowHeight,
theme: { color: themeColor },
onResourceClick,
} = useTimelineContext();

const rowPoints = useMemo(() => [0, rowHeight, RESOURCE_HEADER_WIDTH, rowHeight], [rowHeight]);
Expand All @@ -53,8 +63,15 @@ const ResourceHeader = ({ index, isLast = false, resource }: ResourceHeaderProps
}
return DEFAULT_STROKE_DARK_MODE;
}, [themeColor]);

const onClick = useCallback(
() => onResourceClick && !header && onResourceClick(resource),
[resource, header, onResourceClick]
);

return (
<KonvaGroup y={yCoordinate}>
<Group y={yCoordinate}>
<Rect onClick={onClick} width={RESOURCE_HEADER_WIDTH} height={rowHeight} />
<KonvaText
fill={themeColor}
fontSize={DEFAULT_TEXT_SIZE}
Expand All @@ -64,12 +81,12 @@ const ResourceHeader = ({ index, isLast = false, resource }: ResourceHeaderProps
x={RESOURCE_TEXT_OFFSET}
/>
{!isLast && (
<KonvaGroup>
<Group>
<KonvaLine points={rowPoints} stroke={stroke} />
<KonvaRect x={0} y={rowHeight} width={RESOURCE_HEADER_WIDTH} height={rowHeight} fill={fill} />
</KonvaGroup>
</Group>
)}
</KonvaGroup>
</Group>
);
};

Expand Down
17 changes: 13 additions & 4 deletions src/resources/components/Layer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { FC } from "react";
import { Layer } from "react-konva";

import { KonvaLayer } from "../../../@konva";
import { useTimelineContext } from "../../../timeline/TimelineContext";
import ResourceHeader from "../Header";

Expand All @@ -13,13 +13,22 @@ const ResourcesLayer: FC<ResourcesLayerProps> = () => {
const { resources } = useTimelineContext();

return (
<KonvaLayer>
<Layer>
{resources.map((resource, index) => {
const isLast = index === resources.length - 1;
const header = index === 0 ? true : false;

return <ResourceHeader key={`resource-${resource.id}`} index={index} isLast={isLast} resource={resource} />;
return (
<ResourceHeader
key={`resource-${resource.id}`}
index={index}
isLast={isLast}
resource={resource}
header={header}
/>
);
})}
</KonvaLayer>
</Layer>
);
};

Expand Down
6 changes: 5 additions & 1 deletion src/tasks/components/Task/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,16 @@ const Task = ({
return DISABLED_TASK_DEFAULT_FILL;
}
try {
if (data.taskColor) {
const rgb = getRGB(data.taskColor);
return ` rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
}
const rgb = getRGB(fill);
return ` rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`;
} catch (error) {
return INVALIDFILL_TASK_DEFAULT_FILL;
}
}, [fill, disabled]);
}, [fill, disabled, data]);

const mainStroke = useMemo(() => {
if (disabled) {
Expand Down
4 changes: 4 additions & 0 deletions src/tasks/utils/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ export interface TaskData<T extends TimeRange = TimeRange> {
* Id of connected Tasks
*/
relatedTasks?: string[];
/**
* Color of the single task
*/
taskColor?: string;
}

type FilteredTasks = Operation<TaskData<InternalTimeRange>>;
Expand Down
9 changes: 8 additions & 1 deletion src/timeline/TimelineContext.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { createContext, PropsWithChildren, useContext, useEffect, useMemo, useState } from "react";
import { DateTime, Interval } from "luxon";

import { addHeaderResource } from "../resources/utils/resources";
import { addHeaderResource, Resource } from "../resources/utils/resources";
import { AreaSelect, filterTasks, TaskData, validateTasks } from "../tasks/utils/tasks";
import { DEFAULT_GRID_COLUMN_WIDTH, DEFAULT_GRID_ROW_HEIGHT, MINIMUM_GRID_ROW_HEIGHT } from "../utils/dimensions";
import { logDebug, logWarn } from "../utils/logger";
Expand Down Expand Up @@ -117,6 +117,10 @@ export type TimelineProviderProps = PropsWithChildren<TimelineInput> & {
* Enables connection between tasks (if kLine is set in taskData)
*/
enableLines?: boolean;
/**
* Event handler for resource click
*/
onResourceClick?: (task: Resource) => void;
};

type TimelineTheme = {
Expand Down Expand Up @@ -157,6 +161,7 @@ type TimelineContextType = Required<
validLine?: LineData[];
allValidTasks: TaskData<InternalTimeRange>[];
externalRangeInMillis: InternalTimeRange;
onResourceClick?: (resource: Resource) => void;
};

const TimelineContext = createContext<TimelineContextType | undefined>(undefined);
Expand Down Expand Up @@ -197,6 +202,7 @@ export const TimelineProvider = ({
customToolTip,
enableTaskPattern = true,
enableLines,
onResourceClick,
}: TimelineProviderProps) => {
const timezone = useMemo(() => {
if (!externalTimezone) {
Expand Down Expand Up @@ -484,6 +490,7 @@ export const TimelineProvider = ({
validLine,
allValidTasks,
externalRangeInMillis: range,
onResourceClick,
}}
>
{children}
Expand Down

0 comments on commit cea953f

Please sign in to comment.