From 607d7ce5ade0f56c7b0a62b2bd26e7cab901311b Mon Sep 17 00:00:00 2001 From: Douglas Fernandes Date: Thu, 28 Jan 2021 17:22:01 -0300 Subject: [PATCH 01/13] Add valid annotation for PageRequest params --- .../io/charlescd/moove/api/controller/V2UserGroupController.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moove/api/src/main/kotlin/io/charlescd/moove/api/controller/V2UserGroupController.kt b/moove/api/src/main/kotlin/io/charlescd/moove/api/controller/V2UserGroupController.kt index d17875fb6e..9744e39db8 100644 --- a/moove/api/src/main/kotlin/io/charlescd/moove/api/controller/V2UserGroupController.kt +++ b/moove/api/src/main/kotlin/io/charlescd/moove/api/controller/V2UserGroupController.kt @@ -83,7 +83,7 @@ class V2UserGroupController( @GetMapping fun findAll( @RequestParam("name", required = false) name: String?, - pageable: PageRequest + @Valid pageable: PageRequest ): ResourcePageResponse { return this.findAllUserGroupsInteractor.execute(name, pageable) } From f437af4c159ecd0533940165132af96514019afa Mon Sep 17 00:00:00 2001 From: Douglas Fernandes Date: Fri, 29 Jan 2021 10:29:56 -0300 Subject: [PATCH 02/13] Improvements --- ui/src/core/providers/user-group.ts | 7 ++- ui/src/modules/Groups/Menu/index.tsx | 73 ++++++++++++++++++---------- ui/src/modules/Groups/Menu/styled.ts | 6 +++ ui/src/modules/Groups/hooks.ts | 4 +- ui/src/modules/Groups/index.tsx | 15 +++--- 5 files changed, 67 insertions(+), 38 deletions(-) diff --git a/ui/src/core/providers/user-group.ts b/ui/src/core/providers/user-group.ts index 1182432cfc..e59330562b 100644 --- a/ui/src/core/providers/user-group.ts +++ b/ui/src/core/providers/user-group.ts @@ -21,6 +21,7 @@ const endpoint = '/moove/v2/user-groups'; export interface UserGroupFilter { name?: string; + page?: number; } export interface UserGroupSave { @@ -32,7 +33,8 @@ export interface UserGroupMemberSave { } const initialGroupUserFilter = { - name: '' + name: '', + page: 0 }; export const findAllUserGroup = ( @@ -40,7 +42,8 @@ export const findAllUserGroup = ( ) => { const params = new URLSearchParams({ size: `${DEFAULT_PAGE_SIZE}`, - name: filter?.name + name: filter?.name, + page: `${filter.page ?? 0}` }); return baseRequest(`${endpoint}?${params}`); diff --git a/ui/src/modules/Groups/Menu/index.tsx b/ui/src/modules/Groups/Menu/index.tsx index 69f73b3d15..45cd30c736 100644 --- a/ui/src/modules/Groups/Menu/index.tsx +++ b/ui/src/modules/Groups/Menu/index.tsx @@ -14,48 +14,71 @@ * limitations under the License. */ -import React from 'react'; +import React, { Fragment, useEffect, useState } from 'react'; import map from 'lodash/map'; import some from 'lodash/some'; import method from 'lodash/method'; import isEmpty from 'lodash/isEmpty'; import Text from 'core/components/Text'; import LabeledIcon from 'core/components/LabeledIcon'; +import InfiniteScroll from 'core/components/InfiniteScroll'; import MenuItem from './MenuItem'; -import Styled from './styled'; import Loader from './Loaders'; +import Styled from './styled'; -import { UserGroupPaginationItem } from '../interfaces/UserGroupsPagination'; +import { + UserGroupPagination, + UserGroupPaginationItem +} from '../interfaces/UserGroupsPagination'; +import { useFindAllUserGroup } from '../hooks'; +import { useGlobalState } from 'core/state/hooks'; interface ListProps { - items: UserGroupPaginationItem[]; + // list: UserGroupPagination; selectedItems: string[]; onSelect: (id: string) => void; } interface Props extends ListProps { - onSearch: (name: string) => void; onCreate: () => void; - isLoading: boolean; } -const UserGroupList = ({ items, selectedItems, onSelect }: ListProps) => ( - <> - {map(items, item => ( - - ))} - -); +const UserGroupMenu = ({ onCreate, selectedItems, onSelect }: Props) => { + const [name, setName] = useState(''); + const [getUserGroups, loading] = useFindAllUserGroup(); + const { list } = useGlobalState(({ userGroups }) => userGroups); + + useEffect(() => { + const page = 0; + console.log('name', name); + getUserGroups(name, page); + }, [name]); + + const loadMore = (page: number) => { + getUserGroups(name, page); + }; + + const renderList = ({ selectedItems, onSelect }: ListProps) => ( + } + > + {map(list?.content, item => ( + + ))} + + ); -const UserGroupMenu = ({ onSearch, onCreate, isLoading, ...rest }: Props) => { return ( - <> + @@ -64,16 +87,16 @@ const UserGroupMenu = ({ onSearch, onCreate, isLoading, ...rest }: Props) => { - + - {isEmpty(rest.items) && isLoading ? ( + {isEmpty(list?.content) && loading ? ( ) : ( - + renderList({ selectedItems, onSelect }) )} - + ); }; diff --git a/ui/src/modules/Groups/Menu/styled.ts b/ui/src/modules/Groups/Menu/styled.ts index 3c4b88a192..8ab43c6669 100644 --- a/ui/src/modules/Groups/Menu/styled.ts +++ b/ui/src/modules/Groups/Menu/styled.ts @@ -22,6 +22,7 @@ import ButtonComponent from 'core/components/Button'; import Form from 'core/components/Form'; import Text from 'core/components/Text'; import { COLOR_BLACK_MARLIN } from 'core/assets/colors'; +import LoaderMenuComponent from './Loaders'; const SearchInput = styled(SearchInputComponent)` margin: 15px 0; @@ -98,6 +99,10 @@ const ButtonModal = styled(ButtonComponent.Default)` margin-top: 20px; `; +const Loader = styled(LoaderMenuComponent.List)` + margin-left: 16px; +`; + export default { SearchInput, List, @@ -107,6 +112,7 @@ export default { Icon, Link, Button, + Loader, Modal: { Input: ModalInput, Title: ModalTitle, diff --git a/ui/src/modules/Groups/hooks.ts b/ui/src/modules/Groups/hooks.ts index 46c8ed0665..190d11c174 100644 --- a/ui/src/modules/Groups/hooks.ts +++ b/ui/src/modules/Groups/hooks.ts @@ -48,8 +48,8 @@ export const useFindAllUserGroup = (): [ const { response, loading } = userGroupData; const loadUserGroupList = useCallback( - (name: string) => { - getUserGroups({ name }); + (name: string, page: string) => { + getUserGroups({ name, page }); }, [getUserGroups] ); diff --git a/ui/src/modules/Groups/index.tsx b/ui/src/modules/Groups/index.tsx index 4aa3278fdd..6dee7b4787 100644 --- a/ui/src/modules/Groups/index.tsx +++ b/ui/src/modules/Groups/index.tsx @@ -37,11 +37,11 @@ export enum FormAction { const UserGroups = () => { const profileName = getProfileByKey('name'); const history = useHistory(); - const [search, setSearch] = useState(''); + // const [search, setSearch] = useState(''); const [toggleModal, setToggleModal] = useState(false); const [isDisabled, setIsDisabled] = useState(true); - const [getUserGroups, loading] = useFindAllUserGroup(); - const { list } = useGlobalState(state => state.userGroups); + // const [getUserGroups, loading] = useFindAllUserGroup(); + // const { list } = useGlobalState(({ userGroups }) => userGroups); const { register, watch, handleSubmit } = useForm(); const watchName = watch('name'); const { @@ -54,9 +54,9 @@ const UserGroups = () => { setIsDisabled(isEmpty(watchName)); }, [watchName]); - useEffect(() => { - getUserGroups(search); - }, [search, getUserGroups]); + // useEffect(() => { + // getUserGroups(search); + // }, [search, getUserGroups]); useEffect(() => { if (userGroupResponse) { @@ -94,13 +94,10 @@ const UserGroups = () => { {toggleModal && renderModal()} addParamUserGroup(history, `${id}~${FormAction.view}`) } - onSearch={setSearch} onCreate={() => setToggleModal(true)} /> From 76f81a5b6f9296ae66fb35a121f44ef2d2c9d866 Mon Sep 17 00:00:00 2001 From: Douglas Fernandes Date: Fri, 29 Jan 2021 15:20:38 -0300 Subject: [PATCH 03/13] Improvements --- ui/src/modules/Groups/Menu/Loaders/list.tsx | 6 +- ui/src/modules/Groups/Menu/MenuItem.tsx | 4 +- ui/src/modules/Groups/Menu/index.tsx | 67 +++++++++------------ ui/src/modules/Groups/Menu/styled.ts | 9 ++- ui/src/modules/Groups/helpers.ts | 5 ++ ui/src/modules/Groups/hooks.ts | 2 +- ui/src/modules/Groups/index.tsx | 13 +--- ui/src/modules/Groups/state/actions.ts | 12 ++-- ui/src/modules/Groups/state/reducer.ts | 9 ++- 9 files changed, 57 insertions(+), 70 deletions(-) diff --git a/ui/src/modules/Groups/Menu/Loaders/list.tsx b/ui/src/modules/Groups/Menu/Loaders/list.tsx index 56e304eb00..773324ce77 100644 --- a/ui/src/modules/Groups/Menu/Loaders/list.tsx +++ b/ui/src/modules/Groups/Menu/Loaders/list.tsx @@ -26,8 +26,8 @@ export const Loader: FunctionComponent = () => ( backgroundColor="#3a393c" foregroundColor="#2c2b2e" > - - - + + + ); diff --git a/ui/src/modules/Groups/Menu/MenuItem.tsx b/ui/src/modules/Groups/Menu/MenuItem.tsx index c143e8f5de..e912c0bfb5 100644 --- a/ui/src/modules/Groups/Menu/MenuItem.tsx +++ b/ui/src/modules/Groups/Menu/MenuItem.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { memo } from 'react'; +import React from 'react'; import Text from 'core/components/Text'; import Styled from './styled'; @@ -33,4 +33,4 @@ const MenuItem = ({ id, name, onSelect, isActive }: Props) => ( ); -export default memo(MenuItem); +export default MenuItem; diff --git a/ui/src/modules/Groups/Menu/index.tsx b/ui/src/modules/Groups/Menu/index.tsx index 45cd30c736..a994b8dfd7 100644 --- a/ui/src/modules/Groups/Menu/index.tsx +++ b/ui/src/modules/Groups/Menu/index.tsx @@ -14,10 +14,8 @@ * limitations under the License. */ -import React, { Fragment, useEffect, useState } from 'react'; +import React, { Fragment, useEffect, useState, useCallback } from 'react'; import map from 'lodash/map'; -import some from 'lodash/some'; -import method from 'lodash/method'; import isEmpty from 'lodash/isEmpty'; import Text from 'core/components/Text'; import LabeledIcon from 'core/components/LabeledIcon'; @@ -25,55 +23,50 @@ import InfiniteScroll from 'core/components/InfiniteScroll'; import MenuItem from './MenuItem'; import Loader from './Loaders'; import Styled from './styled'; - -import { - UserGroupPagination, - UserGroupPaginationItem -} from '../interfaces/UserGroupsPagination'; +import { isActiveById } from '../helpers'; import { useFindAllUserGroup } from '../hooks'; import { useGlobalState } from 'core/state/hooks'; +import { UserGroupPaginationItem } from '../interfaces/UserGroupsPagination'; -interface ListProps { - // list: UserGroupPagination; - selectedItems: string[]; - onSelect: (id: string) => void; -} - -interface Props extends ListProps { +interface Props { onCreate: () => void; + onSelect: (id: string) => void; } -const UserGroupMenu = ({ onCreate, selectedItems, onSelect }: Props) => { +const UserGroupMenu = ({ onCreate, onSelect }: Props) => { const [name, setName] = useState(''); const [getUserGroups, loading] = useFindAllUserGroup(); const { list } = useGlobalState(({ userGroups }) => userGroups); + const loadByPage = useCallback( + (page: number) => { + getUserGroups(name, page); + }, + [name, getUserGroups] + ); + useEffect(() => { - const page = 0; - console.log('name', name); - getUserGroups(name, page); - }, [name]); + loadByPage(0); + }, [loadByPage]); - const loadMore = (page: number) => { - getUserGroups(name, page); - }; + const renderItem = (item: UserGroupPaginationItem) => ( + + ); - const renderList = ({ selectedItems, onSelect }: ListProps) => ( + const renderList = () => ( } > - {map(list?.content, item => ( - - ))} + {map(list?.content, item => renderItem(item))} ); @@ -89,11 +82,7 @@ const UserGroupMenu = ({ onCreate, selectedItems, onSelect }: Props) => { - {isEmpty(list?.content) && loading ? ( - - ) : ( - renderList({ selectedItems, onSelect }) - )} + {isEmpty(list?.content) && loading ? : renderList()} diff --git a/ui/src/modules/Groups/Menu/styled.ts b/ui/src/modules/Groups/Menu/styled.ts index 8ab43c6669..031fca11c0 100644 --- a/ui/src/modules/Groups/Menu/styled.ts +++ b/ui/src/modules/Groups/Menu/styled.ts @@ -33,10 +33,6 @@ const List = styled.div` display: flex; flex-direction: column; margin: 0; - - > * { - padding: 0 16px; - } `; const ListItem = styled(LabeledIcon)` @@ -69,6 +65,8 @@ const Link = styled('button')` background: none; border: none; text-decoration: none; + width: 100%; + padding: 0 16px; background-color: ${({ isActive }) => isActive ? COLOR_BLACK_MARLIN : 'transparent'}; `; @@ -100,7 +98,8 @@ const ButtonModal = styled(ButtonComponent.Default)` `; const Loader = styled(LoaderMenuComponent.List)` - margin-left: 16px; + /* margin-left: 16px; */ + padding: 0 16px; `; export default { diff --git a/ui/src/modules/Groups/helpers.ts b/ui/src/modules/Groups/helpers.ts index d89e0420b3..32db1df94a 100644 --- a/ui/src/modules/Groups/helpers.ts +++ b/ui/src/modules/Groups/helpers.ts @@ -17,6 +17,8 @@ import without from 'lodash/without'; import { History } from 'history'; import map from 'lodash/map'; +import some from 'lodash/some'; +import method from 'lodash/method'; import routes from 'core/constants/routes'; import getQueryStrings from 'core/utils/query'; import includes from 'lodash/includes'; @@ -58,3 +60,6 @@ export const addParamUserGroup = (history: History, usergroupId: string) => { search: query.toString() }); }; + +export const isActiveById = (id: string) => + some(getSelectedUserGroups(), method('includes', id)); diff --git a/ui/src/modules/Groups/hooks.ts b/ui/src/modules/Groups/hooks.ts index 190d11c174..743a132022 100644 --- a/ui/src/modules/Groups/hooks.ts +++ b/ui/src/modules/Groups/hooks.ts @@ -48,7 +48,7 @@ export const useFindAllUserGroup = (): [ const { response, loading } = userGroupData; const loadUserGroupList = useCallback( - (name: string, page: string) => { + (name: string, page = 0) => { getUserGroups({ name, page }); }, [getUserGroups] diff --git a/ui/src/modules/Groups/index.tsx b/ui/src/modules/Groups/index.tsx index 6dee7b4787..7b8a07e094 100644 --- a/ui/src/modules/Groups/index.tsx +++ b/ui/src/modules/Groups/index.tsx @@ -21,12 +21,11 @@ import isEmpty from 'lodash/isEmpty'; import Page from 'core/components/Page'; import Modal from 'core/components/Modal'; import routes from 'core/constants/routes'; -import { useGlobalState } from 'core/state/hooks'; import { getProfileByKey } from 'core/utils/profile'; import Menu from './Menu'; import Tabs from './Tabs'; -import { addParamUserGroup, getSelectedUserGroups } from './helpers'; -import { useFindAllUserGroup, useCreateUserGroup } from './hooks'; +import { addParamUserGroup } from './helpers'; +import { useCreateUserGroup } from './hooks'; import Styled from './styled'; export enum FormAction { @@ -37,11 +36,8 @@ export enum FormAction { const UserGroups = () => { const profileName = getProfileByKey('name'); const history = useHistory(); - // const [search, setSearch] = useState(''); const [toggleModal, setToggleModal] = useState(false); const [isDisabled, setIsDisabled] = useState(true); - // const [getUserGroups, loading] = useFindAllUserGroup(); - // const { list } = useGlobalState(({ userGroups }) => userGroups); const { register, watch, handleSubmit } = useForm(); const watchName = watch('name'); const { @@ -54,10 +50,6 @@ const UserGroups = () => { setIsDisabled(isEmpty(watchName)); }, [watchName]); - // useEffect(() => { - // getUserGroups(search); - // }, [search, getUserGroups]); - useEffect(() => { if (userGroupResponse) { setToggleModal(false); @@ -94,7 +86,6 @@ const UserGroups = () => { {toggleModal && renderModal()} addParamUserGroup(history, `${id}~${FormAction.view}`) } diff --git a/ui/src/modules/Groups/state/actions.ts b/ui/src/modules/Groups/state/actions.ts index 5286c2d237..5533e16b37 100644 --- a/ui/src/modules/Groups/state/actions.ts +++ b/ui/src/modules/Groups/state/actions.ts @@ -18,31 +18,31 @@ import { UserGroupPagination } from '../interfaces/UserGroupsPagination'; import { UserGroup } from '../interfaces/UserGroups'; export enum ACTION_TYPES { - listUserGroups = 'USERS/LIST_USERS_GROUPS', - getUserGroup = 'USERS/GET_USER_GROUP' + loadedUserGroups = 'USER_GROUPS/LOADED_USERS_GROUPS', + loadedUserGroup = 'USER_GROUPS/GET_USER_GROUP' } interface ListUserGroupsActionType { - type: typeof ACTION_TYPES.listUserGroups; + type: typeof ACTION_TYPES.loadedUserGroups; payload: UserGroupPagination; } interface GetUserGroupActionType { - type: typeof ACTION_TYPES.getUserGroup; + type: typeof ACTION_TYPES.loadedUserGroup; payload: UserGroup; } export const listUserGroupsAction = ( payload: UserGroupPagination ): UserGroupsActionTypes => ({ - type: ACTION_TYPES.listUserGroups, + type: ACTION_TYPES.loadedUserGroups, payload }); export const getUserGroupAction = ( payload: UserGroup ): UserGroupsActionTypes => ({ - type: ACTION_TYPES.getUserGroup, + type: ACTION_TYPES.loadedUserGroup, payload }); diff --git a/ui/src/modules/Groups/state/reducer.ts b/ui/src/modules/Groups/state/reducer.ts index 3bea0c71b9..eb45f209c4 100644 --- a/ui/src/modules/Groups/state/reducer.ts +++ b/ui/src/modules/Groups/state/reducer.ts @@ -36,13 +36,16 @@ export const userGroupReducer = ( action: UserGroupsActionTypes ): UserGroupState => { switch (action.type) { - case ACTION_TYPES.listUserGroups: { + case ACTION_TYPES.loadedUserGroups: { return { ...state, - list: action.payload + list: { + ...action.payload, + content: [...state.list.content, ...(action?.payload?.content ?? [])] + } }; } - case ACTION_TYPES.getUserGroup: { + case ACTION_TYPES.loadedUserGroup: { return { ...state, item: action.payload From e9d41454e8446116600b9e937a27957d9ff28190 Mon Sep 17 00:00:00 2001 From: Douglas Fernandes Date: Fri, 29 Jan 2021 16:35:51 -0300 Subject: [PATCH 04/13] Improvements --- ui/src/modules/Groups/Menu/index.tsx | 12 +++++++----- ui/src/modules/Groups/Menu/styled.ts | 6 +++++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ui/src/modules/Groups/Menu/index.tsx b/ui/src/modules/Groups/Menu/index.tsx index ad2a3e2f60..0ae680e2ad 100644 --- a/ui/src/modules/Groups/Menu/index.tsx +++ b/ui/src/modules/Groups/Menu/index.tsx @@ -70,12 +70,14 @@ const UserGroupMenu = ({ onCreate, onSelect }: Props) => { ); - const renderContent = () => - isEmpty(list?.content) ? ( + const renderEmpty = () => ( + No User group was found - ) : ( - renderList() - ); + + ); + + const renderContent = () => + isEmpty(list?.content) ? renderEmpty() : renderList(); return ( diff --git a/ui/src/modules/Groups/Menu/styled.ts b/ui/src/modules/Groups/Menu/styled.ts index 031fca11c0..4486334373 100644 --- a/ui/src/modules/Groups/Menu/styled.ts +++ b/ui/src/modules/Groups/Menu/styled.ts @@ -98,7 +98,10 @@ const ButtonModal = styled(ButtonComponent.Default)` `; const Loader = styled(LoaderMenuComponent.List)` - /* margin-left: 16px; */ + padding: 0 16px; +`; + +const Empty = styled.div` padding: 0 16px; `; @@ -112,6 +115,7 @@ export default { Link, Button, Loader, + Empty, Modal: { Input: ModalInput, Title: ModalTitle, From daed4ceda5b414c8b70130cb0879d35ce3350e55 Mon Sep 17 00:00:00 2001 From: Douglas Fernandes Date: Sat, 30 Jan 2021 09:35:51 -0300 Subject: [PATCH 05/13] Improvements --- .../Groups/Menu/__tests__/Menu.spec.tsx | 41 +++++++++++-------- ui/src/modules/Groups/Menu/index.tsx | 12 +++--- ui/src/modules/Groups/hooks.ts | 4 +- ui/src/modules/Groups/state/actions.ts | 4 +- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/ui/src/modules/Groups/Menu/__tests__/Menu.spec.tsx b/ui/src/modules/Groups/Menu/__tests__/Menu.spec.tsx index 95e849c7d4..c4cd6bcd00 100644 --- a/ui/src/modules/Groups/Menu/__tests__/Menu.spec.tsx +++ b/ui/src/modules/Groups/Menu/__tests__/Menu.spec.tsx @@ -17,42 +17,51 @@ import React from 'react'; import { render, screen, waitFor } from 'unit-test/testUtils'; import { UserGroupItem } from './fixtures'; -import { FetchMock } from 'jest-fetch-mock/types'; -import userEvent from '@testing-library/user-event'; +import * as StateHooks from 'core/state/hooks'; import Menu from '../index'; -test('render Menu users groups default', async () => { +test('render Menu user groups default', async () => { render( ); - const menu = screen.getByTestId('users-groups-menu'); - const emptyItems = screen.getByText('No User group was found'); + const menu = await screen.findByTestId('user-groups-menu'); + const emptyItems = await screen.findByText('No User group was found'); expect(menu).toBeInTheDocument(); expect(emptyItems).toBeInTheDocument(); }); -test('render Menu items', async () => { +test('render Menu user groups items', async () => { + jest.spyOn(StateHooks, 'useGlobalState').mockImplementation(() => ({ + list: { + content: [{ + id: '1', + name: 'group', + page: 0, + size: 1, + totalPages: 1, + last: true, + users: [{ + id: '2', + name: 'Charles', + email: 'charlescd@zup.com.br', + createdAt: '2021-01-01 01:01' + }] + }] + }, + })); + render( ); - const menuItem = screen.getByTestId('group-menu-item-1'); + const menuItem = await screen.findByTestId('group-menu-item-1'); expect(menuItem).toBeInTheDocument(); - }); diff --git a/ui/src/modules/Groups/Menu/index.tsx b/ui/src/modules/Groups/Menu/index.tsx index 0ae680e2ad..c1acb8db94 100644 --- a/ui/src/modules/Groups/Menu/index.tsx +++ b/ui/src/modules/Groups/Menu/index.tsx @@ -49,12 +49,12 @@ const UserGroupMenu = ({ onCreate, onSelect }: Props) => { loadByPage(0); }, [loadByPage]); - const renderItem = (item: UserGroupPaginationItem) => ( + const renderItem = ({ id, name }: UserGroupPaginationItem) => ( ); @@ -81,7 +81,7 @@ const UserGroupMenu = ({ onCreate, onSelect }: Props) => { return ( - + Create user group diff --git a/ui/src/modules/Groups/hooks.ts b/ui/src/modules/Groups/hooks.ts index 743a132022..e619330504 100644 --- a/ui/src/modules/Groups/hooks.ts +++ b/ui/src/modules/Groups/hooks.ts @@ -28,7 +28,7 @@ import { removeMemberToUserGroup } from 'core/providers/user-group'; import { UserGroupPagination } from './interfaces/UserGroupsPagination'; -import { listUserGroupsAction } from './state/actions'; +import { loadUserGroupsAction } from './state/actions'; import { UserPagination } from 'modules/Users/interfaces/UserPagination'; import { findAllUsers } from 'core/providers/users'; import { toogleNotification } from 'core/components/Notification/state/actions'; @@ -56,7 +56,7 @@ export const useFindAllUserGroup = (): [ useEffect(() => { if (response) { - dispatch(listUserGroupsAction(response)); + dispatch(loadUserGroupsAction(response)); } }, [response, dispatch]); diff --git a/ui/src/modules/Groups/state/actions.ts b/ui/src/modules/Groups/state/actions.ts index 5533e16b37..52b29bc32e 100644 --- a/ui/src/modules/Groups/state/actions.ts +++ b/ui/src/modules/Groups/state/actions.ts @@ -32,14 +32,14 @@ interface GetUserGroupActionType { payload: UserGroup; } -export const listUserGroupsAction = ( +export const loadUserGroupsAction = ( payload: UserGroupPagination ): UserGroupsActionTypes => ({ type: ACTION_TYPES.loadedUserGroups, payload }); -export const getUserGroupAction = ( +export const loadUserGroupAction = ( payload: UserGroup ): UserGroupsActionTypes => ({ type: ACTION_TYPES.loadedUserGroup, From d29db64756a9955d8849aff8a2f215014d644d22 Mon Sep 17 00:00:00 2001 From: Douglas Fernandes Date: Mon, 1 Feb 2021 10:38:24 -0300 Subject: [PATCH 06/13] Update menu after delete or add new one --- ui/src/modules/Groups/hooks.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ui/src/modules/Groups/hooks.ts b/ui/src/modules/Groups/hooks.ts index e619330504..ff62bb6dd4 100644 --- a/ui/src/modules/Groups/hooks.ts +++ b/ui/src/modules/Groups/hooks.ts @@ -96,8 +96,9 @@ export const useCreateUserGroup = (): { loading: boolean; response: UserGroup; } => { + const dispatch = useDispatch(); const history = useHistory(); - const [listUserGroups] = useFindAllUserGroup(); + const [getAllUserGroups, , userGroups] = useFindAllUserGroup(); const [usersData, save] = useFetch(saveUserGroup); const { response, loading } = usersData; @@ -108,12 +109,18 @@ export const useCreateUserGroup = (): { [save] ); + useEffect(() => { + if (userGroups) { + dispatch(loadUserGroupsAction(userGroups)); + } + }, [dispatch, userGroups]); + useEffect(() => { if (response) { - listUserGroups(); + getAllUserGroups(); addParamUserGroup(history, `${response?.id}~${FormAction.edit}`); } - }, [response, listUserGroups, history]); + }, [response, getAllUserGroups, history]); return { createUserGroup, @@ -172,9 +179,10 @@ export const useDeleteUserGroup = (): [Function, UserGroup, boolean] => { useEffect(() => { if (userGroups) { + dispatch(loadUserGroupsAction(userGroups)); setIsFinished(true); } - }, [userGroups]); + }, [dispatch, userGroups]); useEffect(() => { if (error) { From 9131d5812726f0e035a74f8cd6be9fb1e68f8386 Mon Sep 17 00:00:00 2001 From: Douglas Fernandes Date: Mon, 1 Feb 2021 15:28:17 -0300 Subject: [PATCH 07/13] Add default value for name pagination param --- ui/src/core/providers/user-group.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/core/providers/user-group.ts b/ui/src/core/providers/user-group.ts index e59330562b..26a21494ef 100644 --- a/ui/src/core/providers/user-group.ts +++ b/ui/src/core/providers/user-group.ts @@ -42,7 +42,7 @@ export const findAllUserGroup = ( ) => { const params = new URLSearchParams({ size: `${DEFAULT_PAGE_SIZE}`, - name: filter?.name, + name: filter?.name || '', page: `${filter.page ?? 0}` }); From 5cce99e32f8b88de71d7f2a6ce86b9be307e49b4 Mon Sep 17 00:00:00 2001 From: Douglas Fernandes Date: Mon, 1 Feb 2021 15:28:26 -0300 Subject: [PATCH 08/13] Add reset reducer action --- ui/src/modules/Groups/hooks.ts | 4 +++- ui/src/modules/Groups/state/actions.ts | 14 ++++++++++++-- ui/src/modules/Groups/state/reducer.ts | 6 ++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/ui/src/modules/Groups/hooks.ts b/ui/src/modules/Groups/hooks.ts index ff62bb6dd4..cef9f97de4 100644 --- a/ui/src/modules/Groups/hooks.ts +++ b/ui/src/modules/Groups/hooks.ts @@ -28,7 +28,7 @@ import { removeMemberToUserGroup } from 'core/providers/user-group'; import { UserGroupPagination } from './interfaces/UserGroupsPagination'; -import { loadUserGroupsAction } from './state/actions'; +import { loadUserGroupsAction, resetUserGroupsAction } from './state/actions'; import { UserPagination } from 'modules/Users/interfaces/UserPagination'; import { findAllUsers } from 'core/providers/users'; import { toogleNotification } from 'core/components/Notification/state/actions'; @@ -111,6 +111,7 @@ export const useCreateUserGroup = (): { useEffect(() => { if (userGroups) { + dispatch(resetUserGroupsAction()); dispatch(loadUserGroupsAction(userGroups)); } }, [dispatch, userGroups]); @@ -179,6 +180,7 @@ export const useDeleteUserGroup = (): [Function, UserGroup, boolean] => { useEffect(() => { if (userGroups) { + dispatch(resetUserGroupsAction()); dispatch(loadUserGroupsAction(userGroups)); setIsFinished(true); } diff --git a/ui/src/modules/Groups/state/actions.ts b/ui/src/modules/Groups/state/actions.ts index 52b29bc32e..4cc1526c0e 100644 --- a/ui/src/modules/Groups/state/actions.ts +++ b/ui/src/modules/Groups/state/actions.ts @@ -19,7 +19,8 @@ import { UserGroup } from '../interfaces/UserGroups'; export enum ACTION_TYPES { loadedUserGroups = 'USER_GROUPS/LOADED_USERS_GROUPS', - loadedUserGroup = 'USER_GROUPS/GET_USER_GROUP' + loadedUserGroup = 'USER_GROUPS/GET_USER_GROUP', + resetUserGroups = 'USER_GROUPS/RESET_USERS_GROUPS' } interface ListUserGroupsActionType { @@ -32,6 +33,10 @@ interface GetUserGroupActionType { payload: UserGroup; } +interface ResetUserGroupsType { + type: typeof ACTION_TYPES.resetUserGroups; +} + export const loadUserGroupsAction = ( payload: UserGroupPagination ): UserGroupsActionTypes => ({ @@ -46,6 +51,11 @@ export const loadUserGroupAction = ( payload }); +export const resetUserGroupsAction = (): UserGroupsActionTypes => ({ + type: ACTION_TYPES.resetUserGroups +}); + export type UserGroupsActionTypes = | ListUserGroupsActionType - | GetUserGroupActionType; + | GetUserGroupActionType + | ResetUserGroupsType; diff --git a/ui/src/modules/Groups/state/reducer.ts b/ui/src/modules/Groups/state/reducer.ts index eb45f209c4..cee5f94815 100644 --- a/ui/src/modules/Groups/state/reducer.ts +++ b/ui/src/modules/Groups/state/reducer.ts @@ -51,6 +51,12 @@ export const userGroupReducer = ( item: action.payload }; } + case ACTION_TYPES.resetUserGroups: { + return { + ...state, + list: userGroupInitialState.list + }; + } default: { return state; } From df72e13ad0250583f119d4a7103cbe8f04f59aa6 Mon Sep 17 00:00:00 2001 From: Douglas Fernandes Date: Wed, 3 Feb 2021 10:08:08 -0300 Subject: [PATCH 09/13] Add @Valid annotation for pageRequest --- .../io/charlescd/moove/api/controller/V2ModuleController.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moove/api/src/main/kotlin/io/charlescd/moove/api/controller/V2ModuleController.kt b/moove/api/src/main/kotlin/io/charlescd/moove/api/controller/V2ModuleController.kt index 542fb40060..631776053a 100644 --- a/moove/api/src/main/kotlin/io/charlescd/moove/api/controller/V2ModuleController.kt +++ b/moove/api/src/main/kotlin/io/charlescd/moove/api/controller/V2ModuleController.kt @@ -84,7 +84,7 @@ class V2ModuleController( fun findAllModules( @RequestHeader("x-workspace-id") workspaceId: String, @RequestParam("name", required = false) name: String?, - pageRequest: PageRequest + @Valid pageRequest: PageRequest ): ResourcePageResponse { return this.findAllModulesInteractor.execute(workspaceId, name, pageRequest) } From 5278f62757b37731e2e77c1c788c0a4fe6fd13b3 Mon Sep 17 00:00:00 2001 From: Douglas Fernandes Date: Wed, 3 Feb 2021 10:18:01 -0300 Subject: [PATCH 10/13] Remove incorrect annotation for this Pull Request --- .../io/charlescd/moove/api/controller/V2ModuleController.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moove/api/src/main/kotlin/io/charlescd/moove/api/controller/V2ModuleController.kt b/moove/api/src/main/kotlin/io/charlescd/moove/api/controller/V2ModuleController.kt index 631776053a..542fb40060 100644 --- a/moove/api/src/main/kotlin/io/charlescd/moove/api/controller/V2ModuleController.kt +++ b/moove/api/src/main/kotlin/io/charlescd/moove/api/controller/V2ModuleController.kt @@ -84,7 +84,7 @@ class V2ModuleController( fun findAllModules( @RequestHeader("x-workspace-id") workspaceId: String, @RequestParam("name", required = false) name: String?, - @Valid pageRequest: PageRequest + pageRequest: PageRequest ): ResourcePageResponse { return this.findAllModulesInteractor.execute(workspaceId, name, pageRequest) } From ffeacb4543a45e9bf8daf2eb20eb64f04105b379 Mon Sep 17 00:00:00 2001 From: Douglas Fernandes Date: Fri, 5 Feb 2021 13:50:54 -0300 Subject: [PATCH 11/13] Improvements --- ui/src/modules/Groups/Menu/index.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ui/src/modules/Groups/Menu/index.tsx b/ui/src/modules/Groups/Menu/index.tsx index c1acb8db94..7e274da6e1 100644 --- a/ui/src/modules/Groups/Menu/index.tsx +++ b/ui/src/modules/Groups/Menu/index.tsx @@ -25,8 +25,9 @@ import Loader from './Loaders'; import Styled from './styled'; import { isActiveById } from '../helpers'; import { useFindAllUserGroup } from '../hooks'; -import { useGlobalState } from 'core/state/hooks'; +import { useDispatch, useGlobalState } from 'core/state/hooks'; import { UserGroupPaginationItem } from '../interfaces/UserGroupsPagination'; +import { resetUserGroupsAction } from '../state/actions'; interface Props { onCreate: () => void; @@ -34,20 +35,22 @@ interface Props { } const UserGroupMenu = ({ onCreate, onSelect }: Props) => { + const dispatch = useDispatch(); const [name, setName] = useState(''); const [getUserGroups, loading] = useFindAllUserGroup(); const { list } = useGlobalState(({ userGroups }) => userGroups); const loadByPage = useCallback( - (page: number) => { + (page: number, name?: string) => { getUserGroups(name, page); }, - [name, getUserGroups] + [getUserGroups] ); useEffect(() => { + dispatch(resetUserGroupsAction()); loadByPage(0); - }, [loadByPage]); + }, [dispatch, loadByPage]); const renderItem = ({ id, name }: UserGroupPaginationItem) => ( Date: Fri, 5 Feb 2021 15:32:11 -0300 Subject: [PATCH 12/13] Improvements --- .../Groups/Menu/__tests__/Menu.spec.tsx | 5 ++- ui/src/modules/Groups/Menu/index.tsx | 36 +++++++++---------- ui/src/modules/Groups/Menu/styled.ts | 10 +----- .../__tests__/GroupsComponents.spec.tsx | 2 +- 4 files changed, 21 insertions(+), 32 deletions(-) diff --git a/ui/src/modules/Groups/Menu/__tests__/Menu.spec.tsx b/ui/src/modules/Groups/Menu/__tests__/Menu.spec.tsx index c4cd6bcd00..5d86d42913 100644 --- a/ui/src/modules/Groups/Menu/__tests__/Menu.spec.tsx +++ b/ui/src/modules/Groups/Menu/__tests__/Menu.spec.tsx @@ -15,8 +15,7 @@ */ import React from 'react'; -import { render, screen, waitFor } from 'unit-test/testUtils'; -import { UserGroupItem } from './fixtures'; +import { render, screen } from 'unit-test/testUtils'; import * as StateHooks from 'core/state/hooks'; import Menu from '../index'; @@ -28,7 +27,7 @@ test('render Menu user groups default', async () => { /> ); - const menu = await screen.findByTestId('user-groups-menu'); + const menu = await screen.findByTestId('user-groups-action'); const emptyItems = await screen.findByText('No User group was found'); expect(menu).toBeInTheDocument(); diff --git a/ui/src/modules/Groups/Menu/index.tsx b/ui/src/modules/Groups/Menu/index.tsx index 7e274da6e1..42b7ad08f7 100644 --- a/ui/src/modules/Groups/Menu/index.tsx +++ b/ui/src/modules/Groups/Menu/index.tsx @@ -21,7 +21,6 @@ import Text from 'core/components/Text'; import LabeledIcon from 'core/components/LabeledIcon'; import InfiniteScroll from 'core/components/InfiniteScroll'; import MenuItem from './MenuItem'; -import Loader from './Loaders'; import Styled from './styled'; import { isActiveById } from '../helpers'; import { useFindAllUserGroup } from '../hooks'; @@ -39,12 +38,13 @@ const UserGroupMenu = ({ onCreate, onSelect }: Props) => { const [name, setName] = useState(''); const [getUserGroups, loading] = useFindAllUserGroup(); const { list } = useGlobalState(({ userGroups }) => userGroups); + const isRenderEmpty = isEmpty(list.content) && !loading; const loadByPage = useCallback( - (page: number, name?: string) => { + (page: number) => { getUserGroups(name, page); }, - [getUserGroups] + [getUserGroups, name] ); useEffect(() => { @@ -62,40 +62,38 @@ const UserGroupMenu = ({ onCreate, onSelect }: Props) => { /> ); - const renderList = () => ( + const renderEmpty = () => ( + + No User group was found + + ); + + const renderList = (data: UserGroupPaginationItem[]) => + map(data, item => renderItem(item)) + + const renderContent = () => ( } > - {map(list?.content, item => renderItem(item))} + {isRenderEmpty ? renderEmpty() : renderList(list.content)} ); - const renderEmpty = () => ( - - No User group was found - - ); - - const renderContent = () => - isEmpty(list?.content) ? renderEmpty() : renderList(); - return ( - + Create user group - + - - {loading ? : renderContent()} - + {renderContent()} ); diff --git a/ui/src/modules/Groups/Menu/styled.ts b/ui/src/modules/Groups/Menu/styled.ts index 4486334373..d9f6d57e50 100644 --- a/ui/src/modules/Groups/Menu/styled.ts +++ b/ui/src/modules/Groups/Menu/styled.ts @@ -29,12 +29,6 @@ const SearchInput = styled(SearchInputComponent)` padding: 0 16px; `; -const List = styled.div` - display: flex; - flex-direction: column; - margin: 0; -`; - const ListItem = styled(LabeledIcon)` padding: 15px 0; cursor: pointer; @@ -42,8 +36,7 @@ const ListItem = styled(LabeledIcon)` `; const Content = styled.div` - height: calc(100vh - 200px); - overflow-y: auto; + height: calc(100vh - 250px); `; const Actions = styled.div` @@ -107,7 +100,6 @@ const Empty = styled.div` export default { SearchInput, - List, ListItem, Content, Actions, diff --git a/ui/src/modules/Groups/__tests__/GroupsComponents.spec.tsx b/ui/src/modules/Groups/__tests__/GroupsComponents.spec.tsx index d75bbe1d89..adc49ea1af 100644 --- a/ui/src/modules/Groups/__tests__/GroupsComponents.spec.tsx +++ b/ui/src/modules/Groups/__tests__/GroupsComponents.spec.tsx @@ -28,7 +28,7 @@ test('render groups', async () => { render(); - const UserGroupMenu = await screen.findByTestId('user-group-menu'); + const UserGroupMenu = await screen.findByTestId('user-groups-menu'); expect(UserGroupMenu).toBeInTheDocument(); }); From 0bb25dd56cdd7de8a9c405a52aad178cdfc6fd1b Mon Sep 17 00:00:00 2001 From: Douglas Fernandes Date: Fri, 5 Feb 2021 17:49:38 -0300 Subject: [PATCH 13/13] Improvements --- ui/src/modules/Groups/Menu/index.tsx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/ui/src/modules/Groups/Menu/index.tsx b/ui/src/modules/Groups/Menu/index.tsx index 42b7ad08f7..f55aac4e5c 100644 --- a/ui/src/modules/Groups/Menu/index.tsx +++ b/ui/src/modules/Groups/Menu/index.tsx @@ -20,11 +20,11 @@ import isEmpty from 'lodash/isEmpty'; import Text from 'core/components/Text'; import LabeledIcon from 'core/components/LabeledIcon'; import InfiniteScroll from 'core/components/InfiniteScroll'; +import { useDispatch, useGlobalState } from 'core/state/hooks'; import MenuItem from './MenuItem'; import Styled from './styled'; import { isActiveById } from '../helpers'; import { useFindAllUserGroup } from '../hooks'; -import { useDispatch, useGlobalState } from 'core/state/hooks'; import { UserGroupPaginationItem } from '../interfaces/UserGroupsPagination'; import { resetUserGroupsAction } from '../state/actions'; @@ -40,17 +40,19 @@ const UserGroupMenu = ({ onCreate, onSelect }: Props) => { const { list } = useGlobalState(({ userGroups }) => userGroups); const isRenderEmpty = isEmpty(list.content) && !loading; - const loadByPage = useCallback( - (page: number) => { - getUserGroups(name, page); - }, - [getUserGroups, name] - ); + const onChange = useCallback(() => { + const page = 0; + dispatch(resetUserGroupsAction()); + getUserGroups(name, page); + }, [dispatch, getUserGroups, name]); useEffect(() => { - dispatch(resetUserGroupsAction()); - loadByPage(0); - }, [dispatch, loadByPage]); + onChange(); + }, [name, onChange]); + + const loadMore = (page: number) => { + getUserGroups(name, page); + }; const renderItem = ({ id, name }: UserGroupPaginationItem) => ( { const renderContent = () => ( } >