Skip to content
This repository has been archived by the owner on Oct 27, 2022. It is now read-only.

Commit

Permalink
fix: remove group owner concept (#1210)
Browse files Browse the repository at this point in the history
* fix: remove group owner concept

* fix: adapt e2e tests accordingly

* refactor users select to match improvement

* refactor: add user -> edit users

* feat: add edit users to group card actions

* add a few more UI improvements

* fix: edit group users icon

* improve loading behaviour

* fix group users refresh on card view

* improvement: create group form validation

* fix edit group, some refactoring

* fix: e2e tests, minor bugs

* fix: infinite re-renders due to useHiddenColumns useEffect array dependency

* fix re-rendering on useHiddenColumns for some tables

* refactor: validations into functions / variables
  • Loading branch information
nunogois committed Aug 11, 2022
1 parent a3e28cb commit 688f8cd
Show file tree
Hide file tree
Showing 27 changed files with 345 additions and 651 deletions.
53 changes: 3 additions & 50 deletions cypress/integration/groups/groups.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,6 @@ describe('groups', () => {
}
});

it('gives an error if a group does not have an owner', () => {
cy.get("[data-testid='NAVIGATE_TO_CREATE_GROUP']").click();

cy.intercept('POST', '/api/admin/groups').as('createGroup');

cy.get("[data-testid='UG_NAME_ID']").type(groupName);
cy.get("[data-testid='UG_DESC_ID']").type('hello-world');
cy.get("[data-testid='UG_USERS_ID']").click();
cy.contains(`unleash-e2e-user1-${randomId}`).click();
cy.get("[data-testid='UG_USERS_ADD_ID']").click();

cy.get("[data-testid='UG_CREATE_BTN_ID']").click();
cy.get("[data-testid='TOAST_TEXT']").contains(
'Group needs to have at least one Owner'
);
});

