From 0cd80b6ef65ed4d60b33cb653204019a57472b43 Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 13 Jan 2021 22:09:16 -0800 Subject: [PATCH 01/13] WIP: bulk submit cont [gh-1132] --- api/controller/contributions.ts | 1 + api/routes/index.ts | 47 ++++++++++++++ .../ContributionsTable/ContributionsTable.js | 63 +++++++++++++++---- .../Utils/ContributionsFields.js | 3 - app/src/api/api.js | 6 ++ .../ContributorMatchPicker/index.js | 1 + .../Forms/ContributionReady/index.js | 1 + app/src/components/Table/index.js | 1 + app/src/state/ducks/contributions.js | 2 + 9 files changed, 111 insertions(+), 14 deletions(-) diff --git a/api/controller/contributions.ts b/api/controller/contributions.ts index 1d4aeb75f..bb200e4e5 100644 --- a/api/controller/contributions.ts +++ b/api/controller/contributions.ts @@ -175,6 +175,7 @@ export class UpdateContributionDto implements IUpdateContributionAttrs { export async function updateContribution(request: IRequest, response: Response, next: Function) { try { + console.log(response); checkCurrentUser(request); const updateContributionDto = Object.assign(new UpdateContributionDto(), { ...request.body, diff --git a/api/routes/index.ts b/api/routes/index.ts index 2567fb93c..07f627c16 100644 --- a/api/routes/index.ts +++ b/api/routes/index.ts @@ -519,6 +519,53 @@ export const AppRoutes = [ action: contributions.updateContribution }, + /** + * @swagger + * /bulk-update-contributions: + * put: + * summary: Bulk update contributions + * tags: + * - Contributions + * security: + * - cookieAuth: [] + * produces: + * - application/json + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: array + * items: + * type: object + * properties: + * currentUserId: + * type: integer + * id: + * type: integer + * status: + * type: string + * responses: + * 200: + * description: Success response (X of X updated, X invalid) + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * 422: + * $ref: '#/components/responses/UnprocessableEntity' + * + */ + // TODO: verify swagger is correct + { + path: '/contributions/:id', + method: 'put', + action: contributions.updateContribution + }, + /** * @swagger * /contributions/{id}: diff --git a/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js b/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js index 7de7912da..3aab5c043 100644 --- a/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js +++ b/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js @@ -41,7 +41,7 @@ const buttonWrapper = css` const actionInfo = (name, buttonType, onClick, isFreeAction = undefined) => isFreeAction ? { icon: 'none', name, buttonType, onClick, isFreeAction } - : { icon: 'none', name, buttonType, onClick }; + : { icon: 'none', name, buttonType, onClick, position: 'row' }; const columns = isGovAdmin => { const cols = [ @@ -118,11 +118,27 @@ const columns = isGovAdmin => { class ContributionsTable extends React.Component { constructor(props) { super(props); + this.state = { + itemsToSubmit: null, + }; props.getContributions({ governmentId: props.govId, currentUserId: props.userId, campaignId: props.campaignId, }); + this.updateItemsToSubmit = this.updateItemsToSubmit.bind(this); + } + + updateItemsToSubmit(items) { + if (items.length > 0) { + this.setState({ + itemsToSubmit: items, + }); + } else { + this.setState({ + itemsToSubmit: null, + }); + } } render() { @@ -144,9 +160,14 @@ class ContributionsTable extends React.Component { const isLoading = isListLoading && !Array.isArray(contributionList); const actions = [ - actionInfo('View', 'submit', (event, rowData) => { - history.push(`/contributions/${rowData.id}`); - }), + actionInfo( + 'View', + 'submit', + (event, rowData) => { + history.push(`/contributions/${rowData.id}`); + }, + false + ), ]; const components = { @@ -253,6 +274,14 @@ class ContributionsTable extends React.Component { options={{ pageSize: filterOptions.perPage || 50, showTitle: false, + actionsColumnIndex: -1, + selection: true, + selectionProps: rowData => { + return { + disabled: rowData.status === 'Submitted', + color: 'primary', + }; + }, }} actions={actions} components={components} @@ -275,18 +304,30 @@ class ContributionsTable extends React.Component { pageNumber={filterOptions.page || 0} totalRows={total} onChangePage={handleOnChangePage} - // eslint-disable-next-line no-use-before-define onChangeRowsPerPage={handleOnRowsPerPageChange} toolbarAction={ !isGovAdmin ? ( - + <> + + {this.state.itemsToSubmit && ( + + )} + ) : null } + onSelectionChange={items => this.updateItemsToSubmit(items)} /> ); diff --git a/app/src/Pages/Portal/Contributions/Utils/ContributionsFields.js b/app/src/Pages/Portal/Contributions/Utils/ContributionsFields.js index 99bf31db2..09e76db6d 100644 --- a/app/src/Pages/Portal/Contributions/Utils/ContributionsFields.js +++ b/app/src/Pages/Portal/Contributions/Utils/ContributionsFields.js @@ -530,9 +530,6 @@ export const validate = values => { checkNumber, occupation, occupationLetterDate, - employerName, - employerCity, - employerState, subTypeOfContribution, inKindType, lastName, diff --git a/app/src/api/api.js b/app/src/api/api.js index 5415c5ad4..dd5c32e18 100644 --- a/app/src/api/api.js +++ b/app/src/api/api.js @@ -603,6 +603,12 @@ export function updateContribution(contributionAttrs) { ); } +// path: '/bulk-update-contributions' +// method: 'put', +export function bulkUpdateContribution(contributionAttrs) { + return put(`${baseUrl()}/bulk-update-contributions`, contributionAttrs); +} + // path: '/contributions/new', // method: 'post', export function createContribution(contributionAttrs) { diff --git a/app/src/components/ContributorMatchPicker/index.js b/app/src/components/ContributorMatchPicker/index.js index 993f715e0..03099d91d 100644 --- a/app/src/components/ContributorMatchPicker/index.js +++ b/app/src/components/ContributorMatchPicker/index.js @@ -139,6 +139,7 @@ class contributorMatchPicker extends React.Component { } handleSubmit() { + // TODO: does this need to update this? this.props.updateMatchForContribution({ contributionId: this.props.contributionId, matchId: this.state.pages[this.state.currentPage].id, diff --git a/app/src/components/Forms/ContributionReady/index.js b/app/src/components/Forms/ContributionReady/index.js index 5ddf0c60f..1fd9234a3 100644 --- a/app/src/components/Forms/ContributionReady/index.js +++ b/app/src/components/Forms/ContributionReady/index.js @@ -148,6 +148,7 @@ class ContributionReadyForm extends React.Component { ) : ( <> +

nice

diff --git a/app/src/state/ducks/contributions.js b/app/src/state/ducks/contributions.js index 872bed9ba..6a48a8f9f 100644 --- a/app/src/state/ducks/contributions.js +++ b/app/src/state/ducks/contributions.js @@ -268,10 +268,12 @@ export function createContribution(contributionAttrs) { } export function updateContribution(contributionAttrs) { + // TODO: duplicate for bulk submission return async (dispatch, getState, { api, schema }) => { dispatch(actionCreators.updateContribution.request()); try { const response = await api.updateContribution(contributionAttrs); + console.log({ contributionAttrs, response }); if (response.status === 204) { let status = ''; if (contributionAttrs.status) { From 3d7d23fb6c768639421ab5ba99b182960e667043 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 15 Jan 2021 01:22:16 -0800 Subject: [PATCH 02/13] update frontend and backend with bulk submit --- api/controller/contributions.ts | 33 +++++++++++++- api/routes/index.ts | 4 +- .../ContributionsTable/ContributionsTable.js | 7 ++- app/src/api/api.js | 3 +- .../Forms/ContributionReady/index.js | 1 - app/src/components/Table/index.js | 1 - app/src/state/ducks/contributions.js | 45 ++++++++++++++++++- 7 files changed, 86 insertions(+), 8 deletions(-) diff --git a/api/controller/contributions.ts b/api/controller/contributions.ts index bb200e4e5..61cebe6b1 100644 --- a/api/controller/contributions.ts +++ b/api/controller/contributions.ts @@ -17,6 +17,7 @@ import { checkCurrentUser, IRequest } from '../routes/helpers'; import { Response } from 'express'; import { checkDto } from './helpers'; import { + Contribution, ContributionStatus, ContributionSubType, ContributionType, @@ -175,7 +176,6 @@ export class UpdateContributionDto implements IUpdateContributionAttrs { export async function updateContribution(request: IRequest, response: Response, next: Function) { try { - console.log(response); checkCurrentUser(request); const updateContributionDto = Object.assign(new UpdateContributionDto(), { ...request.body, @@ -192,6 +192,37 @@ export async function updateContribution(request: IRequest, response: Response, } } +export async function bulkUpdateContributions(request: IRequest, response: Response, next: Function) { + try { + console.log(request.body); + checkCurrentUser(request); + if (request.body.ids && request.body.ids.length > 0) { + const promises = request.body.ids.map(async (id: string) => { + const updatedContribution = request.body; + delete updatedContribution.ids; + const updateContributionDto = Object.assign(new UpdateContributionDto(), { + ...updatedContribution, + currentUserId: request.currentUser.id, + id + }); + await checkDto(updateContributionDto); + return await updateContributionAsync(updateContributionDto); + }); + const contributions = await Promise.all(promises); + const completedContributions = contributions.filter(contribution => (contribution as Contribution).status === request.body.status); + console.log(completedContributions, contributions); + return response.status(200).json({ + message: `${completedContributions.length} of ${contributions.length} successfully updated.` + }); + } + } catch (err) { + if (process.env.NODE_ENV === 'production' && err.message !== 'No token set') { + bugsnagClient.notify(err); + } + return response.status(422).json({ message: err.message }); + } +} + export class GetContributionsDto implements IGetContributionAttrs { @IsNumber() governmentId: number; diff --git a/api/routes/index.ts b/api/routes/index.ts index 07f627c16..082b4dab8 100644 --- a/api/routes/index.ts +++ b/api/routes/index.ts @@ -561,9 +561,9 @@ export const AppRoutes = [ */ // TODO: verify swagger is correct { - path: '/contributions/:id', + path: '/bulk-update-contributions', method: 'put', - action: contributions.updateContribution + action: contributions.bulkUpdateContributions }, /** diff --git a/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js b/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js index 3aab5c043..061a15394 100644 --- a/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js +++ b/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js @@ -10,6 +10,7 @@ import FilterContribution from '../../../../components/Forms/FilterContributions import Table from '../../../../components/Table'; import Button from '../../../../components/Button/Button'; import { + bulkUpdateContributions, getContributions, getContributionsList, getFilterOptions, @@ -155,6 +156,7 @@ class ContributionsTable extends React.Component { userId, campaignId, isGovAdmin, + bulkSubmitContributions, } = this.props; const isLoading = isListLoading && !Array.isArray(contributionList); @@ -319,7 +321,9 @@ class ContributionsTable extends React.Component { {this.state.itemsToSubmit && ( @@ -357,6 +361,7 @@ export default connect( showModal: payload => { dispatch(showModal(payload)); }, + bulkSubmitContributions: data => dispatch(bulkUpdateContributions(data)), }; } )(ContributionsTable); diff --git a/app/src/api/api.js b/app/src/api/api.js index dd5c32e18..783671070 100644 --- a/app/src/api/api.js +++ b/app/src/api/api.js @@ -597,6 +597,7 @@ export function updateCampaignNameForGovernment(campaignAttrs) { // path: '/contributions/:id' // method: 'put', export function updateContribution(contributionAttrs) { + console.log(contributionAttrs); return put( `${baseUrl()}/contributions/${contributionAttrs.id}`, contributionAttrs @@ -605,7 +606,7 @@ export function updateContribution(contributionAttrs) { // path: '/bulk-update-contributions' // method: 'put', -export function bulkUpdateContribution(contributionAttrs) { +export function bulkUpdateContributions(contributionAttrs) { return put(`${baseUrl()}/bulk-update-contributions`, contributionAttrs); } diff --git a/app/src/components/Forms/ContributionReady/index.js b/app/src/components/Forms/ContributionReady/index.js index 1fd9234a3..5ddf0c60f 100644 --- a/app/src/components/Forms/ContributionReady/index.js +++ b/app/src/components/Forms/ContributionReady/index.js @@ -148,7 +148,6 @@ class ContributionReadyForm extends React.Component { ) : ( <> -

nice

diff --git a/app/src/state/ducks/contributions.js b/app/src/state/ducks/contributions.js index 6a48a8f9f..fc851801d 100644 --- a/app/src/state/ducks/contributions.js +++ b/app/src/state/ducks/contributions.js @@ -268,7 +268,6 @@ export function createContribution(contributionAttrs) { } export function updateContribution(contributionAttrs) { - // TODO: duplicate for bulk submission return async (dispatch, getState, { api, schema }) => { dispatch(actionCreators.updateContribution.request()); try { @@ -304,6 +303,50 @@ export function updateContribution(contributionAttrs) { }; } +export function bulkUpdateContributions(contributionAttrsArray) { + return async (dispatch, getState, { api, schema }) => { + dispatch(actionCreators.updateContribution.request()); + try { + const state = getState(); + const currentUserId = state.auth.me.id; + const ids = contributionAttrsArray.map(contribution => contribution.id); + const bulkSubmitInfo = { + currentUserId, + ids, + status: 'Submitted', + }; + console.log({ bulkSubmitInfo }); + const response = await api.bulkUpdateContributions(bulkSubmitInfo); + if (response.status === 200) { + const res = await response.json(); + console.log(res, response); + dispatch(actionCreators.updateContribution.success()); + if (res.message) { + dispatch( + flashMessage(`${res.message}`, { + props: { variant: 'success' }, + }) + ); + } + // refetch data + // dispatch(push('/contributions')); + } else { + dispatch(actionCreators.updateContribution.failure()); + const error = await response.json(); + dispatch( + flashMessage(`Error - ${error}`, { props: { variant: 'error' } }) + ); + return error; + } + } catch (error) { + dispatch(actionCreators.updateContribution.failure(error)); + dispatch( + flashMessage(`Error - ${error}`, { props: { variant: 'error' } }) + ); + } + }; +} + export function getContributions(contributionSearchAttrs, applyFilter = false) { return async (dispatch, getState, { api, schema }) => { dispatch(actionCreators.getContributions.request()); From df3e2affaca6d5a8d8ecbf990e587c15644ed5b8 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sat, 16 Jan 2021 15:25:31 -0800 Subject: [PATCH 03/13] add refresh button and frontend test --- api/controller/contributions.ts | 1 - .../ContributionsTable/ContributionsTable.js | 25 +++++++++-- .../ContributorMatchPicker/index.js | 1 - app/src/state/ducks/contributions.js | 2 - app/src/state/ducks/contributions.test.js | 45 +++++++++++++++++++ 5 files changed, 67 insertions(+), 7 deletions(-) diff --git a/api/controller/contributions.ts b/api/controller/contributions.ts index 61cebe6b1..1f89372dc 100644 --- a/api/controller/contributions.ts +++ b/api/controller/contributions.ts @@ -194,7 +194,6 @@ export async function updateContribution(request: IRequest, response: Response, export async function bulkUpdateContributions(request: IRequest, response: Response, next: Function) { try { - console.log(request.body); checkCurrentUser(request); if (request.body.ids && request.body.ids.length > 0) { const promises = request.body.ids.map(async (id: string) => { diff --git a/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js b/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js index 061a15394..74411362a 100644 --- a/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js +++ b/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js @@ -121,6 +121,7 @@ class ContributionsTable extends React.Component { super(props); this.state = { itemsToSubmit: null, + bulkSubmitted: false, }; props.getContributions({ governmentId: props.govId, @@ -321,13 +322,31 @@ class ContributionsTable extends React.Component { {this.state.itemsToSubmit && ( )} + {this.state.bulkSubmitted && ( + + )} ) : null } diff --git a/app/src/components/ContributorMatchPicker/index.js b/app/src/components/ContributorMatchPicker/index.js index 03099d91d..993f715e0 100644 --- a/app/src/components/ContributorMatchPicker/index.js +++ b/app/src/components/ContributorMatchPicker/index.js @@ -139,7 +139,6 @@ class contributorMatchPicker extends React.Component { } handleSubmit() { - // TODO: does this need to update this? this.props.updateMatchForContribution({ contributionId: this.props.contributionId, matchId: this.state.pages[this.state.currentPage].id, diff --git a/app/src/state/ducks/contributions.js b/app/src/state/ducks/contributions.js index fc851801d..1e0940f95 100644 --- a/app/src/state/ducks/contributions.js +++ b/app/src/state/ducks/contributions.js @@ -328,8 +328,6 @@ export function bulkUpdateContributions(contributionAttrsArray) { }) ); } - // refetch data - // dispatch(push('/contributions')); } else { dispatch(actionCreators.updateContribution.failure()); const error = await response.json(); diff --git a/app/src/state/ducks/contributions.test.js b/app/src/state/ducks/contributions.test.js index 3bf9d165a..b36c6abff 100644 --- a/app/src/state/ducks/contributions.test.js +++ b/app/src/state/ducks/contributions.test.js @@ -215,6 +215,51 @@ describe('Side Effects', () => { }); }); + it('bulkUpdateContributions', async () => { + const expectedActions = [ + { type: actionTypes.UPDATE_CONTRIBUTION.REQUEST }, + { type: actionTypes.UPDATE_CONTRIBUTION.SUCCESS }, + ]; + const store = mockStore({}); + + process.env.TOKEN = campaignAdminToken; + + const contribution = await api.createContribution({ + address1: '123 ABC ST', + amount: 250, + campaignId, + city: 'Portland', + currentUserId: campaignAdminId, + date: 1562436237619, + firstName: 'John', + middleInitial: '', + lastName: 'Doe', + governmentId, + type: api.ContributionTypeEnum.CONTRIBUTION, + subType: api.ContributionSubTypeEnum.CASH, + paymentMethod: api.PaymentMethodEnum.CASH, + state: 'OR', + status: api.ContributionStatusEnum.DRAFT, + zip: '97214', + contributorType: api.ContributorTypeEnum.INDIVIDUAL, + }); + const { id } = await contribution.json(); + + return store + .dispatch( + contributions.bulkUpdateContributions({ + ids: [id], + status: 'Submitted', + currentUserId: campaignAdminId, + }) + ) + .then(() => { + const actions = store.getActions(); + expect(actions[0].type).toEqual(expectedActions[0].type); + expect(actions[1].type).toEqual(expectedActions[1].type); + }); + }); + it('gets contributions', async () => { const expectedActions = [ { type: actionTypes.GET_CONTRIBUTIONS.REQUEST }, From ed3c838527c4082c35f808972b57f0d23e22b551 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 17 Jan 2021 12:30:29 -0800 Subject: [PATCH 04/13] fix test --- app/src/state/ducks/contributions.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/state/ducks/contributions.test.js b/app/src/state/ducks/contributions.test.js index b36c6abff..2d17cc2f6 100644 --- a/app/src/state/ducks/contributions.test.js +++ b/app/src/state/ducks/contributions.test.js @@ -247,7 +247,7 @@ describe('Side Effects', () => { return store .dispatch( - contributions.bulkUpdateContributions({ + api.bulkUpdateContributions({ ids: [id], status: 'Submitted', currentUserId: campaignAdminId, From 2fcc88046c0f748d4efa7448f787788458573a3d Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 17 Jan 2021 12:41:33 -0800 Subject: [PATCH 05/13] update test --- app/src/state/ducks/contributions.test.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/app/src/state/ducks/contributions.test.js b/app/src/state/ducks/contributions.test.js index 2d17cc2f6..03c4be433 100644 --- a/app/src/state/ducks/contributions.test.js +++ b/app/src/state/ducks/contributions.test.js @@ -246,13 +246,7 @@ describe('Side Effects', () => { const { id } = await contribution.json(); return store - .dispatch( - api.bulkUpdateContributions({ - ids: [id], - status: 'Submitted', - currentUserId: campaignAdminId, - }) - ) + .dispatch(contributions.bulkUpdateContributions([{ id }])) .then(() => { const actions = store.getActions(); expect(actions[0].type).toEqual(expectedActions[0].type); From f50c9936c5a6ca3d90787330bdc4db6f82ea4aa0 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 17 Jan 2021 13:03:53 -0800 Subject: [PATCH 06/13] log state --- app/src/state/ducks/contributions.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/state/ducks/contributions.js b/app/src/state/ducks/contributions.js index 1e0940f95..f676ab171 100644 --- a/app/src/state/ducks/contributions.js +++ b/app/src/state/ducks/contributions.js @@ -308,6 +308,7 @@ export function bulkUpdateContributions(contributionAttrsArray) { dispatch(actionCreators.updateContribution.request()); try { const state = getState(); + console.log('bulk state: ', state); const currentUserId = state.auth.me.id; const ids = contributionAttrsArray.map(contribution => contribution.id); const bulkSubmitInfo = { From 65ffc9c0f6d8af773e87f6c62c39e53b476f1dbc Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 17 Jan 2021 13:13:07 -0800 Subject: [PATCH 07/13] add to mock state --- app/src/api/api.js | 1 - app/src/state/ducks/contributions.test.js | 8 +++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/api/api.js b/app/src/api/api.js index 783671070..0588f42b1 100644 --- a/app/src/api/api.js +++ b/app/src/api/api.js @@ -597,7 +597,6 @@ export function updateCampaignNameForGovernment(campaignAttrs) { // path: '/contributions/:id' // method: 'put', export function updateContribution(contributionAttrs) { - console.log(contributionAttrs); return put( `${baseUrl()}/contributions/${contributionAttrs.id}`, contributionAttrs diff --git a/app/src/state/ducks/contributions.test.js b/app/src/state/ducks/contributions.test.js index 03c4be433..a330acf14 100644 --- a/app/src/state/ducks/contributions.test.js +++ b/app/src/state/ducks/contributions.test.js @@ -220,7 +220,13 @@ describe('Side Effects', () => { { type: actionTypes.UPDATE_CONTRIBUTION.REQUEST }, { type: actionTypes.UPDATE_CONTRIBUTION.SUCCESS }, ]; - const store = mockStore({}); + const store = mockStore({ + auth: { + me: { + id: 2, + }, + }, + }); process.env.TOKEN = campaignAdminToken; From 77efe7ae4b9b1ee7ccc0717d1c396c7fe8e5bd3b Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 17 Jan 2021 13:22:23 -0800 Subject: [PATCH 08/13] a new hope --- app/src/state/ducks/contributions.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/src/state/ducks/contributions.js b/app/src/state/ducks/contributions.js index f676ab171..9f36144f3 100644 --- a/app/src/state/ducks/contributions.js +++ b/app/src/state/ducks/contributions.js @@ -318,9 +318,9 @@ export function bulkUpdateContributions(contributionAttrsArray) { }; console.log({ bulkSubmitInfo }); const response = await api.bulkUpdateContributions(bulkSubmitInfo); + const res = await response.json(); + console.log(res, response); if (response.status === 200) { - const res = await response.json(); - console.log(res, response); dispatch(actionCreators.updateContribution.success()); if (res.message) { dispatch( @@ -331,11 +331,9 @@ export function bulkUpdateContributions(contributionAttrsArray) { } } else { dispatch(actionCreators.updateContribution.failure()); - const error = await response.json(); dispatch( - flashMessage(`Error - ${error}`, { props: { variant: 'error' } }) + flashMessage(`Error - ${res}`, { props: { variant: 'error' } }) ); - return error; } } catch (error) { dispatch(actionCreators.updateContribution.failure(error)); From c273a0f01f7ad2d68c29ccf038a9b22c18b820dc Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 17 Jan 2021 13:35:56 -0800 Subject: [PATCH 09/13] empire strikes back --- app/src/state/ducks/contributions.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/state/ducks/contributions.test.js b/app/src/state/ducks/contributions.test.js index a330acf14..33fc514b0 100644 --- a/app/src/state/ducks/contributions.test.js +++ b/app/src/state/ducks/contributions.test.js @@ -210,6 +210,7 @@ describe('Side Effects', () => { ) .then(() => { const actions = store.getActions(); + console.log(actions); expect(actions[0].type).toEqual(expectedActions[0].type); expect(actions[1].type).toEqual(expectedActions[1].type); }); From 41e791b51119c960192ad5e194810c37e514ef7b Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 17 Jan 2021 13:59:47 -0800 Subject: [PATCH 10/13] add api test --- app/src/api/api.test.js | 32 +++++++++++++++++++++++ app/src/state/ducks/contributions.test.js | 4 +-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/app/src/api/api.test.js b/app/src/api/api.test.js index c53b32ee5..05885837e 100644 --- a/app/src/api/api.test.js +++ b/app/src/api/api.test.js @@ -301,6 +301,38 @@ describe('API', () => { expect(response.status).toEqual(204); }); + it('bulkUpdateContributions', async () => { + process.env.TOKEN = campaignStaffToken; + + let response = await api.createContribution({ + address1: '123 ABC ST', + amount: 250, + campaignId, + city: 'Portland', + currentUserId: campaignAdminId, + date: 1562436237619, + firstName: 'John', + middleInitial: '', + lastName: 'Doe', + governmentId, + type: api.ContributionTypeEnum.CONTRIBUTION, + subType: api.ContributionSubTypeEnum.CASH, + paymentMethod: api.PaymentMethodEnum.CASH, + state: 'OR', + status: api.ContributionStatusEnum.DRAFT, + zip: '97214', + contributorType: api.ContributorTypeEnum.INDIVIDUAL, + }); + const contribution = await response.json(); + + response = await api.bulkUpdateContributions({ + ids: [contribution.id], + status: 'Submitted', + currentUserId: campaignStaffId, + }); + expect(response.status).toEqual(200); + }); + it('getContributions', async () => { process.env.TOKEN = campaignStaffToken; const response = await api.getContributions({ diff --git a/app/src/state/ducks/contributions.test.js b/app/src/state/ducks/contributions.test.js index 33fc514b0..54bd6d4ff 100644 --- a/app/src/state/ducks/contributions.test.js +++ b/app/src/state/ducks/contributions.test.js @@ -210,13 +210,12 @@ describe('Side Effects', () => { ) .then(() => { const actions = store.getActions(); - console.log(actions); expect(actions[0].type).toEqual(expectedActions[0].type); expect(actions[1].type).toEqual(expectedActions[1].type); }); }); - it('bulkUpdateContributions', async () => { + it('bulk Update Contributions', async () => { const expectedActions = [ { type: actionTypes.UPDATE_CONTRIBUTION.REQUEST }, { type: actionTypes.UPDATE_CONTRIBUTION.SUCCESS }, @@ -256,6 +255,7 @@ describe('Side Effects', () => { .dispatch(contributions.bulkUpdateContributions([{ id }])) .then(() => { const actions = store.getActions(); + console.log({ actions }); expect(actions[0].type).toEqual(expectedActions[0].type); expect(actions[1].type).toEqual(expectedActions[1].type); }); From 2f3998a888ca87204624b4fea2fe520416b1c48a Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 17 Jan 2021 21:32:48 -0800 Subject: [PATCH 11/13] update records --- api/controller/contributions.ts | 1 - app/src/api/api.test.js | 64 ++++++------- app/src/state/ducks/contributions.test.js | 92 +++++++++---------- ...date-contributions_PUT_1179124204_body.raw | 1 + ...-contributions_PUT_1179124204_options.json | 1 + ...pdate-contributions_PUT_217525293_body.raw | 1 + ...e-contributions_PUT_217525293_options.json | 1 + 7 files changed, 82 insertions(+), 79 deletions(-) create mode 100644 app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_1179124204_body.raw create mode 100644 app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_1179124204_options.json create mode 100644 app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_217525293_body.raw create mode 100644 app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_217525293_options.json diff --git a/api/controller/contributions.ts b/api/controller/contributions.ts index 1f89372dc..6379dcf20 100644 --- a/api/controller/contributions.ts +++ b/api/controller/contributions.ts @@ -201,7 +201,6 @@ export async function bulkUpdateContributions(request: IRequest, response: Respo delete updatedContribution.ids; const updateContributionDto = Object.assign(new UpdateContributionDto(), { ...updatedContribution, - currentUserId: request.currentUser.id, id }); await checkDto(updateContributionDto); diff --git a/app/src/api/api.test.js b/app/src/api/api.test.js index 05885837e..7bef7df03 100644 --- a/app/src/api/api.test.js +++ b/app/src/api/api.test.js @@ -301,38 +301,6 @@ describe('API', () => { expect(response.status).toEqual(204); }); - it('bulkUpdateContributions', async () => { - process.env.TOKEN = campaignStaffToken; - - let response = await api.createContribution({ - address1: '123 ABC ST', - amount: 250, - campaignId, - city: 'Portland', - currentUserId: campaignAdminId, - date: 1562436237619, - firstName: 'John', - middleInitial: '', - lastName: 'Doe', - governmentId, - type: api.ContributionTypeEnum.CONTRIBUTION, - subType: api.ContributionSubTypeEnum.CASH, - paymentMethod: api.PaymentMethodEnum.CASH, - state: 'OR', - status: api.ContributionStatusEnum.DRAFT, - zip: '97214', - contributorType: api.ContributorTypeEnum.INDIVIDUAL, - }); - const contribution = await response.json(); - - response = await api.bulkUpdateContributions({ - ids: [contribution.id], - status: 'Submitted', - currentUserId: campaignStaffId, - }); - expect(response.status).toEqual(200); - }); - it('getContributions', async () => { process.env.TOKEN = campaignStaffToken; const response = await api.getContributions({ @@ -591,4 +559,36 @@ describe('API', () => { ); expect(response.status).toEqual(204); }); + it('bulkUpdateContributions', async () => { + process.env.TOKEN = campaignAdminToken; + + let response = await api.createContribution({ + address1: '123 ABC ST', + amount: 250, + campaignId, + city: 'Portland', + currentUserId: campaignAdminId, + date: 1562436237619, + firstName: 'John', + middleInitial: '', + lastName: 'Doe', + governmentId, + type: api.ContributionTypeEnum.CONTRIBUTION, + subType: api.ContributionSubTypeEnum.CASH, + paymentMethod: api.PaymentMethodEnum.CASH, + state: 'OR', + status: api.ContributionStatusEnum.DRAFT, + zip: '97214', + contributorType: api.ContributorTypeEnum.INDIVIDUAL, + }); + const contribution = await response.json(); + console.log('added it', contribution); + response = await api.bulkUpdateContributions({ + ids: [contribution.id], + status: 'Submitted', + currentUserId: campaignStaffId, + }); + console.log('bulk response', response); + expect(response.status).toEqual(200); + }); }); diff --git a/app/src/state/ducks/contributions.test.js b/app/src/state/ducks/contributions.test.js index 54bd6d4ff..08e5a2a2e 100644 --- a/app/src/state/ducks/contributions.test.js +++ b/app/src/state/ducks/contributions.test.js @@ -215,52 +215,6 @@ describe('Side Effects', () => { }); }); - it('bulk Update Contributions', async () => { - const expectedActions = [ - { type: actionTypes.UPDATE_CONTRIBUTION.REQUEST }, - { type: actionTypes.UPDATE_CONTRIBUTION.SUCCESS }, - ]; - const store = mockStore({ - auth: { - me: { - id: 2, - }, - }, - }); - - process.env.TOKEN = campaignAdminToken; - - const contribution = await api.createContribution({ - address1: '123 ABC ST', - amount: 250, - campaignId, - city: 'Portland', - currentUserId: campaignAdminId, - date: 1562436237619, - firstName: 'John', - middleInitial: '', - lastName: 'Doe', - governmentId, - type: api.ContributionTypeEnum.CONTRIBUTION, - subType: api.ContributionSubTypeEnum.CASH, - paymentMethod: api.PaymentMethodEnum.CASH, - state: 'OR', - status: api.ContributionStatusEnum.DRAFT, - zip: '97214', - contributorType: api.ContributorTypeEnum.INDIVIDUAL, - }); - const { id } = await contribution.json(); - - return store - .dispatch(contributions.bulkUpdateContributions([{ id }])) - .then(() => { - const actions = store.getActions(); - console.log({ actions }); - expect(actions[0].type).toEqual(expectedActions[0].type); - expect(actions[1].type).toEqual(expectedActions[1].type); - }); - }); - it('gets contributions', async () => { const expectedActions = [ { type: actionTypes.GET_CONTRIBUTIONS.REQUEST }, @@ -406,4 +360,50 @@ describe('Side Effects', () => { expect(actions[2].type).toEqual(expectedActions[2].type); }); }); + + it('bulk Update Contributions', async () => { + const expectedActions = [ + { type: actionTypes.UPDATE_CONTRIBUTION.REQUEST }, + { type: actionTypes.UPDATE_CONTRIBUTION.SUCCESS }, + ]; + const store = mockStore({ + auth: { + me: { + id: 2, + }, + }, + }); + + process.env.TOKEN = campaignAdminToken; + + const contribution = await api.createContribution({ + address1: '123 ABC ST', + amount: 250, + campaignId, + city: 'Portland', + currentUserId: campaignAdminId, + date: 1562436237619, + firstName: 'John', + middleInitial: '', + lastName: 'Doe', + governmentId, + type: api.ContributionTypeEnum.CONTRIBUTION, + subType: api.ContributionSubTypeEnum.CASH, + paymentMethod: api.PaymentMethodEnum.CASH, + state: 'OR', + status: api.ContributionStatusEnum.DRAFT, + zip: '97214', + contributorType: api.ContributorTypeEnum.INDIVIDUAL, + }); + const { id } = await contribution.json(); + + return store + .dispatch(contributions.bulkUpdateContributions([{ id }])) + .then(() => { + const actions = store.getActions(); + console.log({ actions }); + expect(actions[0].type).toEqual(expectedActions[0].type); + expect(actions[1].type).toEqual(expectedActions[1].type); + }); + }); }); diff --git a/app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_1179124204_body.raw b/app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_1179124204_body.raw new file mode 100644 index 000000000..bf6b4af77 --- /dev/null +++ b/app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_1179124204_body.raw @@ -0,0 +1 @@ +{"message":"1 of 1 successfully updated."} \ No newline at end of file diff --git a/app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_1179124204_options.json b/app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_1179124204_options.json new file mode 100644 index 000000000..339e1f2d7 --- /dev/null +++ b/app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_1179124204_options.json @@ -0,0 +1 @@ +{"url":"http://localhost:3000/bulk-update-contributions","status":200,"statusText":"OK","ok":true,"headers":{"x-powered-by":["Express"],"vary":["Origin"],"access-control-allow-credentials":["true"],"content-type":["application/json; charset=utf-8"],"content-length":["42"],"etag":["W/\"2a-LIcWy6ni0+o5ijinQ/GzC9gLQko\""],"date":["Mon, 18 Jan 2021 05:30:20 GMT"],"connection":["close"]}} \ No newline at end of file diff --git a/app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_217525293_body.raw b/app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_217525293_body.raw new file mode 100644 index 000000000..bf6b4af77 --- /dev/null +++ b/app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_217525293_body.raw @@ -0,0 +1 @@ +{"message":"1 of 1 successfully updated."} \ No newline at end of file diff --git a/app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_217525293_options.json b/app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_217525293_options.json new file mode 100644 index 000000000..c09c56094 --- /dev/null +++ b/app/test/recordings/http%3A__localhost%3A3000_bulk-update-contributions_PUT_217525293_options.json @@ -0,0 +1 @@ +{"url":"http://localhost:3000/bulk-update-contributions","status":200,"statusText":"OK","ok":true,"headers":{"x-powered-by":["Express"],"vary":["Origin"],"access-control-allow-credentials":["true"],"content-type":["application/json; charset=utf-8"],"content-length":["42"],"etag":["W/\"2a-LIcWy6ni0+o5ijinQ/GzC9gLQko\""],"date":["Mon, 18 Jan 2021 05:30:19 GMT"],"connection":["close"]}} \ No newline at end of file From 5dce8b689defa2ab3385baad36c79faead8d8e93 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 18 Jan 2021 10:46:05 -0800 Subject: [PATCH 12/13] clean up code --- api/routes/index.ts | 1 - .../Contributions/ContributionsTable/ContributionsTable.js | 2 +- app/src/state/ducks/contributions.js | 3 --- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/api/routes/index.ts b/api/routes/index.ts index 082b4dab8..145b3a4ed 100644 --- a/api/routes/index.ts +++ b/api/routes/index.ts @@ -559,7 +559,6 @@ export const AppRoutes = [ * $ref: '#/components/responses/UnprocessableEntity' * */ - // TODO: verify swagger is correct { path: '/bulk-update-contributions', method: 'put', diff --git a/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js b/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js index 74411362a..4eca695a3 100644 --- a/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js +++ b/app/src/Pages/Portal/Contributions/ContributionsTable/ContributionsTable.js @@ -330,7 +330,7 @@ class ContributionsTable extends React.Component { }); }} > - bulk submit + Bulk submit )} {this.state.bulkSubmitted && ( diff --git a/app/src/state/ducks/contributions.js b/app/src/state/ducks/contributions.js index 9f36144f3..b3f4dfd70 100644 --- a/app/src/state/ducks/contributions.js +++ b/app/src/state/ducks/contributions.js @@ -308,7 +308,6 @@ export function bulkUpdateContributions(contributionAttrsArray) { dispatch(actionCreators.updateContribution.request()); try { const state = getState(); - console.log('bulk state: ', state); const currentUserId = state.auth.me.id; const ids = contributionAttrsArray.map(contribution => contribution.id); const bulkSubmitInfo = { @@ -316,10 +315,8 @@ export function bulkUpdateContributions(contributionAttrsArray) { ids, status: 'Submitted', }; - console.log({ bulkSubmitInfo }); const response = await api.bulkUpdateContributions(bulkSubmitInfo); const res = await response.json(); - console.log(res, response); if (response.status === 200) { dispatch(actionCreators.updateContribution.success()); if (res.message) { From 8b27e8bb2884beb6c90e0f4dc74c9d25b1574197 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sat, 10 Apr 2021 16:36:50 -0700 Subject: [PATCH 13/13] rm console logs --- app/src/state/ducks/contributions.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/state/ducks/contributions.js b/app/src/state/ducks/contributions.js index b3f4dfd70..ee6c05df3 100644 --- a/app/src/state/ducks/contributions.js +++ b/app/src/state/ducks/contributions.js @@ -272,7 +272,6 @@ export function updateContribution(contributionAttrs) { dispatch(actionCreators.updateContribution.request()); try { const response = await api.updateContribution(contributionAttrs); - console.log({ contributionAttrs, response }); if (response.status === 204) { let status = ''; if (contributionAttrs.status) {