Skip to content

Commit

Permalink
CLD-411|add admin dev management and delete developer feature (#167)
Browse files Browse the repository at this point in the history
* CLD-411|add admin dev management and delete developer feature

* CLD-411|update unit test

* CLD-411|update missing test
  • Loading branch information
vinhnhq authored Nov 29, 2019
1 parent 5af0b7d commit 9ee8947
Show file tree
Hide file tree
Showing 32 changed files with 4,763 additions and 7 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"react-slick": "^0.24.0",
"redux": "^4.0.4",
"redux-saga": "^1.1.3",
"swagger-ui-react": "^3.23.3"
"swagger-ui-react": "^3.24.3"
},
"devDependencies": {
"@redux-saga/testing-utils": "^1.0.5",
Expand Down
25 changes: 25 additions & 0 deletions src/actions/__tests__/admin-dev-management.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {
adminDevManagementRequestData,
adminDevManagementRequestDataFailure,
adminDevManagementLoading,
adminDevManagementReceiveData
} from '../admin-dev-management'
import ActionTypes from '../../constants/action-types'

describe('admin dev management actions', () => {
it('should create a adminDevManagementRequestData action', () => {
expect(adminDevManagementRequestData.type).toEqual(ActionTypes.ADMIN_DEV_MANAGEMENT_REQUEST_DATA)
})

it('should create a adminDevManagementRequestDataFailure action', () => {
expect(adminDevManagementRequestDataFailure.type).toEqual(ActionTypes.ADMIN_DEV_MANAGEMENT_REQUEST_FAILURE)
})

it('should create a adminDevManagementLoading action', () => {
expect(adminDevManagementLoading.type).toEqual(ActionTypes.ADMIN_DEV_MANAGEMENT_LOADING)
})

it('should create a adminDevManagementReceiveData action', () => {
expect(adminDevManagementReceiveData.type).toEqual(ActionTypes.ADMIN_DEV_MANAGEMENT_RECEIVE_DATA)
})
})
30 changes: 30 additions & 0 deletions src/actions/__tests__/developer-delete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
developerDeleteRequest,
developerDeleteRequestLoading,
developerDeleteRequestFailure,
developerDeleteRequestSuccess,
developerDeleteSetInitFormState
} from '../developer-delete'
import ActionTypes from '../../constants/action-types'

describe('developer delete actions', () => {
it('should create a appDetailLoading action', () => {
expect(developerDeleteRequestLoading.type).toEqual(ActionTypes.DEVELOPER_DELETE_REQUEST_LOADING)
})

it('should create a developerDeleteRequest action', () => {
expect(developerDeleteRequest.type).toEqual(ActionTypes.DEVELOPER_DELETE_REQUEST)
})

it('should create a developerDeleteRequestFailure action', () => {
expect(developerDeleteRequestFailure.type).toEqual(ActionTypes.DEVELOPER_DELETE_REQUEST_FAILURE)
})

it('should create a developerDeleteRequestSuccess action', () => {
expect(developerDeleteRequestSuccess.type).toEqual(ActionTypes.DEVELOPER_DELETE_REQUEST_SUCCESS)
})

it('should create a developerDeleteSetInitFormState action', () => {
expect(developerDeleteSetInitFormState.type).toEqual(ActionTypes.DEVELOPER_DELETE_SET_INIT_FORM_STATE)
})
})
19 changes: 19 additions & 0 deletions src/actions/admin-dev-management.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { actionCreator } from '../utils/actions'
import ActionTypes from '../constants/action-types'
import { PagedResultDeveloperModel_ } from '../types/marketplace-api-schema'

export interface AdminDevManagementRequestDataValues {
page: number
queryString: string
}

export const adminDevManagementRequestData = actionCreator<AdminDevManagementRequestDataValues>(
ActionTypes.ADMIN_DEV_MANAGEMENT_REQUEST_DATA
)
export const adminDevManagementRequestDataFailure = actionCreator<void>(
ActionTypes.ADMIN_DEV_MANAGEMENT_REQUEST_FAILURE
)
export const adminDevManagementLoading = actionCreator<boolean>(ActionTypes.ADMIN_DEV_MANAGEMENT_LOADING)
export const adminDevManagementReceiveData = actionCreator<PagedResultDeveloperModel_ | undefined>(
ActionTypes.ADMIN_DEV_MANAGEMENT_RECEIVE_DATA
)
8 changes: 8 additions & 0 deletions src/actions/developer-delete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { actionCreator } from './../utils/actions'
import ActionTypes from '../constants/action-types'

