Skip to content

Commit 7c2e903

Browse files
authored
fix(ecosystem): Preserve codeowners filters on update (#45810)
1 parent 33a2b8b commit 7c2e903

File tree

2 files changed

+44
-7
lines changed

2 files changed

+44
-7
lines changed

static/app/views/settings/project/projectOwnership/ownershipRulesTable.spec.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,40 @@ describe('OwnershipRulesTable', () => {
104104
expect(screen.queryByText('mytag')).toBeInTheDocument();
105105
});
106106

107+
it('preserves selected teams when rules are updated', () => {
108+
const rules: ParsedOwnershipRule[] = [
109+
{
110+
matcher: {pattern: 'filepath', type: 'path'},
111+
owners: [{type: 'user', id: user1.id, name: user1.name}],
112+
},
113+
{
114+
matcher: {pattern: 'anotherpath', type: 'path'},
115+
owners: [{type: 'user', id: user2.id, name: user2.name}],
116+
},
117+
];
118+
119+
const {rerender} = render(
120+
<OwnershipRulesTable projectRules={rules} codeowners={[]} />
121+
);
122+
123+
// Clear the filter
124+
userEvent.click(screen.getByRole('button', {name: 'My Teams'}));
125+
userEvent.click(screen.getByRole('button', {name: 'Clear'}));
126+
expect(screen.getAllByText('path')).toHaveLength(2);
127+
128+
const newRules: ParsedOwnershipRule[] = [
129+
...rules,
130+
{
131+
matcher: {pattern: 'thirdpath', type: 'path'},
132+
owners: [{type: 'user', id: user2.id, name: user2.name}],
133+
},
134+
];
135+
136+
rerender(<OwnershipRulesTable projectRules={newRules} codeowners={[]} />);
137+
expect(screen.getAllByText('path')).toHaveLength(3);
138+
expect(screen.getByRole('button', {name: 'Everyone'})).toBeInTheDocument();
139+
});
140+
107141
it('should paginate results', () => {
108142
const owners: Actor[] = [{type: 'user', id: user1.id, name: user1.name}];
109143
const rules: ParsedOwnershipRule[] = Array(100)

static/app/views/settings/project/projectOwnership/ownshipRulesTable.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export function OwnershipRulesTable({
4141
}: OwnershipRulesTableProps) {
4242
const [search, setSearch] = useState<string>('');
4343
const [page, setPage] = useState<number>(0);
44-
const [selectedActors, setSelectedActors] = useState<string[]>([]);
44+
const [selectedActors, setSelectedActors] = useState<string[] | null>(null);
4545
const {teams} = useTeams({provideUserTeams: true});
4646

4747
const combinedRules = useMemo(() => {
@@ -52,7 +52,7 @@ export function OwnershipRulesTable({
5252
}))
5353
);
5454

55-
return [...projectRules, ...codeownerRulesWithId];
55+
return [...codeownerRulesWithId, ...projectRules];
5656
}, [projectRules, codeowners]);
5757

5858
/**
@@ -91,10 +91,10 @@ export function OwnershipRulesTable({
9191
}, [allActors, teams]);
9292

9393
useEffect(() => {
94-
if (myTeams.length > 0) {
94+
if (myTeams.length > 0 && selectedActors === null) {
9595
setSelectedActors(myTeams.map(actor => `${actor.type}:${actor.id}`));
9696
}
97-
}, [myTeams]);
97+
}, [myTeams, selectedActors]);
9898

9999
/**
100100
* Rules chunked into pages
@@ -104,8 +104,10 @@ export function OwnershipRulesTable({
104104
rule =>
105105
// Filter by query
106106
(rule.matcher.type.includes(search) || rule.matcher.pattern.includes(search)) &&
107-
// Filter by selected actors
108-
(selectedActors.length === 0 ||
107+
// Selected actors not set
108+
(selectedActors === null ||
109+
// Selected actors was cleared
110+
selectedActors.length === 0 ||
109111
rule.owners.some(owner => selectedActors.includes(`${owner.type}:${owner.id}`)))
110112
);
111113

@@ -137,9 +139,10 @@ export function OwnershipRulesTable({
137139
<SearchAndSelectorWrapper>
138140
<OwnershipOwnerFilter
139141
actors={allActors}
140-
selectedTeams={selectedActors}
142+
selectedTeams={selectedActors ?? []}
141143
handleChangeFilter={handleChangeFilter}
142144
isMyTeams={
145+
!!selectedActors &&
143146
selectedActors.length > 0 &&
144147
isEqual(
145148
selectedActors,

0 commit comments

Comments
 (0)