Skip to content
This repository was archived by the owner on Jun 13, 2024. It is now read-only.

Commit ac99cde

Browse files
authored
feat: added branch filter preview (#240)
* feat: added branch filter preview * chore: removed stale log and effects
1 parent e62a3c4 commit ac99cde

4 files changed

Lines changed: 147 additions & 62 deletions

File tree

src/components/atoms/form/AdjacentStepListItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const AdjacentStepListItem = ({
1616

1717
return (
1818
<button
19-
className="flex-1 cursor-pointer text-left rounded-sm text-circle-black leading-6"
19+
className="flex-1 cursor-pointer text-left rounded text-circle-black leading-6"
2020
type="button"
2121
onClick={() => {
2222
navigateTo({

src/components/atoms/form/ListProperty.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ const ListItem = ({
6363
<Draggable key={index} draggableId={`${index}`} index={index}>
6464
{(provided, _) => (
6565
<div
66-
className="w-full mb-4 p-1 px-3 text-sm
67-
bg-white border border-circle-gray-300 hover:border-circle-black rounded-md2 flex flex-row"
66+
className="w-full mb-2 p-1 px-3
67+
bg-white border border-circle-gray-300 hover:border-circle-black rounded flex flex-row"
6868
ref={provided.innerRef}
6969
{...provided.draggableProps}
7070
>
@@ -102,6 +102,7 @@ const ListProperty = (props: ListPropertyProps) => {
102102
<FieldArray
103103
{...field}
104104
name={props.name}
105+
105106
render={(arrayHelper) => (
106107
<FieldlessListProperty
107108
{...props}
@@ -131,6 +132,7 @@ export const FieldlessListProperty = ({
131132
}) => {
132133
const [input, , helper] = field;
133134
const ListChild = listItem;
135+
134136
return (
135137
<CollapsibleList
136138
title={
@@ -212,9 +214,9 @@ export const FieldlessListProperty = ({
212214
</DragDropContext>
213215
) : (
214216
<>
215-
<p className="ml-2 font-medium text-sm text-circle-gray-500">
217+
<div className="ml-2 font-medium text-sm text-circle-gray-500">
216218
{emptyText}
217-
</p>
219+
</div>
218220
{children}
219221
</>
220222
)}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { types } from '@circleci/circleci-config-sdk';
2+
import { WorkflowJob } from '@circleci/circleci-config-sdk/dist/src/lib/Components/Workflow';
3+
import BranchIcon from '../../icons/ui/BranchIcon';
4+
import EditIcon from '../../icons/ui/EditIcon';
5+
import TagIcon from '../../icons/ui/TagIcon';
6+
import { useStoreActions } from '../../state/Hooks';
7+
import StagedFilterMenuNav from '../menus/stage/StagedFilterMenu';
8+
import CollapsibleList from './CollapsibleList';
9+
10+
const combineFilters = (filters: any, condition: 'ignore' | 'only') => {
11+
const branches = filters?.branches;
12+
const tags = filters?.tags;
13+
const branchesCon =
14+
branches && condition in branches ? branches[condition] : [];
15+
const tagsCon = tags && condition in tags ? tags[condition] : [];
16+
17+
return { branches: branchesCon, tags: tagsCon };
18+
};
19+
20+
export const FilterTargetList = ({
21+
values,
22+
target,
23+
}: {
24+
values: string[];
25+
target: 'branches' | 'tags';
26+
}) => {
27+
const Icon = target === 'branches' ? BranchIcon : TagIcon;
28+
29+
return (
30+
<>
31+
{values.map((value) => (
32+
<div
33+
className="w-full mt-2 p-2 px-3
34+
bg-white border border-circle-gray-300 hover:border-circle-black rounded flex flex-row"
35+
>
36+
<Icon className="w-3 ml-1 mr-2 my-auto" />
37+
{value}
38+
</div>
39+
))}
40+
</>
41+
);
42+
};
43+
44+
export const FilterConditionList = (props: {
45+
filters: any;
46+
condition: 'Ignore' | 'Only';
47+
}) => {
48+
const type = props.condition.toLowerCase() as 'ignore' | 'only';
49+
const values = combineFilters(props.filters, type);
50+
51+
return (
52+
<>
53+
{values.branches?.length > 0 && values.branches?.length > 0 && (
54+
<div className="pl-4 pt-1">
55+
<h3 className="text-sm font-medium">{props.condition}</h3>
56+
<FilterTargetList values={values.branches} target="branches" />
57+
<FilterTargetList values={values.tags} target="tags" />
58+
</div>
59+
)}
60+
</>
61+
);
62+
};
63+
64+
export const FilterPreviewContainer = ({
65+
values,
66+
source,
67+
}: {
68+
values: any;
69+
source: WorkflowJob;
70+
}) => {
71+
const navigateTo = useStoreActions((actions) => actions.navigateTo);
72+
const filters = values.parameters?.filters;
73+
74+
return (
75+
<CollapsibleList
76+
title={'Filters'}
77+
expanded
78+
titleFont='font-medium text-sm'
79+
className='mb-4'
80+
pinned={
81+
<button
82+
type="button"
83+
className={`bg-circle-gray-300 transition-colors h-8 w-8 rounded hover:bg-circle-gray-400 ml-auto`}
84+
onClick={() => {
85+
navigateTo({
86+
component: StagedFilterMenuNav,
87+
props: { source, values },
88+
values,
89+
});
90+
}}
91+
>
92+
<EditIcon className="m-auto w-4"></EditIcon>
93+
</button>
94+
}
95+
>
96+
<>
97+
<FilterConditionList filters={filters} condition="Only" />
98+
<FilterConditionList filters={filters} condition="Ignore" />
99+
</>
100+
</CollapsibleList>
101+
);
102+
};

src/components/menus/stage/StagedFilterMenu.tsx

Lines changed: 38 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { FilterParameter } from '@circleci/circleci-config-sdk/dist/src/lib/Components/Parameters/types';
22
import { WorkflowJob } from '@circleci/circleci-config-sdk/dist/src/lib/Components/Workflow';
33
import { Form, Formik, FormikValues } from 'formik';
4-
import React, { useState } from 'react';
4+
import React, { useEffect, useState } from 'react';
55
import { useStoreActions } from '../../../state/Hooks';
66
import { NavigationComponent } from '../../../state/Store';
77
import { Button } from '../../atoms/Button';
@@ -65,7 +65,6 @@ const FilterList = ({ type, values, target }: FilterListProps) => {
6565
expanded
6666
required
6767
listItem={FilterItem}
68-
empty="filter "
6968
addButton
7069
/>
7170
);
@@ -74,9 +73,6 @@ const FilterList = ({ type, values, target }: FilterListProps) => {
7473
const StagedFilterMenu = ({ job, values }: WorkflowJobMenuProps) => {
7574
const navigateBack = useStoreActions((actions) => actions.navigateBack);
7675
const tabs = ['BRANCHES', 'TAGS'];
77-
const [target, setTarget] = useState(tabs[0].toLowerCase());
78-
79-
console.log(values);
8076

8177
return (
8278
<div className="h-full bg-white flex flex-col overflow-y-auto">
@@ -97,46 +93,34 @@ const StagedFilterMenu = ({ job, values }: WorkflowJobMenuProps) => {
9793
navigateBack({
9894
distance: 1,
9995
applyValues: (currentValues) => {
100-
const filterEmpty = (values: string[]) => {
101-
const filtered = values
102-
.map((value) => value.trim())
103-
.filter((value) => value);
96+
const strip = (list: string[]) => {
97+
const filtered = list.filter((item) => item);
10498

105-
if (filtered.length > 0) {
106-
return filtered;
107-
}
99+
return filtered.length > 0 ? filtered : undefined;
108100
};
109-
110-
const filters = Object.assign(
111-
{},
112-
// filter the the empty values from only and ignore lists
113-
...Object.entries(values)
114-
.map(([targetKey, target]) => {
115-
return {
116-
[targetKey]: Object.entries(target).map(
117-
([typeKey, type]) => {
118-
console.log(filterEmpty(type));
119-
return {
120-
[typeKey]: filterEmpty(type),
121-
};
122-
},
123-
),
124-
};
125-
})
126-
// filter out any target types that have no defined values
127-
.filter((target) =>
128-
Object.values(target).some(
129-
(type) =>
130-
type && Object.values(Object.values(type)[0])[0],
131-
),
132-
),
133-
);
101+
const branches = {
102+
only: strip(values.branches.only),
103+
ignore: strip(values.branches.ignore),
104+
};
105+
const hasBranches =
106+
branches.only?.length || branches.ignore?.length;
107+
const tags = {
108+
only: strip(values.tags.only),
109+
ignore: strip(values.tags.ignore),
110+
};
111+
const hasTags = tags.only?.length || tags.ignore?.length;
134112

135113
return {
136114
...currentValues,
137115
parameters: {
138116
...currentValues.parameters,
139-
filters,
117+
filters:
118+
hasBranches || hasTags
119+
? {
120+
branches: hasBranches ? branches : undefined,
121+
tags: hasTags ? tags : undefined,
122+
}
123+
: undefined,
140124
},
141125
};
142126
},
@@ -145,32 +129,29 @@ const StagedFilterMenu = ({ job, values }: WorkflowJobMenuProps) => {
145129
>
146130
{(formikProps) => (
147131
<Form className="flex flex-col flex-1">
148-
<TabbedMenu
149-
tabs={tabs}
150-
onChange={(index) => {
151-
setTarget(tabs[index].toLowerCase());
152-
}}
153-
>
154-
<div className="p-6">
155-
<FilterList
156-
type="Only"
157-
{...formikProps}
158-
target={target}
159-
></FilterList>
160-
<FilterList
161-
type="Ignore"
162-
{...formikProps}
163-
target={target}
164-
></FilterList>
165-
</div>
132+
<TabbedMenu tabs={tabs}>
133+
{['branches', 'tags'].map((target) => (
134+
<div className="p-6" key={target}>
135+
<FilterList
136+
type="Only"
137+
{...formikProps}
138+
target={target}
139+
></FilterList>
140+
<FilterList
141+
type="Ignore"
142+
{...formikProps}
143+
target={target}
144+
></FilterList>
145+
</div>
146+
))}
166147
</TabbedMenu>
167148

168149
<div className="border-t border-circle-gray-300 p-6 flex">
169150
<Button
170151
type="submit"
171152
className="ml-auto"
172153
variant="primary"
173-
disabled={!formikProps.dirty}
154+
// disabled={!formikProps.dirty}
174155
>
175156
Save Filter
176157
</Button>

0 commit comments

Comments
 (0)