Skip to content

Commit 126d665

Browse files
authored
feat: add ability to select/unselect all when updating api access tokens (#1538)
2 parents 6c30ebd + dc522dc commit 126d665

2 files changed

Lines changed: 144 additions & 76 deletions

File tree

apps/e2e/cypress/e2e/settings.cy.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1911,5 +1911,49 @@ context('Settings tests', () => {
19111911
);
19121912
});
19131913
});
1914+
1915+
it('User Officer should be able to select and unselect all permissions for a group', () => {
1916+
cy.login('officer');
1917+
cy.visit('/');
1918+
1919+
cy.contains('Settings').click();
1920+
cy.contains('API access tokens').click();
1921+
1922+
cy.get('[data-cy="create-new-entry"]').click();
1923+
1924+
cy.get('fieldset').first().as('permissionGroup');
1925+
1926+
cy.get('@permissionGroup')
1927+
.contains('button', 'Unselect all')
1928+
.should('not.exist');
1929+
1930+
// click 'Select all' and verify it switches to 'Unselect all'
1931+
cy.get('@permissionGroup').contains('button', 'Select all').click();
1932+
cy.get('@permissionGroup')
1933+
.contains('button', 'Select all')
1934+
.should('not.exist');
1935+
cy.get('@permissionGroup')
1936+
.contains('button', 'Unselect all')
1937+
.should('exist');
1938+
1939+
// verify all checkboxes are checked
1940+
cy.get('@permissionGroup')
1941+
.find('input[type="checkbox"]')
1942+
.should('be.checked');
1943+
1944+
// click 'Unselect all' and verify it switches to 'Select all'
1945+
cy.get('@permissionGroup').contains('button', 'Unselect all').click();
1946+
cy.get('@permissionGroup')
1947+
.contains('button', 'Unselect all')
1948+
.should('not.exist');
1949+
cy.get('@permissionGroup')
1950+
.contains('button', 'Select all')
1951+
.should('exist');
1952+
1953+
// verify all checkboxes are unchecked
1954+
cy.get('@permissionGroup')
1955+
.find('input[type="checkbox"]')
1956+
.should('not.be.checked');
1957+
});
19141958
});
19151959
});

apps/frontend/src/components/settings/apiAccessTokens/CreateUpdateApiAccessToken.tsx

Lines changed: 100 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -115,85 +115,109 @@ const CreateUpdateApiAccessToken = ({
115115

116116
return (
117117
<>
118-
{groups.map((group, index) => (
119-
<FormControl
120-
component="fieldset"
121-
variant="standard"
122-
key={index}
123-
sx={(theme) => ({
124-
border: `1px solid ${theme.palette.grey[200]}`,
125-
padding: theme.spacing(0, 1),
126-
width: '100%',
118+
{groups.map((group, index) => {
119+
const allSelected = group.items.every((item) =>
120+
formValues.accessPermissions.includes(item)
121+
);
127122

128-
'& legend': {
129-
textTransform: 'capitalize',
130-
},
131-
})}
132-
>
133-
<FormLabel component="legend">
134-
{group.groupName} {title} (
135-
<Link
136-
component="button"
137-
type="button"
138-
onClick={() => {
139-
group.items.forEach((item) => fieldArrayHelpers.push(item));
140-
}}
141-
>
142-
Select all
143-
</Link>
144-
)
145-
</FormLabel>
146-
<FormGroup>
147-
{schedulerAlert(group)}
148-
<Grid container spacing={1}>
149-
{group.items.map((item, index) => (
150-
<Grid
151-
item
152-
md={6}
153-
xs={12}
154-
key={index}
155-
sx={{
156-
'& label': {
157-
width: '100%',
123+
return (
124+
<FormControl
125+
component="fieldset"
126+
variant="standard"
127+
key={index}
128+
sx={(theme) => ({
129+
border: `1px solid ${theme.palette.grey[200]}`,
130+
padding: theme.spacing(0, 1),
131+
width: '100%',
132+
133+
'& legend': {
134+
textTransform: 'capitalize',
135+
},
136+
})}
137+
>
138+
<FormLabel component="legend">
139+
{group.groupName} {title} (
140+
<Link
141+
component="button"
142+
type="button"
143+
onClick={() => {
144+
if (allSelected) {
145+
const indicesToRemove = group.items
146+
.map((item) =>
147+
formValues.accessPermissions.indexOf(item)
148+
)
149+
.filter((index) => index !== -1)
150+
.sort((a, b) => b - a); //sort in descending order to avoid index shifting
151+
indicesToRemove.forEach((index) =>
152+
fieldArrayHelpers.remove(index)
153+
);
154+
} else {
155+
group.items.forEach((item) => {
156+
if (!formValues.accessPermissions.includes(item)) {
157+
fieldArrayHelpers.push(item);
158+
}
159+
});
160+
}
161+
}}
162+
>
163+
{allSelected ? 'Unselect all' : 'Select all'}
164+
</Link>
165+
)
166+
</FormLabel>
167+
<FormGroup>
168+
{schedulerAlert(group)}
169+
<Grid container spacing={1}>
170+
{group.items.map((item, index) => (
171+
<Grid
172+
item
173+
md={6}
174+
xs={12}
175+
key={index}
176+
sx={{
177+
'& label': {
178+
width: '100%',
158179

159-
'& .MuiFormControlLabel-label': {
160-
whiteSpace: 'nowrap',
161-
overflow: 'hidden',
162-
textOverflow: 'ellipsis',
180+
'& .MuiFormControlLabel-label': {
181+
whiteSpace: 'nowrap',
182+
overflow: 'hidden',
183+
textOverflow: 'ellipsis',
184+
},
163185
},
164-
},
165-
}}
166-
>
167-
<FormControlLabel
168-
control={
169-
<Checkbox
170-
id={item}
171-
name="accessPermissions"
172-
value={item}
173-
checked={formValues.accessPermissions.includes(item)}
174-
data-cy={`permission-${title.toLowerCase()}`}
175-
onChange={(e) => {
176-
if (e.target.checked) {
177-
fieldArrayHelpers.push(item);
178-
} else {
179-
const idx =
180-
formValues.accessPermissions.indexOf(item);
181-
fieldArrayHelpers.remove(idx);
182-
}
183-
}}
184-
inputProps={{
185-
'aria-label': 'primary checkbox',
186-
}}
187-
/>
188-
}
189-
label={item}
190-
/>
191-
</Grid>
192-
))}
193-
</Grid>
194-
</FormGroup>
195-
</FormControl>
196-
))}
186+
}}
187+
>
188+
<FormControlLabel
189+
control={
190+
<Checkbox
191+
id={item}
192+
name="accessPermissions"
193+
value={item}
194+
checked={formValues.accessPermissions.includes(
195+
item
196+
)}
197+
data-cy={`permission-${title.toLowerCase()}`}
198+
onChange={(e) => {
199+
if (e.target.checked) {
200+
fieldArrayHelpers.push(item);
201+
} else {
202+
const idx =
203+
formValues.accessPermissions.indexOf(item);
204+
fieldArrayHelpers.remove(idx);
205+
}
206+
}}
207+
inputProps={{
208+
'aria-label': 'primary checkbox',
209+
}}
210+
/>
211+
}
212+
label={item}
213+
/>
214+
</Grid>
215+
))}
216+
</Grid>
217+
</FormGroup>
218+
</FormControl>
219+
);
220+
})}
197221
</>
198222
);
199223
};

0 commit comments

Comments
 (0)