export const developerDeleteRequest = actionCreator<string>(ActionTypes.DEVELOPER_DELETE_REQUEST)
export const developerDeleteRequestLoading = actionCreator<void>(ActionTypes.DEVELOPER_DELETE_REQUEST_LOADING)
export const developerDeleteRequestFailure = actionCreator<void>(ActionTypes.DEVELOPER_DELETE_REQUEST_FAILURE)
export const developerDeleteRequestSuccess = actionCreator<void>(ActionTypes.DEVELOPER_DELETE_REQUEST_SUCCESS)
export const developerDeleteSetInitFormState = actionCreator<void>(ActionTypes.DEVELOPER_DELETE_SET_INIT_FORM_STATE)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AdminDevManagement should match a snapshot when LOADING false 1`] = `<Loader />`;
54 changes: 54 additions & 0 deletions src/components/pages/__tests__/admin-dev-management.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as React from 'react'
import { shallow } from 'enzyme'
import toJson from 'enzyme-to-json'
import {
AdminDevManagement,
AdminDevManagementProps,
onPageChangeHandler,
onSearchHandler
} from '../admin-dev-management'
import { AdminDevManamgenetState } from '@/reducers/admin-dev-management'
import { AdminDevManagementFilterFormValues } from '@/components/ui/admin-dev-management-filter-form'
import { match } from 'react-router'
import { getMockRouterProps } from '@/utils/mock-helper'

describe('AdminDevManagement', () => {
it('should match a snapshot when LOADING false', () => {
const props: AdminDevManagementProps = {
adminDevManagementState: { loading: false, data: undefined } as AdminDevManamgenetState,
filterValues: {} as AdminDevManagementFilterFormValues,
onPageChange: jest.fn(),
onSearch: jest.fn()
}

expect(toJson(shallow(<AdminDevManagement {...props} />))).toMatchSnapshot()
})
})

const mockRouterProps = getMockRouterProps({ page: 2 })

describe('onPageChangeHandler', () => {
it('should return a function when executing', () => {
const onPageChangeHandlerFn = onPageChangeHandler(mockRouterProps.history, {
name: '',
company: ''
} as AdminDevManagementFilterFormValues)
expect(onPageChangeHandlerFn).toBeDefined()

onPageChangeHandlerFn(2)
expect(mockRouterProps.history.push).toBeCalled()
})
})

describe('onSearchHandler', () => {
it('should return a function when executing', () => {
const onSearchHandlerFn = onSearchHandler(mockRouterProps.history, mockRouterProps.match)
expect(onSearchHandlerFn).toBeDefined()

onSearchHandlerFn({
name: '',
company: ''
} as AdminDevManagementFilterFormValues)
expect(mockRouterProps.history.push).toBeCalled()
})
})
156 changes: 156 additions & 0 deletions src/components/pages/admin-dev-management.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import * as React from 'react'
import { History } from 'history'
import { connect } from 'react-redux'
import { withRouter, RouteComponentProps, match } from 'react-router'
import { ReduxState } from '@/types/core'
import { REVISIONS_PER_PAGE } from '@/constants/paginator'
import { AdminDevManamgenetState } from '@/reducers/admin-dev-management'
import ErrorBoundary from '@/components/hocs/error-boundary'
import {
Pagination,
Table,
Info,
FlexContainerResponsive,
Button,
Loader,
Section,
setQueryParams
} from '@reapit/elements'
import Routes from '@/constants/routes'
import AdminDevManagementFilterForm, {
AdminDevManagementFilterFormValues
} from '@/components/ui/admin-dev-management-filter-form'
import AdminDeleteDeveloperModal from '@/components/ui/developer-delete'
import { DeveloperModel } from '@/types/marketplace-api-schema'

export interface AdminDevManagementProps {
adminDevManagementState: AdminDevManamgenetState
filterValues: AdminDevManagementFilterFormValues
onPageChange: any
onSearch: any
}

export const AdminDevManagement: React.FC<AdminDevManagementProps> = ({
adminDevManagementState,
filterValues,
onPageChange,
onSearch
}) => {
const [isDeleteModalOpen, setIsDeleteModalOpen] = React.useState(false)
const [developerId, setDeveloperId] = React.useState('')
const [developerName, setDeveloperName] = React.useState('')

const resetModal = () => {
setIsDeleteModalOpen(false)
setDeveloperId('')
setDeveloperName('')
}

const { loading, data } = adminDevManagementState
const pageNumber = data?.pageNumber || 1

const columns = [
{
Header: '#',
id: 'id',
Cell: ({ row: { index } }) => <>{(pageNumber - 1) * REVISIONS_PER_PAGE + index + 1}</>
},
{ Header: 'Name', accessor: 'name' },
{ Header: 'Company', accessor: 'company' },
{ Header: 'Job Title', accessor: 'jobTitle' },
{ Header: 'Email', accessor: 'email' },
{ Header: 'Phone', accessor: 'telephone' },
{
Header: '',
id: 'buttonColumn',
Cell: ({ row: { original } }) => {
const { id, name } = original as DeveloperModel

return (
<Button
type="button"
variant="primary"
onClick={() => {
if (id && name) {
setDeveloperId(id)
setDeveloperName(name)
setIsDeleteModalOpen(true)
}
}}
>
Delete
</Button>
)
}
}
]

if (loading || !data) {
return <Loader />
}

if (!loading && data?.data?.length === 0) {
return <Info infoType="" />
}

return (
<ErrorBoundary>
<FlexContainerResponsive>
<Section>
<AdminDevManagementFilterForm filterValues={filterValues} onSearch={onSearch} />
<Table loading={false} data={data.data} columns={columns} />
<Pagination
onChange={onPageChange}
totalCount={data.totalCount}
pageSize={data.pageSize}
pageNumber={data.pageNumber}
/>
</Section>
</FlexContainerResponsive>

<AdminDeleteDeveloperModal
visible={isDeleteModalOpen}
afterClose={resetModal}
onDeleteSuccess={resetModal}
developerId={developerId}
developerName={developerName}
/>
</ErrorBoundary>
)
}

export const onPageChangeHandler = (history: History<any>, queryParams: AdminDevManagementFilterFormValues) => (
page: number
) => {
const query = setQueryParams(queryParams) ? `?${setQueryParams(queryParams)}` : ''

return history.push(`${Routes.ADMIN_DEV_MANAGEMENT}/${page}${query}`)
}

export const onSearchHandler = (history: History<any>, match: match<{ page?: any }>) => (
queryParams: AdminDevManagementFilterFormValues
) => {
const page = match.params.page || 1
const query = setQueryParams(queryParams) ? `?${setQueryParams(queryParams)}` : ''

return history.push(`${Routes.ADMIN_DEV_MANAGEMENT}/${page}${query}`)
}

export const mapStateToProps = (state: ReduxState, ownState: RouteComponentProps<any>) => {
const { history, match } = ownState
const queryParams = new URLSearchParams(ownState.location.search)
const name = queryParams.get('name') || ''
const company = queryParams.get('company') || ''
const filterValues = { name, company } as AdminDevManagementFilterFormValues

return {
adminDevManagementState: state.adminDevManagement,
filterValues,
onPageChange: onPageChangeHandler(history, filterValues),
onSearch: onSearchHandler(history, match)
}
}

export const mapDispatchToProps = () => ({})

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(AdminDevManagement))
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AdminDevManagementFilterForm should match a snapshot 1`] = `
<FlexContainerBasic
className="pb-4"
flexColumn={true}
>
<FlexContainerResponsive
flexColumn={true}
hasBackground={true}
hasPadding={true}
>
<Formik
enableReinitialize={false}
initialValues={
Object {
"company": "company",
"name": "name",
}
}
isInitialValid={false}
onSubmit={[Function]}
render={[Function]}
validateOnBlur={true}
validateOnChange={true}
/>
</FlexContainerResponsive>
</FlexContainerBasic>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`DeveloperDeleteModal should match snapshot 1`] = `
<Modal
afterClose={[Function]}
renderChildren={true}
visible={true}
>
<ModalHeader
afterClose={[Function]}
title="Confirm deletion"
/>
<ModalBody
body={
<SubTitleH6
isCentered={true}
>
Are you sure you want to delete '
'?
</SubTitleH6>
}
/>
<ModalFooter
footerItems={
<React.Fragment>
<Button
loading={false}
onClick={[Function]}
type="button"
variant="danger"
>
Confirm
</Button>
<Button
disabled={false}
onClick={[Function]}
type="button"
variant="secondary"
>
Cancel
</Button>
</React.Fragment>
}
/>
</Modal>
`;
Loading

0 comments on commit 9ee8947

Please sign in to comment.