Skip to content

Commit

Permalink
perf(confirm): ask delete and update confirm in pipeline board stage
Browse files Browse the repository at this point in the history
Close #2005
  • Loading branch information
munkhorgil committed May 20, 2020
1 parent 029ca8f commit 09984ee
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 11 deletions.
23 changes: 20 additions & 3 deletions ui/src/modules/common/components/ButtonMutate.tsx
@@ -1,7 +1,7 @@
import client from 'apolloClient';
import gql from 'graphql-tag';
import { colors } from 'modules/common/styles';
import { __, Alert } from 'modules/common/utils';
import { __, Alert, confirm } from 'modules/common/utils';
import { rotate } from 'modules/common/utils/animations';
import React from 'react';
import styled from 'styled-components';
Expand Down Expand Up @@ -37,6 +37,7 @@ type Props = {
disabled?: boolean;
disableLoading?: boolean;
block?: boolean;
confirmationUpdate?: boolean;
beforeSubmit?: () => void;
resetSubmit?: () => void;
};
Expand All @@ -61,7 +62,7 @@ class ButtonMutate extends React.Component<Props, { isLoading: boolean }> {
}
};

mutate = () => {
invokeMutate = () => {
const {
mutation,
callback,
Expand Down Expand Up @@ -120,6 +121,22 @@ class ButtonMutate extends React.Component<Props, { isLoading: boolean }> {
});
};

mutate = () => {
const { confirmationUpdate } = this.props;

if (confirmationUpdate) {
return confirm('Please make sure your changes, this action cannot be undone', { hasUpdateConfirm: true })
.then(() => {
this.invokeMutate();
})
.catch(error => {
Alert.error(error.message);
})
}

return this.invokeMutate();
};

render() {
const {
children = __('Save'),
Expand All @@ -129,7 +146,7 @@ class ButtonMutate extends React.Component<Props, { isLoading: boolean }> {
btnStyle = 'success',
disabled,
block,
uppercase
uppercase,
} = this.props;

const { isLoading } = this.state;
Expand Down
67 changes: 65 additions & 2 deletions ui/src/modules/common/components/ConfirmDialog.tsx
Expand Up @@ -4,6 +4,7 @@ import Modal from 'react-bootstrap/Modal';
import styled from 'styled-components';
import { colors, dimensions } from '../styles';
import Button from './Button';
import { ControlLabel, FormControl, FormGroup } from './form';
import Icon from './Icon';

const ModalBody = styled.div`
Expand Down Expand Up @@ -32,6 +33,8 @@ type Props = {
okLabel?: string;
cancelLabel?: string;
enableEscape?: boolean;
hasDeleteConfirm?: boolean;
hasUpdateConfirm?: boolean;
};
confirmation?: string;
proceed: () => void;
Expand All @@ -40,13 +43,19 @@ type Props = {

type State = {
show: boolean;
confirm: string;
errors: { [key: string]: string };
};

class ConfirmDialog extends React.Component<Props, State> {
constructor(props) {
super(props);

this.state = { show: true };
this.state = {
show: true,
confirm: '',
errors: {}
};
}

dismiss = () => {
Expand All @@ -55,10 +64,33 @@ class ConfirmDialog extends React.Component<Props, State> {
});
};

proceed = () => {
invokeProceed() {
this.setState({ show: false }, () => {
this.props.proceed();
});
}

proceed = () => {
const { options = {} } = this.props;
const { hasDeleteConfirm, hasUpdateConfirm } = options;

if (hasDeleteConfirm) {
if (this.state.confirm === 'delete') {
return this.invokeProceed();
}

return this.setState({ errors: { confirm: 'Enter delete to confirm' } });
}

if (hasUpdateConfirm) {
if (this.state.confirm === 'update') {
return this.invokeProceed();
}

return this.setState({ errors: { confirm: 'Enter update to confirm' } });
}

return this.invokeProceed();
};

handleKeydown = e => {
Expand All @@ -75,6 +107,36 @@ class ConfirmDialog extends React.Component<Props, State> {
document.removeEventListener('keydown', this.handleKeydown);
}

handleChange = e => {
this.setState({ confirm: e.target.value });
};

renderConfirmDelete() {
const { errors, confirm } = this.state;
const { hasDeleteConfirm = false, hasUpdateConfirm = false } = this.props.options || {};

if (!hasDeleteConfirm && !hasUpdateConfirm) {
return null;
}

const label = hasDeleteConfirm ?
'Confirm deletion by typing delete' :
'Confirm change by typing update'

return (
<FormGroup>
<ControlLabel required={true}>{label}</ControlLabel>
<FormControl
name="confirm"
required={true}
value={confirm}
errors={errors}
onChange={this.handleChange}
/>
</FormGroup>
);
}

render() {
const { confirmation = 'Are you sure?', options = {} } = this.props;

Expand All @@ -98,6 +160,7 @@ class ConfirmDialog extends React.Component<Props, State> {
<Icon icon="exclamation-triangle" />
</IconWrapper>
{__(confirmation)}
{this.renderConfirmDelete()}
</ModalBody>
<ModalFooter>
<Button
Expand Down
1 change: 1 addition & 0 deletions ui/src/modules/common/types.ts
Expand Up @@ -79,6 +79,7 @@ export type IButtonMutateProps = {
name?: string;
values: any;
isSubmitted: boolean;
confirmationUpdate?: boolean;
callback?: () => void;
resetSubmit?: () => void;
size?: string;
Expand Down
3 changes: 2 additions & 1 deletion ui/src/modules/settings/boards/components/PipelineForm.tsx
Expand Up @@ -291,7 +291,8 @@ class PipelineForm extends React.Component<Props, State> {
values: this.generateDoc(values),
isSubmitted,
callback: closeModal,
object: pipeline
object: pipeline,
confirmationUpdate: true
})}
</Modal.Footer>
</Modal.Body>
Expand Down
4 changes: 4 additions & 0 deletions ui/src/modules/settings/boards/constants.ts
Expand Up @@ -38,3 +38,7 @@ export const PROBABILITY = {
ALL: [...COMMON_PERCENT, 'Resolved']
}
};

export const getWarningMessage = (type: string): string => {
return `Are you sure you want to delete? everything related to this ${type} will be deleted, this action cannot be undone`;
};
6 changes: 4 additions & 2 deletions ui/src/modules/settings/boards/containers/Boards.tsx
Expand Up @@ -11,6 +11,7 @@ import React from 'react';
import { graphql } from 'react-apollo';
import { withRouter } from 'react-router-dom';
import Boards from '../components/Boards';
import { getWarningMessage } from '../constants';
import { mutations, queries } from '../graphql';
import { IOption, RemoveBoardMutationResponse } from '../types';

Expand Down Expand Up @@ -43,9 +44,10 @@ class BoardsContainer extends React.Component<FinalProps> {

// remove action
const remove = boardId => {
confirm().then(() => {
confirm(getWarningMessage('Board'), { hasDeleteConfirm: true }).then(() => {
removeMutation({
variables: { _id: boardId }
variables: { _id: boardId },
refetchQueries: getRefetchQueries()
})
.then(() => {
// if deleted board is default board
Expand Down
7 changes: 5 additions & 2 deletions ui/src/modules/settings/boards/containers/Pipelines.tsx
Expand Up @@ -11,6 +11,7 @@ import { __, Alert, confirm, withProps } from 'modules/common/utils';
import React from 'react';
import { graphql } from 'react-apollo';
import Pipelines from '../components/Pipelines';
import { getWarningMessage } from '../constants';
import { mutations, queries } from '../graphql';
import {
IOption,
Expand Down Expand Up @@ -51,7 +52,7 @@ class PipelinesContainer extends React.Component<FinalProps> {

// remove action
const remove = pipelineId => {
confirm().then(() => {
confirm(getWarningMessage('Pipeline'), { hasDeleteConfirm: true }).then(() => {
removePipelineMutation({
variables: { _id: pipelineId }
})
Expand All @@ -75,13 +76,15 @@ class PipelinesContainer extends React.Component<FinalProps> {
values,
isSubmitted,
callback,
object
object,
confirmationUpdate
}: IButtonMutateProps) => {
return (
<ButtonMutate
mutation={object ? mutations.pipelineEdit : mutations.pipelineAdd}
variables={values}
callback={callback}
confirmationUpdate={confirmationUpdate}
refetchQueries={getRefetchQueries(boardId)}
isSubmitted={isSubmitted}
type="submit"
Expand Down
1 change: 1 addition & 0 deletions ui/src/modules/settings/boards/types.ts
Expand Up @@ -32,6 +32,7 @@ export type RemoveBoardMutationResponse = {
removeMutation: (
params: {
variables: RemoveBoardMutationVariables;
refetchQueries: string[];
}
) => Promise<void>;
};
Expand Down
5 changes: 4 additions & 1 deletion ui/src/modules/settings/common/components/Form.tsx
Expand Up @@ -6,6 +6,7 @@ import React from 'react';
import { ICommonFormProps } from '../types';

type Props = {
confirmationUpdate?: boolean;
renderButton?: (props: IButtonMutateProps) => JSX.Element;
generateDoc: (values: any) => any;
object?: any;
Expand All @@ -19,6 +20,7 @@ class Form extends React.Component<Props & ICommonFormProps> {
renderContent,
renderButton,
closeModal,
confirmationUpdate,
object,
name
} = this.props;
Expand All @@ -44,7 +46,8 @@ class Form extends React.Component<Props & ICommonFormProps> {
values: this.props.generateDoc(values),
isSubmitted,
callback: closeModal,
object
object,
confirmationUpdate,
})}
</ModalFooter>
</>
Expand Down
Expand Up @@ -127,6 +127,7 @@ class TemplateForm extends React.Component<Props & ICommonFormProps, State> {
renderContent={this.renderContent}
generateDoc={this.generateDoc}
object={this.props.object}
confirmationUpdate={true}
/>
);
}
Expand Down
2 changes: 2 additions & 0 deletions ui/src/modules/settings/utils/commonListComposer.tsx
Expand Up @@ -100,6 +100,7 @@ function commonListComposer<ComponentProps>(options) {
values,
isSubmitted,
callback,
confirmationUpdate,
object
}: IButtonMutateProps) => {
const afterMutate = () => {
Expand Down Expand Up @@ -132,6 +133,7 @@ function commonListComposer<ComponentProps>(options) {
isSubmitted={isSubmitted}
type="submit"
uppercase={false}
confirmationUpdate={confirmationUpdate}
successMessage={`You successfully ${successAction} a ${name}`}
/>
);
Expand Down

0 comments on commit 09984ee

Please sign in to comment.