Skip to content

Commit

Permalink
[##165785921] implement feature to enable super user view office bloc…
Browse files Browse the repository at this point in the history
…ks in different centres (#243)

* [##165785921] implement a feature to enable superuser view office blocks in different locations
- add dropdown component
- add action to fetch office blocks in a particular center
- add action test
- implement feedback on dropdown styling
[finishes ##165785921]
  • Loading branch information
OnyekachiSamuel authored Jun 19, 2019
1 parent 10c1966 commit 366a69b
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 4 deletions.
13 changes: 12 additions & 1 deletion src/__test__/actions/officeLocations.actions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import axios from 'axios';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

import { loadOfficeLocations, loadOfficeBlocks, createOfficeBlock } from '../../_actions/officeLocations.actions';
import { loadOfficeLocations, loadOfficeBlocks, createOfficeBlock, loadCentreOfficeBlocks } from '../../_actions/officeLocations.actions';

import officeLocations from '../../_mock/officeLocations';
import officeBlocks from '../../_mock/officeBlocks';

import constants from '../../_constants';

Expand Down Expand Up @@ -73,6 +74,16 @@ describe('Centres Action tests', () => {
});
});

it('should dispatch LOAD_OFFICE_BLOCK_SUCCESS when loadCentreOfficeBlocks is called successfully', () => {
mock.onGet().reply(200, officeBlocks.results);
return store.dispatch(loadCentreOfficeBlocks(2)).then(() => {
expect(store.getActions()).toContainEqual({
payload: officeBlocks.results,
type: LOAD_OFFICE_BLOCK_SUCCESS
});
});
});

it('should dispatch LOAD_OFFICE_BLOCK_FAILURE when loadOfficeBlocks is unsuccessful', () => {
mock.onGet('office-blocks/?page=1&page_size=10').reply(400, 'Could not office blocks');
return store.dispatch(loadOfficeBlocks(1, 10)).then(() => {
Expand Down
39 changes: 39 additions & 0 deletions src/__test__/components/OfficeBlocksComponent.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ describe('Renders <OfficeBlocksComponent /> correctly', () => {
const props = {
isLoading: false,
blockCount: 2,
locationList: [{ name: 'Lagos', id: 23 }, { name: 'Nairobi', id: 45 }],
loadOfficeBlocks: jest.fn(),
loadOfficeLocations: jest.fn(),
loadCentreOfficeBlocks: jest.fn(),
loadCountries: jest.fn(),
resetMessage: jest.fn()
};
Expand All @@ -36,6 +38,43 @@ describe('Renders <OfficeBlocksComponent /> correctly', () => {
expect(handlePaginationChangeSpy.mock.calls.length).toEqual(1);
});

it('calls handleToggleModal when the modal is toggled', () => {
const handleToggleModalSpy = jest.spyOn(wrapper.instance(), 'handleToggleModal');

wrapper.setState({ modalOpen: true });

const event = {};
const data = {};

wrapper.instance().handleToggleModal(event, data);
expect(handleToggleModalSpy.mock.calls.length).toEqual(1);
expect(wrapper.state('modalOpen')).toEqual(false);
});

it('calls handleEditToggleModal when modal is clicked', () => {
const handleEditToggleModalSpy = jest.spyOn(wrapper.instance(), 'handleEditToggleModal');

wrapper.setState({ modalOpen: true });

const event = {};
const data = {};

wrapper.instance().handleEditToggleModal(event, data);
expect(handleEditToggleModalSpy.mock.calls.length).toEqual(1);
expect(wrapper.state('modalOpen')).toEqual(true);
});


it('calls handleDropdownChange the dropdown item is selected', () => {
const handleDropdownChangeSpy = jest.spyOn(wrapper.instance(), 'handleDropdownChange');

const event = {};
const data = {};

wrapper.instance().handleDropdownChange(event, data);
expect(handleDropdownChangeSpy.mock.calls.length).toEqual(1);
});

it('calls the getTotalPages function when the next button is clicked', () => {
const getTotalPagesSpy = jest.spyOn(wrapper.instance(), 'getTotalPages');
wrapper.instance().getTotalPages();
Expand Down
8 changes: 8 additions & 0 deletions src/_actions/officeLocations.actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ export const loadOfficeBlocks = (pageNumber, limit) => (dispatch) => {
});
};

export const loadCentreOfficeBlocks = centreId => (dispatch) => {
dispatch({ type: LOAD_OFFICE_BLOCK_REQUEST });
return axios
.get(`andela-centres/${centreId}/office_blocks/`)
.then(response => dispatch(loadOfficeBlocksSuccess(response.data)))
.catch(error => dispatch(loadOfficeBlocksFailure(error)));
};

export const loadOfficeBlocksSuccess = blocks => ({
type: LOAD_OFFICE_BLOCK_SUCCESS,
payload: blocks
Expand Down
6 changes: 4 additions & 2 deletions src/_components/OfficeBlocks/OfficeBlocksContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { connect } from 'react-redux';
import {
loadOfficeBlocks,
resetMessage,
loadOfficeLocations
loadOfficeLocations,
loadCentreOfficeBlocks
} from '../../_actions/officeLocations.actions';
import OfficeBlocksComponent from '../../components/OfficeBlocks/OfficeBlocksComponent';

Expand Down Expand Up @@ -32,5 +33,6 @@ export const mapStateToProps = ({ officeLocations }) => {
export default connect(mapStateToProps, {
loadOfficeBlocks,
resetMessage,
loadOfficeLocations
loadOfficeLocations,
loadCentreOfficeBlocks
})(OfficeBlocksComponent);
7 changes: 7 additions & 0 deletions src/_css/officeBlocksComponent.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.center-filter {
.ui.fluid.dropdown {
margin-top: 0;
height: 100%;
width: 160px;
}
}
17 changes: 17 additions & 0 deletions src/_mock/officeBlocks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default {
count: 2,
next: null,
previous: null,
results: [
{
id: 4,
name: 'Epic Tower',
location: 'Lagos'
},
{
id: 5,
name: 'Dojo',
location: 'Nairobi'
}
]
};
34 changes: 33 additions & 1 deletion src/components/OfficeBlocks/OfficeBlocksComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { isEmpty } from 'lodash';

import { Dropdown } from 'semantic-ui-react';
import NavBarComponent from '../../_components/NavBarContainer';
import LoaderComponent from '../../components/LoaderComponent';
import Cards from '../common/Card/Card';
Expand All @@ -10,6 +11,9 @@ import Paginator from '../common/PaginationComponent';
import StatusMessageComponent from '../common/StatusComponent';
import PageHeader from '../common/PageHeader';
import OfficeBlocksModal from '../../_components/OfficeBlocks/OfficeBlocksModal';
import verifySuperAdmin from '../../_utils/verifySuperAdmin';

import '../../_css/officeBlocksComponent.scss';

class OfficeBlocksComponent extends React.Component {
state = {
Expand Down Expand Up @@ -48,14 +52,27 @@ class OfficeBlocksComponent extends React.Component {
this.props.resetMessage();
};

handleDropdownChange = (e, data) => {
this.props.loadCentreOfficeBlocks(data.value);
};

getTotalPages = () => Math.ceil(this.props.blockCount / this.state.limit);

render() {
const { isLoading, blockList, error, resetMessage, entity } = this.props;
const { isLoading, blockList, error, resetMessage, entity, locationList } = this.props;
const hasLocations = !isEmpty(blockList);
const showStatus = error;
const showAction = entity === 'office-blocks';
const showNotFound = !isLoading && !hasLocations && !showStatus;
const options = [{ key: -1, text: 'Select Center', value: 0 }];
locationList.forEach((location, index) => {
const locObj = {
key: index,
text: location.name,
value: location.id
};
options.push(locObj);
});

return (
<NavBarComponent>
Expand All @@ -69,6 +86,19 @@ class OfficeBlocksComponent extends React.Component {
onToggle={this.handleToggleModal}
open={this.state.modalOpen}
/>
{
verifySuperAdmin() && (
<div className="center-filter">
<Dropdown
placeholder="Select Center"
fluid
selection
options={options}
onChange={this.handleDropdownChange}
/>
</div>
)
}
</div>
</PageHeader>

Expand Down Expand Up @@ -128,8 +158,10 @@ OfficeBlocksComponent.propTypes = {
resetMessage: PropTypes.func,
blockCount: PropTypes.number,
blockList: PropTypes.array,
locationList: PropTypes.array,
error: PropTypes.string,
loadOfficeLocations: PropTypes.func,
loadCentreOfficeBlocks: PropTypes.func,
entity: PropTypes.string
};

Expand Down

0 comments on commit 366a69b

Please sign in to comment.