it('can create a group', () => {
cy.get("[data-testid='NAVIGATE_TO_CREATE_GROUP']").click();

Expand All @@ -65,9 +48,6 @@ describe('groups', () => {
cy.get("[data-testid='UG_DESC_ID']").type('hello-world');
cy.get("[data-testid='UG_USERS_ID']").click();
cy.contains(`unleash-e2e-user1-${randomId}`).click();
cy.get("[data-testid='UG_USERS_ADD_ID']").click();
cy.get("[data-testid='UG_USERS_TABLE_ROLE_ID']").click();
cy.contains('Owner').click();

cy.get("[data-testid='UG_CREATE_BTN_ID']").click();
cy.wait('@createGroup');
Expand All @@ -80,16 +60,8 @@ describe('groups', () => {
cy.intercept('POST', '/api/admin/groups').as('createGroup');

cy.get("[data-testid='UG_NAME_ID']").type(groupName);
cy.get("[data-testid='UG_DESC_ID']").type('hello-world');
cy.get("[data-testid='UG_USERS_ID']").click();
cy.contains(`unleash-e2e-user1-${randomId}`).click();
cy.get("[data-testid='UG_USERS_ADD_ID']").click();
cy.get("[data-testid='UG_USERS_TABLE_ROLE_ID']").click();
cy.contains('Owner').click();

cy.get("[data-testid='UG_CREATE_BTN_ID']").click();
cy.get("[data-testid='TOAST_TEXT']").contains(
'Group name already exists'
cy.get("[data-testid='INPUT_ERROR_TEXT'").contains(
'A group with that name already exists.'
);
});

Expand All @@ -108,34 +80,15 @@ describe('groups', () => {
it('can add user to a group', () => {
cy.contains(groupName).click();

cy.get("[data-testid='UG_ADD_USER_BTN_ID']").click();
cy.get("[data-testid='UG_EDIT_USERS_BTN_ID']").click();

cy.get("[data-testid='UG_USERS_ID']").click();
cy.contains(`unleash-e2e-user2-${randomId}`).click();
cy.get("[data-testid='UG_USERS_ADD_ID']").click();

cy.get("[data-testid='UG_SAVE_BTN_ID']").click();

cy.contains(`unleash-e2e-user1-${randomId}`);
cy.contains(`unleash-e2e-user2-${randomId}`);
cy.get("td span:contains('Owner')").should('have.length', 1);
cy.get("td span:contains('Member')").should('have.length', 1);
});

it('can edit user role in a group', () => {
cy.contains(groupName).click();

cy.get(`[data-testid='UG_EDIT_USER_BTN_ID-${userIds[1]}']`).click();

cy.get("[data-testid='UG_USERS_ROLE_ID']").click();
cy.get("li[data-value='Owner']").click();

cy.get("[data-testid='UG_SAVE_BTN_ID']").click();

cy.contains(`unleash-e2e-user1-${randomId}`);
cy.contains(`unleash-e2e-user2-${randomId}`);
cy.get("td span:contains('Owner')").should('have.length', 2);
cy.contains('Member').should('not.exist');
});

it('can remove user from a group', () => {
Expand Down
16 changes: 6 additions & 10 deletions src/component/admin/apiToken/ApiTokenTable/ApiTokenTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,14 @@ import { HighlightCell } from 'component/common/Table/cells/HighlightCell/Highli
import { Search } from 'component/common/Search/Search';
import useHiddenColumns from 'hooks/useHiddenColumns';

const hiddenColumnsSmall = ['Icon', 'createdAt'];
const hiddenColumnsFlagE = ['projects', 'environment'];

export const ApiTokenTable = () => {
const { tokens, loading } = useApiTokens();
const initialState = useMemo(() => ({ sortBy: [{ id: 'createdAt' }] }), []);
const { uiConfig } = useUiConfig();
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));

const {
getTableProps,
Expand All @@ -53,16 +57,8 @@ export const ApiTokenTable = () => {
useSortBy
);

useHiddenColumns(
setHiddenColumns,
['Icon', 'createdAt'],
useMediaQuery(theme.breakpoints.down('md'))
);
useHiddenColumns(
setHiddenColumns,
['projects', 'environment'],
!uiConfig.flags.E
);
useHiddenColumns(setHiddenColumns, hiddenColumnsSmall, isSmallScreen);
useHiddenColumns(setHiddenColumns, hiddenColumnsFlagE, !uiConfig.flags.E);

return (
<PageContent
Expand Down
22 changes: 20 additions & 2 deletions src/component/admin/groups/CreateGroup/CreateGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { UG_CREATE_BTN_ID } from 'utils/testIds';
import { Button } from '@mui/material';
import { CREATE } from 'constants/misc';
import { GO_BACK } from 'constants/navigate';
import { useGroups } from 'hooks/api/getters/useGroups/useGroups';

export const CreateGroup = () => {
const { setToastData, setToastApiError } = useToast();
Expand All @@ -26,14 +27,18 @@ export const CreateGroup = () => {
getGroupPayload,
clearErrors,
errors,
setErrors,
} = useGroupForm();

const { groups } = useGroups();
const { createGroup, loading } = useGroupApi();

const handleSubmit = async (e: Event) => {
e.preventDefault();
clearErrors();

if (!isValid) return;

const payload = getGroupPayload();
try {
const group = await createGroup(payload);
Expand Down Expand Up @@ -62,6 +67,19 @@ export const CreateGroup = () => {
navigate(GO_BACK);
};

const isNameEmpty = (name: string) => name.length;
const isNameUnique = (name: string) =>
!groups?.filter(group => group.name === name).length;
const isValid = isNameEmpty(name) && isNameUnique(name);

const onSetName = (name: string) => {
clearErrors();
if (!isNameUnique(name)) {
setErrors({ name: 'A group with that name already exists.' });
}
setName(name);
};

return (
<FormTemplate
loading={loading}
Expand All @@ -75,19 +93,19 @@ export const CreateGroup = () => {
name={name}
description={description}
users={users}
setName={setName}
setName={onSetName}
setDescription={setDescription}
setUsers={setUsers}
errors={errors}
handleSubmit={handleSubmit}
handleCancel={handleCancel}
mode={CREATE}
clearErrors={clearErrors}
>
<Button
type="submit"
variant="contained"
color="primary"
disabled={!isValid}
data-testid={UG_CREATE_BTN_ID}
>
Create group
Expand Down
23 changes: 21 additions & 2 deletions src/component/admin/groups/EditGroup/EditGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { useGroup } from 'hooks/api/getters/useGroup/useGroup';
import { UG_SAVE_BTN_ID } from 'utils/testIds';
import { GO_BACK } from 'constants/navigate';
import { useGroups } from 'hooks/api/getters/useGroups/useGroups';

export const EditGroup = () => {
const groupId = Number(useRequiredPathParam('groupId'));
const { group, refetchGroup } = useGroup(groupId);
const { refetchGroups } = useGroups();
const { setToastData, setToastApiError } = useToast();
const { uiConfig } = useUiConfig();
const navigate = useNavigate();
Expand All @@ -30,8 +32,10 @@ export const EditGroup = () => {
getGroupPayload,
clearErrors,
errors,
setErrors,
} = useGroupForm(group?.name, group?.description, group?.users);

const { groups } = useGroups();
const { updateGroup, loading } = useGroupApi();

const handleSubmit = async (e: Event) => {
Expand All @@ -42,6 +46,7 @@ export const EditGroup = () => {
try {
await updateGroup(groupId, payload);
refetchGroup();
refetchGroups();
navigate(GO_BACK);
setToastData({
title: 'Group updated successfully',
Expand All @@ -65,6 +70,20 @@ export const EditGroup = () => {
navigate(GO_BACK);
};

const isNameEmpty = (name: string) => name.length;
const isNameUnique = (name: string) =>
!groups?.filter(group => group.name === name && group.id !== groupId)
.length;
const isValid = isNameEmpty(name) && isNameUnique(name);

const onSetName = (name: string) => {
clearErrors();
if (!isNameUnique(name)) {
setErrors({ name: 'A group with that name already exists.' });
}
setName(name);
};

return (
<FormTemplate
loading={loading}
Expand All @@ -78,19 +97,19 @@ export const EditGroup = () => {
name={name}
description={description}
users={users}
setName={setName}
setName={onSetName}
setDescription={setDescription}
setUsers={setUsers}
errors={errors}
handleSubmit={handleSubmit}
handleCancel={handleCancel}
mode={EDIT}
clearErrors={clearErrors}
>
<Button
type="submit"
variant="contained"
color="primary"
disabled={!isValid}
data-testid={UG_SAVE_BTN_ID}
>
Save
Expand Down

0 comments on commit 688f8cd

Please sign in to comment.