Skip to content

Commit

Permalink
merge: main
Browse files Browse the repository at this point in the history
  • Loading branch information
Kiryous committed Nov 18, 2024
2 parents 9cae809 + f3f38ff commit 5ff2b44
Show file tree
Hide file tree
Showing 17 changed files with 5,457 additions and 7,548 deletions.
10 changes: 7 additions & 3 deletions keep-ui/app/alerts/alert-table-headers.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// culled from https://github.com/cpvalente/ontime/blob/master/apps/client/src/features/cuesheet/cuesheet-table-elements/CuesheetHeader.tsx

import { CSSProperties, ReactNode } from "react";
import { CSSProperties, ReactNode, RefObject } from "react";
import {
closestCenter,
DndContext,
Expand All @@ -27,7 +27,6 @@ import { TableHead, TableHeaderCell, TableRow } from "@tremor/react";
import { AlertDto } from "./models";
import { useLocalStorage } from "utils/hooks/useLocalStorage";
import { getColumnsIds } from "./alert-table-utils";
import classnames from "classnames";
import { FaArrowUp, FaArrowDown, FaArrowRight } from "react-icons/fa";
import clsx from "clsx";
import { getCommonPinningStylesAndClassNames } from "@/components/ui/table/utils";
Expand Down Expand Up @@ -121,7 +120,7 @@ const DraggableHeaderCell = ({

{column.getIsPinned() === false && (
<div
className={classnames(
className={clsx(
"h-full absolute top-0 right-0 w-0.5 cursor-col-resize inline-block opacity-0 group-hover:opacity-100",
{
"hover:w-2 bg-blue-100": column.getIsResizing() === false,
Expand All @@ -138,12 +137,14 @@ interface Props {
columns: ColumnDef<AlertDto>[];
table: Table<AlertDto>;
presetName: string;
a11yContainerRef: RefObject<HTMLDivElement>;
}

export default function AlertsTableHeaders({
columns,
table,
presetName,
a11yContainerRef,
}: Props) {
const [columnOrder, setColumnOrder] = useLocalStorage<ColumnOrderState>(
`column-order-${presetName}`,
Expand Down Expand Up @@ -192,6 +193,9 @@ export default function AlertsTableHeaders({
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={onDragEnd}
accessibility={{
container: a11yContainerRef.current ?? undefined,
}}
>
<TableRow key={headerGroup.id}>
<SortableContext
Expand Down
6 changes: 5 additions & 1 deletion keep-ui/app/alerts/alert-table.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from "react";
import { useRef, useState } from "react";
import { Table, Callout, Card } from "@tremor/react";
import { AlertsTableBody } from "./alerts-table-body";
import { AlertDto } from "./models";
Expand Down Expand Up @@ -71,6 +71,8 @@ export function AlertTable({
setDismissedModalAlert,
mutateAlerts,
}: Props) {
const a11yContainerRef = useRef<HTMLDivElement>(null);

const [theme, setTheme] = useLocalStorage(
"alert-table-theme",
Object.values(severityMapping).reduce<{ [key: string]: string }>(
Expand Down Expand Up @@ -326,11 +328,13 @@ export function AlertTable({
setSelectedTab={setSelectedTab}
/>
)}
<div ref={a11yContainerRef} className="sr-only" />
<Table className="[&>table]:table-fixed [&>table]:w-full">
<AlertsTableHeaders
columns={columns}
table={table}
presetName={presetName}
a11yContainerRef={a11yContainerRef}
/>
<AlertsTableBody
table={table}
Expand Down
2 changes: 1 addition & 1 deletion keep-ui/app/config-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { createContext } from "react";
import { InternalConfig } from "types/internal-config";
import { InternalConfig } from "@/types/internal-config";

// Create the context with undefined as initial value
export const ConfigContext = createContext<InternalConfig | null>(null);
Expand Down
6 changes: 3 additions & 3 deletions keep-ui/app/incidents/[id]/incident-overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type { IncidentDto } from "@/entities/incidents/model";
import React from "react";
import { useIncident } from "@/utils/hooks/useIncidents";
import { Disclosure } from "@headlessui/react";
import classNames from "classnames";
import { IoChevronDown } from "react-icons/io5";
import remarkRehype from "remark-rehype";
import rehypeRaw from "rehype-raw";
Expand All @@ -19,6 +18,7 @@ import {
FollowingIncidents,
} from "@/features/same-incidents-in-the-past/";
import { StatusIcon } from "@/entities/incidents/ui/statuses";
import clsx from "clsx";

interface Props {
incident: IncidentDto;
Expand All @@ -43,13 +43,13 @@ function Summary({

if (collapsable) {
return (
<Disclosure as="div" className={classNames("space-y-1", className)}>
<Disclosure as="div" className={clsx("space-y-1", className)}>
<Disclosure.Button>
{({ open }) => (
<h4 className="text-gray-500 text-sm inline-flex justify-between items-center gap-1">
<span>{title}</span>
<IoChevronDown
className={classNames({ "rotate-180": open }, "text-slate-400")}
className={clsx({ "rotate-180": open }, "text-slate-400")}
/>
</h4>
)}
Expand Down
149 changes: 88 additions & 61 deletions keep-ui/app/workflows/builder/ToolBox.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useState, useEffect, useMemo } from "react";
import classNames from "classnames";
import { Disclosure } from "@headlessui/react";
import { Subtitle } from "@tremor/react";
import { IoChevronUp, IoClose } from "react-icons/io5";
Expand All @@ -8,10 +7,16 @@ import { IoIosArrowDown } from "react-icons/io";
import useStore, { V2Step } from "./builder-store";
import { FaHandPointer } from "react-icons/fa";
import { PiDiamondsFourFill } from "react-icons/pi";

const GroupedMenu = ({ name, steps, searchTerm, isDraggable = true }: {
name: string,
steps: any[],
import clsx from "clsx";

const GroupedMenu = ({
name,
steps,
searchTerm,
isDraggable = true,
}: {
name: string;
steps: any[];
searchTerm: string;
isDraggable?: boolean;
}) => {
Expand All @@ -28,8 +33,12 @@ const GroupedMenu = ({ name, steps, searchTerm, isDraggable = true }: {
if (isDraggable) {
return;
}
addNodeBetween(selectedNode || selectedEdge, step, selectedNode ? 'node' : 'edge');
}
addNodeBetween(
selectedNode || selectedEdge,
step,
selectedNode ? "node" : "edge"
);
};

function IconUrlProvider(data: any) {
const { type } = data || {};
Expand All @@ -41,18 +50,20 @@ const GroupedMenu = ({ name, steps, searchTerm, isDraggable = true }: {
?.replace("condition-", "")}-icon.png`;
}


function getTriggerIcon(step: any) {
const { type } = step;
switch (type) {
case "manual":
return <FaHandPointer size={32} />
return <FaHandPointer size={32} />;
case "interval":
return <PiDiamondsFourFill size={32} />
return <PiDiamondsFourFill size={32} />;
}
}

const handleDragStart = (event: React.DragEvent<HTMLLIElement>, step: any) => {
const handleDragStart = (
event: React.DragEvent<HTMLLIElement>,
step: any
) => {
if (!isDraggable) {
event.stopPropagation();
event.preventDefault();
Expand All @@ -70,10 +81,7 @@ const GroupedMenu = ({ name, steps, searchTerm, isDraggable = true }: {
{name}
</Subtitle>
<IoChevronUp
className={classNames(
{ "rotate-180": open },
"mr-2 text-slate-400"
)}
className={clsx({ "rotate-180": open }, "mr-2 text-slate-400")}
/>
</Disclosure.Button>
{(open || !isDraggable) && (
Expand All @@ -92,13 +100,15 @@ const GroupedMenu = ({ name, steps, searchTerm, isDraggable = true }: {
onClick={(e) => handleAddNode(e, step)}
>
{getTriggerIcon(step)}
{!!step && !['interval', 'manual'].includes(step.type) && <Image
src={IconUrlProvider(step) || "/keep.png"}
alt={step?.type}
className="object-contain aspect-auto"
width={32}
height={32}
/>}
{!!step && !["interval", "manual"].includes(step.type) && (
<Image
src={IconUrlProvider(step) || "/keep.png"}
alt={step?.type}
className="object-contain aspect-auto"
width={32}
height={32}
/>
)}
<Subtitle className="truncate">{step.name}</Subtitle>
</li>
))}
Expand All @@ -110,48 +120,57 @@ const GroupedMenu = ({ name, steps, searchTerm, isDraggable = true }: {
);
};

const DragAndDropSidebar = ({ isDraggable }: {
isDraggable?: boolean;
}) => {
const DragAndDropSidebar = ({ isDraggable }: { isDraggable?: boolean }) => {
const [searchTerm, setSearchTerm] = useState("");
const [isVisible, setIsVisible] = useState(false);
const [open, setOpen] = useState(false);
const { toolboxConfiguration, selectedNode, selectedEdge, nodes } = useStore();
const { toolboxConfiguration, selectedNode, selectedEdge, nodes } =
useStore();

useEffect(() => {

setOpen(
!!selectedNode && selectedNode.includes('empty') ||
!!selectedEdge
)
setIsVisible(!isDraggable)
(!!selectedNode && selectedNode.includes("empty")) || !!selectedEdge
);
setIsVisible(!isDraggable);
}, [selectedNode, selectedEdge, isDraggable]);

const triggerNodeMap = nodes.filter((node: any) => ['interval', 'manual', 'alert', 'incident'].includes(node?.id)).reduce((obj: any, node: any) => {
obj[node.id] = true;
return obj;
}, {} as Record<string, boolean>);

const triggerNodeMap = nodes
.filter((node: any) =>
["interval", "manual", "alert", "incident"].includes(node?.id)
)
.reduce(
(obj: any, node: any) => {
obj[node.id] = true;
return obj;
},
{} as Record<string, boolean>
);

const filteredGroups = useMemo(() => {
return toolboxConfiguration?.groups?.map((group: any) => ({
...group,
steps: group?.steps?.filter((step: any) =>
step?.name?.toLowerCase().includes(searchTerm?.toLowerCase()) && !triggerNodeMap[step?.id]
),
})) || [];
return (
toolboxConfiguration?.groups?.map((group: any) => ({
...group,
steps: group?.steps?.filter(
(step: any) =>
step?.name?.toLowerCase().includes(searchTerm?.toLowerCase()) &&
!triggerNodeMap[step?.id]
),
})) || []
);
}, [toolboxConfiguration, searchTerm, nodes?.length]);

const checkForSearchResults = searchTerm && !!filteredGroups?.find((group: any) => group?.steps?.length > 0);
const checkForSearchResults =
searchTerm &&
!!filteredGroups?.find((group: any) => group?.steps?.length > 0);

if (!open) {
return null;
}

return (
<div
className={`absolute top-50 left-2 rounded border-2 broder-gray-300 bg-white transition-transform duration-300 z-50 ${isVisible ? 'h-[88%] border-b-0' : 'shadow-lg'}`}
style={{ width: '280px' }} // Set a fixed width
className={`absolute top-50 left-2 rounded border-2 broder-gray-300 bg-white transition-transform duration-300 z-50 ${isVisible ? "h-[88%] border-b-0" : "shadow-lg"}`}
style={{ width: "280px" }} // Set a fixed width
>
<div className="relative h-full flex flex-col">
{/* Sticky header */}
Expand All @@ -167,30 +186,38 @@ const DragAndDropSidebar = ({ isDraggable }: {
/>
<button
className="p-2 text-gray-500"
onClick={() => { setIsVisible(!isVisible); setSearchTerm(''); }}
onClick={() => {
setIsVisible(!isVisible);
setSearchTerm("");
}}
>
{(isVisible || checkForSearchResults) ? <IoClose size={20} /> : <IoIosArrowDown size={20} />}
{isVisible || checkForSearchResults ? (
<IoClose size={20} />
) : (
<IoIosArrowDown size={20} />
)}
</button>
</div>
</div>

{/* Scrollable list */}
{(isVisible || checkForSearchResults) && <div className="flex-1 overflow-y-auto pt-6 space-y-4 overflow-hidden">
{filteredGroups.length > 0 &&
filteredGroups.map((group: Record<string, any>) => (
<GroupedMenu
key={group.name}
name={group.name}
steps={group.steps}
searchTerm={searchTerm}
isDraggable={isDraggable}
/>
))}
</div>}
{(isVisible || checkForSearchResults) && (
<div className="flex-1 overflow-y-auto pt-6 space-y-4 overflow-hidden">
{filteredGroups.length > 0 &&
filteredGroups.map((group: Record<string, any>) => (
<GroupedMenu
key={group.name}
name={group.name}
steps={group.steps}
searchTerm={searchTerm}
isDraggable={isDraggable}
/>
))}
</div>
)}
</div>
</div>

)
);
};

export default DragAndDropSidebar;
10 changes: 5 additions & 5 deletions keep-ui/components/LinkWithIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import Link, { LinkProps } from "next/link";
import { IconType } from "react-icons/lib";
import { Badge, Icon } from "@tremor/react";
import { usePathname } from "next/navigation";
import classNames from "classnames";
import { Trashcan } from "components/icons";
import { Trashcan } from "@/components/icons";
import clsx from "clsx";

type LinkWithIconProps = {
children: ReactNode;
Expand Down Expand Up @@ -40,12 +40,12 @@ export const LinkWithIcon = ({
restOfLinkProps.href?.toString() || ""
);

const iconClasses = classNames("group-hover:text-orange-400", {
const iconClasses = clsx("group-hover:text-orange-400", {
"text-orange-400": isActive,
"text-black": !isActive,
});

const textClasses = classNames("truncate", {
const textClasses = clsx("truncate", {
"text-orange-400": isActive,
"text-black": !isActive,
});
Expand All @@ -61,7 +61,7 @@ export const LinkWithIcon = ({

return (
<div
className={classNames(
className={clsx(
"flex items-center justify-between text-sm p-1 font-medium rounded-lg focus:ring focus:ring-orange-300 group w-full",
{
"bg-stone-200/50": isActive,
Expand Down
Loading

0 comments on commit 5ff2b44

Please sign in to comment.