Skip to content

Commit bba5cd1

Browse files
authored
Set current branch in activities filter and update event type filter options (#5862)
* set current branch in filter * set current branch in filter + update event type filter * add event type * fix param
1 parent 639c432 commit bba5cd1

File tree

5 files changed

+257
-103
lines changed

5 files changed

+257
-103
lines changed
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { QSP } from "@/config/qsp";
2+
import { AttributeSchema, RelationshipSchema } from "@/entities/schema/types";
3+
import { Popover, PopoverContent, PopoverTrigger } from "@/shared/components/ui/popover";
4+
import useFilters from "@/shared/hooks/useFilters";
5+
import { Icon } from "@iconify-icon/react";
6+
import React, { useEffect, useState } from "react";
7+
import { TagProps } from "react-aria-components";
8+
import { useQueryParam } from "use-query-params";
9+
import { GlobalFilterForm } from "./global-filter-form";
10+
import { FilterTag } from "./global-filter-tag";
11+
12+
interface FilterTagProps extends TagProps {
13+
label: React.ReactNode;
14+
name: string;
15+
fieldSchema: AttributeSchema | RelationshipSchema;
16+
}
17+
18+
export function GlobalBranchFilter({ label, name, fieldSchema, ...props }: FilterTagProps) {
19+
const [filters, setFilters] = useFilters();
20+
const [branch] = useQueryParam(QSP.BRANCH);
21+
const [showFilters, setShowFilters] = useState(false);
22+
23+
const currentFilter = filters.find((filter) => filter.name.startsWith(name));
24+
25+
const handleRemoveFilter = () => {
26+
setFilters([...filters, { name: "branches__value", value: null }]);
27+
};
28+
29+
const getFilterDisplayValue = () => {
30+
if (typeof currentFilter?.value === "boolean") {
31+
return JSON.stringify(currentFilter?.value);
32+
}
33+
34+
if (fieldSchema.kind === "Dropdown") {
35+
return fieldSchema.choices?.find((choice) => {
36+
return choice.name === currentFilter?.value;
37+
})?.label;
38+
}
39+
40+
if (Array.isArray(currentFilter?.value)) {
41+
return currentFilter?.value
42+
.map((value) => {
43+
return value.display_label;
44+
})
45+
.join(", ");
46+
}
47+
48+
return currentFilter?.value;
49+
};
50+
51+
useEffect(() => {
52+
if (!branch || branch === "main") return;
53+
54+
if (currentFilter?.value === null) return;
55+
56+
// Set the current branch if it's not main and if it has not been removed from the filters
57+
setFilters([...filters, { name: "branches__value", value: branch }]);
58+
}, []);
59+
60+
return (
61+
<FilterTag label="branches" currentFilter={currentFilter} {...props}>
62+
<Popover open={showFilters} onOpenChange={setShowFilters}>
63+
<PopoverTrigger className="flex items-center h-6 pl-1">
64+
<span>{label}</span>
65+
66+
<div className="w-px bg-gray-300 self-stretch ml-1" />
67+
68+
{(currentFilter?.value === undefined || currentFilter?.value === null) && (
69+
<Icon
70+
icon="mdi:plus-circle-outline"
71+
className="text-base text-gray-400 group-hover:text-custom-blue-700 transition-all mx-1"
72+
/>
73+
)}
74+
75+
{currentFilter?.value !== undefined && currentFilter?.value !== null && (
76+
<div
77+
className="flex items-center gap-1 h-6 rounded-r-full px-1 hover:bg-gray-300 transition-all"
78+
onClick={(event) => {
79+
event.stopPropagation();
80+
handleRemoveFilter();
81+
}}
82+
>
83+
<div className="text-custom-blue-700 font-medium inline-flex items-center">
84+
{getFilterDisplayValue()}
85+
</div>
86+
87+
<Icon
88+
icon="mdi:close-circle-outline"
89+
className="text-base text-gray-400 group-hover:text-custom-blue-700 transition-all"
90+
/>
91+
</div>
92+
)}
93+
</PopoverTrigger>
94+
<PopoverContent className="relative rounded-tl-none" align="start">
95+
<div className="absolute -top-[1.8rem] bg-white border px-2 py-1 rounded-t-md border-b-0 -left-px">
96+
Filter by
97+
<span className="ml-1 font-semibold">{label}</span>
98+
</div>
99+
100+
<GlobalFilterForm
101+
name={name}
102+
fieldSchema={fieldSchema}
103+
onSuccess={() => {
104+
setShowFilters(false);
105+
}}
106+
/>
107+
</PopoverContent>
108+
</Popover>
109+
</FilterTag>
110+
);
111+
}

frontend/app/src/entities/events/ui/global-events-filters.tsx

Lines changed: 16 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -2,102 +2,31 @@ import { branchesState } from "@/entities/branches/stores";
22
import { ScrollArea } from "@/shared/components/ui/scroll-area";
33
import { useAtomValue } from "jotai";
44
import { TagGroup, TagList } from "react-aria-components";
5+
import { FILTERS } from "../utils/constants";
6+
import { GlobalBranchFilter } from "./global-branch-filter";
57
import { GlobalFilter } from "./global-filter";
68

79
export const GlobalEventsFilters = () => {
810
const branches = useAtomValue(branchesState);
911

10-
const FILTERS = [
11-
{
12-
name: "hasChildren",
13-
label: "Has Children",
14-
fieldSchema: {
15-
kind: "Boolean",
16-
},
17-
},
18-
{
19-
name: "branches",
20-
label: "Branch",
21-
fieldSchema: {
22-
kind: "Dropdown",
23-
choices: branches.map((branch) => {
24-
return {
25-
label: branch.name,
26-
name: branch.name,
27-
};
28-
}),
29-
},
30-
},
31-
{
32-
name: "eventType",
33-
label: "Event Type",
34-
fieldSchema: {
35-
kind: "Dropdown",
36-
choices: [
37-
{
38-
label: "Node updated",
39-
name: "NodeMutatedEvent",
40-
},
41-
{
42-
label: "Branch created",
43-
name: "BranchCreatedEvent",
44-
},
45-
{
46-
label: "Branch updated",
47-
name: "BranchUpdatedEvent",
48-
},
49-
{
50-
label: "Branch rebased",
51-
name: "BranchRebasedEvent",
52-
},
53-
{
54-
label: "Standard event",
55-
name: "StandardEvent",
56-
},
57-
],
58-
},
59-
},
60-
{
61-
name: "primaryNodeIds",
62-
label: "Primary Node",
63-
fieldSchema: {
64-
peer: "CoreNode",
65-
},
66-
},
67-
{
68-
name: "relatedNodeIds",
69-
label: "Related Node",
70-
fieldSchema: {
71-
peer: "CoreNode",
72-
},
73-
},
74-
{
75-
name: "accountIds",
76-
label: "Account",
77-
fieldSchema: {
78-
peer: "CoreAccount",
79-
},
80-
},
81-
{
82-
name: "since",
83-
label: "Start Date",
84-
fieldSchema: {
85-
kind: "DateTime",
86-
},
87-
},
88-
{
89-
name: "until",
90-
label: "End Date",
91-
fieldSchema: {
92-
kind: "DateTime",
93-
},
94-
},
95-
];
96-
9712
return (
9813
<ScrollArea scrollX>
9914
<TagGroup className="flex" selectionMode="single" aria-label="Filter group">
10015
<TagList className="flex items-center gap-2 py-3">
16+
<GlobalBranchFilter
17+
name="branches"
18+
label="Branch"
19+
fieldSchema={{
20+
kind: "Dropdown",
21+
choices: branches.map((branch) => {
22+
return {
23+
label: branch.name,
24+
name: branch.name,
25+
};
26+
}),
27+
}}
28+
/>
29+
10130
{FILTERS.map((filter) => {
10231
return <GlobalFilter key={filter.name} {...filter} />;
10332
})}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { focusVisibleStyle } from "@/shared/components/style-rac";
2+
import { Filter } from "@/shared/hooks/useFilters";
3+
import { classNames } from "@/shared/utils/common";
4+
import { Tag, TagProps } from "react-aria-components";
5+
6+
type FilterTagProps = {
7+
label: string;
8+
currentFilter?: Filter;
9+
} & TagProps;
10+
11+
export const FilterTag = ({ children, label, currentFilter, ...props }: FilterTagProps) => {
12+
return (
13+
<Tag
14+
className={classNames(
15+
focusVisibleStyle,
16+
"group text-sm whitespace-nowrap rounded-full inline-flex items-center gap-1.5 border border-gray-300",
17+
currentFilter?.value && "text-gray-600 bg-neutral-100 pl-1 cursor-pointer",
18+
!currentFilter?.value && "text-gray-400 px-1 cursor-pointer border-dashed",
19+
"data-[hovered]:bg-gray-100 data-[hovered]:text-gray-600 data-[hovered]:border-gray-600"
20+
)}
21+
aria-label={`${label} contains ${currentFilter?.value}`}
22+
textValue={`${label} contains ${currentFilter?.value}`}
23+
{...props}
24+
>
25+
{children}
26+
</Tag>
27+
);
28+
};

frontend/app/src/entities/events/ui/global-filter.tsx

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import { AttributeSchema, RelationshipSchema } from "@/entities/schema/types";
2-
import { focusVisibleStyle } from "@/shared/components/style-rac";
32
import { Popover, PopoverContent, PopoverTrigger } from "@/shared/components/ui/popover";
43
import useFilters from "@/shared/hooks/useFilters";
5-
import { classNames } from "@/shared/utils/common";
64
import { Icon } from "@iconify-icon/react";
75
import React, { useState } from "react";
8-
import { Tag, TagProps } from "react-aria-components";
6+
import { TagProps } from "react-aria-components";
97
import { GlobalFilterForm } from "./global-filter-form";
8+
import { FilterTag } from "./global-filter-tag";
109

1110
interface FilterTagProps extends TagProps {
1211
label: React.ReactNode;
@@ -47,18 +46,7 @@ export function GlobalFilter({ label, name, fieldSchema, ...props }: FilterTagPr
4746
};
4847

4948
return (
50-
<Tag
51-
className={classNames(
52-
focusVisibleStyle,
53-
"group text-sm whitespace-nowrap rounded-full inline-flex items-center gap-1.5 border border-gray-300",
54-
currentFilter?.value && "text-gray-600 bg-neutral-100 pl-1 cursor-pointer",
55-
!currentFilter?.value && "text-gray-400 px-1 cursor-pointer border-dashed",
56-
"data-[hovered]:bg-gray-100 data-[hovered]:text-gray-600 data-[hovered]:border-gray-600"
57-
)}
58-
aria-label={`${label} contains ${currentFilter?.value}`}
59-
textValue={`${label} contains ${currentFilter?.value}`}
60-
{...props}
61-
>
49+
<FilterTag currentFilter={currentFilter} label={label} {...props}>
6250
<Popover open={showFilters} onOpenChange={setShowFilters}>
6351
<PopoverTrigger className="flex items-center h-6 pl-1">
6452
<span>{label}</span>
@@ -106,6 +94,6 @@ export function GlobalFilter({ label, name, fieldSchema, ...props }: FilterTagPr
10694
/>
10795
</PopoverContent>
10896
</Popover>
109-
</Tag>
97+
</FilterTag>
11098
);
11199
}

0 commit comments

Comments
 (0)