Skip to content

Commit

Permalink
Deactivate transfer card (#602)
Browse files Browse the repository at this point in the history
* starting

* Adding capacity to disable transfer card

* fixing migration

fixing migration

* Update afdbf2c8d633_.py

* Create afdbf2c8d633_.py

* fixes

* adding is_disabled rejection if already disabled

* merging heads

* Fix test

* fixing id ref

* version and changelog

Co-authored-by: michielderoos <michiel@deroos.ca>
  • Loading branch information
enjeyw and michielderoos committed Mar 10, 2021
1 parent b66eecf commit 8b7e4a4
Show file tree
Hide file tree
Showing 21 changed files with 328 additions and 33 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [v1.8.0] - 2021-03-11

### Added capacity to deactivate transfer cards as per https://github.com/teamsempo/SempoBlockchain/pull/602

## [v1.7.72] - 2021-03-10

### Added
Expand Down
2 changes: 1 addition & 1 deletion app/client/api/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ export interface ApiClientType {
isForm?: boolean;
query?: null | Query;
body?: null | Body;
path?: null | number;
path?: null | number | string;
errorHandling?: boolean;
}
10 changes: 10 additions & 0 deletions app/client/api/transferCardAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { apiClient } from "./client/apiClient";
import { EditTransferCardPayload } from "../reducers/transferCard/types";

export const editTransferCardAPI = ({ body, path }: EditTransferCardPayload) =>
apiClient({
url: "/transfer_cards/public_serial_number/",
method: "PUT",
body: body,
path: path
});
4 changes: 3 additions & 1 deletion app/client/components/form/WrappedInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export const AdaptedInput = (props: any) => {
placeholder,
disabled,
isPhoneNumber,
isMultipleChoice
isMultipleChoice,
style
} = props;

const field = isMultipleChoice ? (
Expand All @@ -50,6 +51,7 @@ export const AdaptedInput = (props: any) => {
name={name}
disabled={disabled}
type={type}
style={style}
{...input}
/>
);
Expand Down
66 changes: 49 additions & 17 deletions app/client/components/user/EditUserForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { connect } from "react-redux";

import { reduxForm, InjectedFormProps, formValueSelector } from "redux-form";

import { Tooltip } from "antd";

import { StopOutlined } from "@ant-design/icons";

import { GenderTypes } from "./types";
import {
Wrapper,
Expand Down Expand Up @@ -47,6 +51,7 @@ interface OuterProps {
transferUsages: TransferUsage[];
onResetPin: () => void;
onDeleteUser: () => void;
onDisableCard: () => void;
}

interface StateProps {
Expand Down Expand Up @@ -264,13 +269,40 @@ class EditUserForm extends React.Component<
</SubRow>
</Row>
<Row>
<SubRow>
<SubRow
style={{
color:
selectedUser.transfer_card &&
selectedUser.transfer_card.is_disabled
? "#c53631"
: "#555"
}}
>
<InputField name="publicSerialNumber" label={"ID Number"}>
{/*
// @ts-ignore */}
<QrReadingModal
updateData={(data: string) => this.setSerialNumber(data)}
/>
{/* // @ts-ignore */}

<div style={{ display: "flex", alignItems: "flex-end" }}>
<QrReadingModal
updateData={(data: string) =>
this.setSerialNumber(data)
}
/>
{selectedUser.public_serial_number ? (
<Tooltip title="Disable Card">
<StopOutlined
translate={""}
style={{
fontSize: "20px",
margin: "2px",
color: "#555"
}}
onClick={() => this.props.onDisableCard()}
/>
</Tooltip>
) : (
<></>
)}
</div>
</InputField>
</SubRow>
<SubRow>
Expand Down Expand Up @@ -383,14 +415,14 @@ const EditUserFormReduxForm = reduxForm<IEditUser, Props>({
validate
})(EditUserForm);

export default connect(
(state: ReduxState): StateProps => {
const selector = formValueSelector("editUser");
return {
accountTypes: selector(state, "accountTypes"),
businessUsageValue: selector(state, "businessUsage"),
// @ts-ignore
activeOrganisation: state.organisations.byId[state.login.organisationId]
};
}
)(EditUserFormReduxForm);
const mapStateToProps = (state: ReduxState): StateProps => {
const selector = formValueSelector("editUser");
return {
accountTypes: selector(state, "accountTypes"),
businessUsageValue: selector(state, "businessUsage"),
// @ts-ignore
activeOrganisation: state.organisations.byId[state.login.organisationId]
};
};

export default connect(mapStateToProps)(EditUserFormReduxForm);
42 changes: 40 additions & 2 deletions app/client/components/user/SingleUserManagement.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,21 @@ import {
import {
User,
ResetPinPayload,
DeleteUserPayload
DeleteUserPayload,
LoadUserRequestPayload
} from "../../reducers/user/types";

import { EditTransferCardAction } from "../../reducers/transferCard/actions";

interface DispatchProps {
editUser: (body: User, path: number) => EditUserAction;
resetPin: (payload: ResetPinPayload) => ResetPinAction;
deleteUser: (payload: DeleteUserPayload) => DeleteUserAction;
editTransferCard: (
body: any,
path: string,
userId: number
) => EditTransferCardAction;
}

interface StateProps {
Expand Down Expand Up @@ -89,6 +97,30 @@ class SingleUserManagement extends React.Component<Props> {
}
}

onDisableCard() {
if (
this.props.selectedUser.transfer_card &&
this.props.selectedUser.transfer_card.is_disabled
) {
window.alert("This card has already been disabled.");
return;
}

if (
!window.confirm(
"Warning: A card that has been disabled cannot be re-enabled. Continue?"
)
) {
return;
}

this.props.editTransferCard(
{ disable: true },
this.props.selectedUser.public_serial_number,
this.props.selectedUser.id
);
}

render() {
return (
<EditUserForm
Expand All @@ -98,6 +130,7 @@ class SingleUserManagement extends React.Component<Props> {
onSubmit={(form: IEditUser) => this.onEditUser(form)}
onResetPin={() => this.onResetPin()}
onDeleteUser={() => this.onDeleteUser()}
onDisableCard={() => this.onDisableCard()}
/>
);
}
Expand All @@ -116,7 +149,12 @@ const mapDispatchToProps = (dispatch: any): DispatchProps => {
editUser: (body: User, path: number) =>
dispatch(EditUserAction.editUserRequest({ body, path })),
resetPin: payload => dispatch(ResetPinAction.resetPinRequest(payload)),
deleteUser: payload => dispatch(DeleteUserAction.deleteUserRequest(payload))
deleteUser: payload =>
dispatch(DeleteUserAction.deleteUserRequest(payload)),
editTransferCard: (body: any, path: string, userId) =>
dispatch(
EditTransferCardAction.editTransferCardRequest({ body, path, userId })
)
};
};

Expand Down
6 changes: 4 additions & 2 deletions app/client/reducers/rootReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { TransferUsageReducer } from "./transferUsage/reducers";
import { OrganisationReducer } from "./organisation/reducers";
import { metrics } from "./metric/reducers";
import { allowedFilters } from "./allowedFilters/reducers";
import { transferCard } from "./transferCard/reducers";
import { tokens } from "./token/reducers";
import { all } from "redux-saga/effects";
import { userSchema } from "../schemas";
Expand Down Expand Up @@ -62,8 +63,9 @@ const appReducer = combineReducers({
transferUsages: TransferUsageReducer,
organisations: OrganisationReducer,
allowedFilters,
tokens,
form
form,
transferCard,
tokens
});

const rootReducer = (state: any, action: any) => {
Expand Down
17 changes: 17 additions & 0 deletions app/client/reducers/transferCard/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { EditTransferCardActionTypes, EditTransferCardPayload } from "./types";
import { createAction, ActionsUnion } from "../../reduxUtils";

export const EditTransferCardAction = {
editTransferCardRequest: (payload: EditTransferCardPayload) =>
createAction(
EditTransferCardActionTypes.EDIT_TRANSFER_CARD_REQUEST,
payload
),
editTransferCardSuccess: () =>
createAction(EditTransferCardActionTypes.EDIT_TRANSFER_CARD_SUCCESS),
editTransferCardFailure: (error: string) =>
createAction(EditTransferCardActionTypes.EDIT_TRANSFER_CARD_FAILURE, error)
};
export type EditTransferCardAction = ActionsUnion<
typeof EditTransferCardAction
>;
37 changes: 37 additions & 0 deletions app/client/reducers/transferCard/reducers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { combineReducers } from "redux";

import { EditTransferCardActionTypes } from "./types";

import { EditTransferCardAction } from "./actions";

interface RequestingState {
isRequesting: boolean;
success: boolean;
error: null | string;
}

const initialState: RequestingState = {
isRequesting: false,
success: false,
error: null
};

const editStatus = (state = initialState, action: EditTransferCardAction) => {
switch (action.type) {
case EditTransferCardActionTypes.EDIT_TRANSFER_CARD_REQUEST:
return { ...state, isRequesting: true };

case EditTransferCardActionTypes.EDIT_TRANSFER_CARD_SUCCESS:
return { ...state, isRequesting: false, success: true };

case EditTransferCardActionTypes.EDIT_TRANSFER_CARD_FAILURE:
return { ...state, isRequesting: false, error: action.error };

default:
return state;
}
};

export const transferCard = combineReducers({
editStatus
});
18 changes: 18 additions & 0 deletions app/client/reducers/transferCard/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export interface TransferCard {
public_serial_number: string;
is_disabled: boolean;
}

export enum EditTransferCardActionTypes {
EDIT_TRANSFER_CARD_REQUEST = "EDIT_TRANSFER_CARD_REQUEST",
EDIT_TRANSFER_CARD_SUCCESS = "EDIT_TRANSFER_CARD_SUCCESS",
EDIT_TRANSFER_CARD_FAILURE = "EDIT_TRANSFER_CARD_FAILURE"
}

export interface EditTransferCardPayload {
body: {
disable?: boolean;
};
path: string;
userId: number;
}
2 changes: 1 addition & 1 deletion app/client/reducers/user/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export enum LoadUserActionTypes {
}

export interface LoadUserRequestPayload {
query: {};
query?: {};
path: number;
}

Expand Down
2 changes: 2 additions & 0 deletions app/client/sagas/rootSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import transferUsageSagas from "./transferUsageSagas";
import organisationSagas from "./organisationSagas";
import metricSaga from "./metricSaga";
import allowedFilterSaga from "./allowedFilterSaga";
import transferCardSagas from "./transferCardSagas";
import tokenSagas from "./tokenSaga";

export default function* rootSaga() {
Expand All @@ -30,6 +31,7 @@ export default function* rootSaga() {
organisationSagas(),
metricSaga(),
allowedFilterSaga(),
transferCardSagas(),
tokenSagas()
]);
}
50 changes: 50 additions & 0 deletions app/client/sagas/transferCardSagas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { put, takeEvery, call, all } from "redux-saga/effects";
import { message } from "antd";
import { handleError } from "../utils";

import {
EditTransferCardActionTypes,
EditTransferCardPayload
} from "../reducers/transferCard/types";

import { EditTransferCardAction } from "../reducers/transferCard/actions";

import { LoadUserAction } from "../reducers/user/actions";

import { editTransferCardAPI } from "../api/transferCardAPI";

import { ActionWithPayload } from "../reduxUtils";

function* editTransferCard(
action: ActionWithPayload<
EditTransferCardActionTypes.EDIT_TRANSFER_CARD_REQUEST,
EditTransferCardPayload
>
) {
try {
const load_result = yield call(editTransferCardAPI, action.payload);

yield put(EditTransferCardAction.editTransferCardSuccess());

yield put(LoadUserAction.loadUserRequest({ path: action.payload.userId }));

message.success(load_result.message);
} catch (fetch_error) {
const error = yield call(handleError, fetch_error);

yield put(EditTransferCardAction.editTransferCardFailure(error.message));

message.error(error.message);
}
}

function* watchEditTransferCard() {
yield takeEvery(
EditTransferCardActionTypes.EDIT_TRANSFER_CARD_REQUEST,
editTransferCard
);
}

export default function* transferCardSagas() {
yield all([watchEditTransferCard()]);
}
Loading

0 comments on commit 8b7e4a4

Please sign in to comment.