feat: add confirmation for Datasource deletion operation (#11180)
* add confirmation for Datasource, refactor other components * fix failing cypress tests * fix Mongo_spec failing test
This commit is contained in:
parent
c03ecf2e13
commit
ead4d875fa
|
|
@ -120,6 +120,7 @@ describe("Entity explorer tests related to query and datasource", function() {
|
|||
.click({ force: true });
|
||||
cy.contains(".t--datasource-name", datasourceName).click();
|
||||
cy.get(".t--delete-datasource").click();
|
||||
cy.get("[data-cy=t--confirm-modal-btn]").click();
|
||||
cy.wait("@deleteDatasource").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ describe("Entity explorer tests related to copy query", function() {
|
|||
cy.wait(2000);
|
||||
cy.hoverAndClick();
|
||||
cy.get(apiwidget.delete).click({ force: true });
|
||||
cy.get("[data-cy=t--confirm-modal-btn]").click();
|
||||
//This is check to make sure if a datasource is active 409
|
||||
cy.wait("@deleteDatasource").should(
|
||||
"have.nested.property",
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the
|
|||
cy.NavigateToActiveTab();
|
||||
cy.contains(".t--datasource-name", datasourceName).click();
|
||||
cy.get(".t--delete-datasource").click();
|
||||
cy.get("[data-cy=t--confirm-modal-btn]").click();
|
||||
cy.wait("@deleteDatasource").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
|
|
@ -288,6 +289,7 @@ describe("Create a query with a mongo datasource, run, save and then delete the
|
|||
cy.NavigateToActiveTab();
|
||||
cy.contains(".t--datasource-name", datasourceName).click();
|
||||
cy.get(".t--delete-datasource").click();
|
||||
cy.get("[data-cy=t--confirm-modal-btn]").click();
|
||||
// cy.wait("@deleteDatasource").should(
|
||||
// "have.nested.property",
|
||||
// "response.body.responseMeta.status",
|
||||
|
|
|
|||
|
|
@ -2186,6 +2186,7 @@ Cypress.Commands.add("testSaveDeleteDatasource", () => {
|
|||
.click();
|
||||
// delete datasource
|
||||
cy.get(".t--delete-datasource").click();
|
||||
cy.get("[data-cy=t--confirm-modal-btn]").click();
|
||||
cy.wait("@deleteDatasource").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
|
|
@ -2504,6 +2505,7 @@ Cypress.Commands.add("deleteDatasource", (datasourceName) => {
|
|||
.click({ force: true });
|
||||
cy.contains(".t--datasource-name", datasourceName).click();
|
||||
cy.get(".t--delete-datasource").click();
|
||||
cy.get("[data-cy=t--confirm-modal-btn]").click();
|
||||
cy.wait("@deleteDatasource").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
|
|
@ -2581,6 +2583,7 @@ Cypress.Commands.add("deleteJSObject", () => {
|
|||
Cypress.Commands.add("deleteDataSource", () => {
|
||||
cy.hoverAndClick();
|
||||
cy.get(apiwidget.delete).click({ force: true });
|
||||
cy.get("[data-cy=t--confirm-modal-btn]").click();
|
||||
cy.wait("@deleteDatasource").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
|
|
|
|||
|
|
@ -89,22 +89,22 @@ export const runAction = (id: string, paginationField?: PaginationField) => {
|
|||
};
|
||||
};
|
||||
|
||||
export const showRunActionConfirmModal = (show: boolean) => {
|
||||
export const showActionConfirmationModal = (show: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SHOW_RUN_ACTION_CONFIRM_MODAL,
|
||||
type: ReduxActionTypes.SHOW_ACTION_MODAL,
|
||||
payload: show,
|
||||
};
|
||||
};
|
||||
|
||||
export const cancelRunActionConfirmModal = () => {
|
||||
export const cancelActionConfirmationModal = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.CANCEL_RUN_ACTION_CONFIRM_MODAL,
|
||||
type: ReduxActionTypes.CANCEL_ACTION_MODAL,
|
||||
};
|
||||
};
|
||||
|
||||
export const acceptRunActionConfirmModal = () => {
|
||||
export const acceptActionConfirmationModal = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.ACCEPT_RUN_ACTION_CONFIRM_MODAL,
|
||||
type: ReduxActionTypes.CONFIRM_ACTION_MODAL,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -260,9 +260,9 @@ export const ReduxActionTypes = {
|
|||
DELETE_ACTION_INIT: "DELETE_ACTION_INIT",
|
||||
SET_DATASOURCE_EDITOR_MODE: "SET_DATASOURCE_EDITOR_MODE",
|
||||
DELETE_ACTION_SUCCESS: "DELETE_ACTION_SUCCESS",
|
||||
SHOW_RUN_ACTION_CONFIRM_MODAL: "SHOW_RUN_ACTION_CONFIRM_MODAL",
|
||||
CANCEL_RUN_ACTION_CONFIRM_MODAL: "CANCEL_RUN_ACTION_CONFIRM_MODAL",
|
||||
ACCEPT_RUN_ACTION_CONFIRM_MODAL: "ACCEPT_RUN_ACTION_CONFIRM_MODAL",
|
||||
SHOW_ACTION_MODAL: "SHOW_ACTION_MODAL",
|
||||
CANCEL_ACTION_MODAL: "CANCEL_ACTION_MODAL",
|
||||
CONFIRM_ACTION_MODAL: "CONFIRM_ACTION_MODAL",
|
||||
CREATE_QUERY_INIT: "CREATE_QUERY_INIT",
|
||||
ONBOARDING_CREATE_APPLICATION: "ONBOARDING_CREATE_APPLICATION",
|
||||
FETCH_DATASOURCES_INIT: "FETCH_DATASOURCES_INIT",
|
||||
|
|
@ -295,6 +295,7 @@ export const ReduxActionTypes = {
|
|||
HISTORY_PUSH: "HISTORY_PUSH",
|
||||
DELETE_DATASOURCE_INIT: "DELETE_DATASOURCE_INIT",
|
||||
DELETE_DATASOURCE_SUCCESS: "DELETE_DATASOURCE_SUCCESS",
|
||||
DELETE_DATASOURCE_CANCELLED: "DELETE_DATASOURCE_CANCELLED",
|
||||
STORE_AS_DATASOURCE_INIT: "STORE_AS_DATASOURCE_INIT",
|
||||
STORE_AS_DATASOURCE_UPDATE: "STORE_AS_DATASOURCE_UPDATE",
|
||||
STORE_AS_DATASOURCE_COMPLETE: "STORE_AS_DATASOURCE_COMPLETE",
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
getCurrentApplicationId,
|
||||
getCurrentPageName,
|
||||
} from "selectors/editorSelectors";
|
||||
import ConfirmRunModal from "pages/Editor/ConfirmRunModal";
|
||||
import RequestConfirmationModal from "pages/Editor/RequestConfirmationModal";
|
||||
import { getCurrentApplication } from "selectors/applicationSelectors";
|
||||
import {
|
||||
isPermitted,
|
||||
|
|
@ -110,7 +110,7 @@ class AppViewerPageContainer extends Component<AppViewerPageContainerProps> {
|
|||
pageId={this.props.match.params.pageId}
|
||||
pageName={this.props.currentPageName}
|
||||
/>
|
||||
<ConfirmRunModal />
|
||||
<RequestConfirmationModal />
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,8 @@ const SelectedDatasourceInfoContainer = styled.div`
|
|||
align-items: center;
|
||||
padding: 2px 8px;
|
||||
background-color: ${Colors.LIGHT_GREEN_CYAN};
|
||||
margin-right: 5px;
|
||||
margin-right: 2px;
|
||||
margin-left: 3px;
|
||||
text-transform: uppercase;
|
||||
& p {
|
||||
font-style: normal;
|
||||
|
|
@ -141,6 +142,7 @@ const SelectedDatasourceInfoContainer = styled.div`
|
|||
letter-spacing: 0.4px;
|
||||
text-transform: uppercase;
|
||||
color: ${Colors.GREEN};
|
||||
white-space: nowrap;
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import { connect } from "react-redux";
|
|||
import { AppState } from "reducers";
|
||||
import { Keys } from "@blueprintjs/core";
|
||||
import {
|
||||
showRunActionConfirmModal,
|
||||
cancelRunActionConfirmModal,
|
||||
acceptRunActionConfirmModal,
|
||||
showActionConfirmationModal,
|
||||
cancelActionConfirmationModal,
|
||||
acceptActionConfirmationModal,
|
||||
} from "actions/pluginActionActions";
|
||||
import DialogComponent from "components/ads/DialogComponent";
|
||||
import styled from "styled-components";
|
||||
|
|
@ -33,7 +33,7 @@ const ModalFooter = styled.div`
|
|||
}
|
||||
`;
|
||||
|
||||
class ConfirmRunModal extends React.Component<Props> {
|
||||
class RequestConfirmationModal extends React.Component<Props> {
|
||||
addEventListener = () => {
|
||||
document.addEventListener("keydown", this.onKeyUp);
|
||||
};
|
||||
|
|
@ -50,14 +50,14 @@ class ConfirmRunModal extends React.Component<Props> {
|
|||
|
||||
onConfirm = () => {
|
||||
const { dispatch } = this.props;
|
||||
dispatch(acceptRunActionConfirmModal());
|
||||
dispatch(acceptActionConfirmationModal());
|
||||
this.handleClose();
|
||||
};
|
||||
|
||||
handleClose = () => {
|
||||
const { dispatch } = this.props;
|
||||
dispatch(showRunActionConfirmModal(false));
|
||||
dispatch(cancelRunActionConfirmModal());
|
||||
dispatch(showActionConfirmationModal(false));
|
||||
dispatch(cancelActionConfirmationModal());
|
||||
};
|
||||
|
||||
componentDidUpdate() {
|
||||
|
|
@ -85,8 +85,9 @@ class ConfirmRunModal extends React.Component<Props> {
|
|||
<ModalFooter>
|
||||
<Button
|
||||
category={Category.tertiary}
|
||||
cypressSelector="t--cancel-modal-btn"
|
||||
onClick={() => {
|
||||
dispatch(cancelRunActionConfirmModal());
|
||||
dispatch(cancelActionConfirmationModal());
|
||||
this.handleClose();
|
||||
}}
|
||||
size={Size.medium}
|
||||
|
|
@ -96,6 +97,7 @@ class ConfirmRunModal extends React.Component<Props> {
|
|||
/>
|
||||
<Button
|
||||
category={Category.primary}
|
||||
cypressSelector="t--confirm-modal-btn"
|
||||
onClick={this.onConfirm}
|
||||
size={Size.medium}
|
||||
tag="button"
|
||||
|
|
@ -112,4 +114,4 @@ const mapStateToProps = (state: AppState) => ({
|
|||
isModalOpen: state.ui.confirmRunAction.modalOpen,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(ConfirmRunModal);
|
||||
export default connect(mapStateToProps)(RequestConfirmationModal);
|
||||
|
|
@ -20,7 +20,7 @@ import { editorInitializer } from "utils/EditorUtils";
|
|||
import CenteredWrapper from "components/designSystems/appsmith/CenteredWrapper";
|
||||
import { getCurrentUser } from "selectors/usersSelectors";
|
||||
import { User } from "constants/userConstants";
|
||||
import ConfirmRunModal from "pages/Editor/ConfirmRunModal";
|
||||
import RequestConfirmationModal from "pages/Editor/RequestConfirmationModal";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { getTheme, ThemeMode } from "selectors/themeSelectors";
|
||||
import { ThemeProvider } from "styled-components";
|
||||
|
|
@ -228,7 +228,7 @@ class Editor extends Component<Props> {
|
|||
<RepoLimitExceededErrorModal />
|
||||
</GlobalHotKeys>
|
||||
</div>
|
||||
<ConfirmRunModal />
|
||||
<RequestConfirmationModal />
|
||||
</DndProvider>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -197,6 +197,14 @@ const datasourceReducer = createReducer(initialState, {
|
|||
),
|
||||
};
|
||||
},
|
||||
[ReduxActionTypes.DELETE_DATASOURCE_CANCELLED]: (
|
||||
state: DatasourceDataState,
|
||||
) => {
|
||||
return {
|
||||
...state,
|
||||
isDeleting: false,
|
||||
};
|
||||
},
|
||||
[ReduxActionTypes.CREATE_DATASOURCE_SUCCESS]: (
|
||||
state: DatasourceDataState,
|
||||
action: ReduxAction<Datasource>,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const initialState: ConfirmRunActionReduxState = {
|
|||
};
|
||||
|
||||
const confirmRunActionReducer = createReducer(initialState, {
|
||||
[ReduxActionTypes.SHOW_RUN_ACTION_CONFIRM_MODAL]: (
|
||||
[ReduxActionTypes.SHOW_ACTION_MODAL]: (
|
||||
state: ConfirmRunActionReduxState,
|
||||
action: ReduxAction<boolean>,
|
||||
) => {
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ const explorerReducer = createReducer(initialState, {
|
|||
[ReduxActionTypes.DELETE_DATASOURCE_INIT]: setUpdatingDatasourceEntity,
|
||||
[ReduxActionErrorTypes.DELETE_DATASOURCE_ERROR]: setEntityUpdateError,
|
||||
[ReduxActionTypes.DELETE_DATASOURCE_SUCCESS]: setEntityUpdateSuccess,
|
||||
[ReduxActionTypes.DELETE_DATASOURCE_CANCELLED]: setEntityUpdateSuccess,
|
||||
|
||||
[ReduxActionTypes.UPDATE_DATASOURCE_INIT]: setUpdatingDatasourceEntity,
|
||||
[ReduxActionErrorTypes.UPDATE_DATASOURCE_ERROR]: setEntityUpdateError,
|
||||
|
|
|
|||
|
|
@ -1,18 +1,9 @@
|
|||
import {
|
||||
all,
|
||||
call,
|
||||
put,
|
||||
race,
|
||||
select,
|
||||
take,
|
||||
takeLatest,
|
||||
} from "redux-saga/effects";
|
||||
import { all, call, put, select, take, takeLatest } from "redux-saga/effects";
|
||||
import {
|
||||
executePluginActionError,
|
||||
executePluginActionRequest,
|
||||
executePluginActionSuccess,
|
||||
runAction,
|
||||
showRunActionConfirmModal,
|
||||
updateAction,
|
||||
} from "actions/pluginActionActions";
|
||||
import {
|
||||
|
|
@ -102,6 +93,7 @@ import {
|
|||
executeAppAction,
|
||||
TriggerMeta,
|
||||
} from "sagas/ActionExecution/ActionExecutionSagas";
|
||||
import { requestModalConfirmationSaga } from "sagas/UtilSagas";
|
||||
|
||||
enum ActionResponseDataTypes {
|
||||
BINARY = "BINARY",
|
||||
|
|
@ -237,17 +229,6 @@ function* evaluateActionParams(
|
|||
return mapToPropList(actionParams);
|
||||
}
|
||||
|
||||
function* confirmRunActionSaga() {
|
||||
yield put(showRunActionConfirmModal(true));
|
||||
|
||||
const { accept } = yield race({
|
||||
cancel: take(ReduxActionTypes.CANCEL_RUN_ACTION_CONFIRM_MODAL),
|
||||
accept: take(ReduxActionTypes.ACCEPT_RUN_ACTION_CONFIRM_MODAL),
|
||||
});
|
||||
|
||||
return !!accept;
|
||||
}
|
||||
|
||||
export default function* executePluginActionTriggerSaga(
|
||||
pluginAction: RunPluginActionDescription["payload"],
|
||||
eventType: EventType,
|
||||
|
|
@ -700,7 +681,7 @@ function* executePluginActionSaga(
|
|||
}
|
||||
|
||||
if (pluginAction.confirmBeforeExecute) {
|
||||
const confirmed = yield call(confirmRunActionSaga);
|
||||
const confirmed = yield call(requestModalConfirmationSaga);
|
||||
if (!confirmed) {
|
||||
yield put({
|
||||
type: ReduxActionTypes.RUN_ACTION_CANCELLED,
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ import { inGuidedTour } from "selectors/onboardingSelectors";
|
|||
import { updateReplayEntity } from "actions/pageActions";
|
||||
import OAuthApi from "api/OAuthApi";
|
||||
import { AppState } from "reducers";
|
||||
import { requestModalConfirmationSaga } from "sagas/UtilSagas";
|
||||
|
||||
function* fetchDatasourcesSaga() {
|
||||
try {
|
||||
|
|
@ -212,6 +213,15 @@ export function* deleteDatasourceSaga(
|
|||
actionPayload: ReduxActionWithCallbacks<{ id: string }, unknown, unknown>,
|
||||
) {
|
||||
try {
|
||||
// request confirmation from user before deleting datasource.
|
||||
const confirmed = yield call(requestModalConfirmationSaga);
|
||||
|
||||
if (!confirmed) {
|
||||
return yield put({
|
||||
type: ReduxActionTypes.DELETE_DATASOURCE_CANCELLED,
|
||||
});
|
||||
}
|
||||
|
||||
const id = actionPayload.payload.id;
|
||||
const response: GenericApiResponse<Datasource> = yield DatasourcesApi.deleteDatasource(
|
||||
id,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { all, takeEvery } from "redux-saga/effects";
|
||||
import { all, takeEvery, race, put, take } from "redux-saga/effects";
|
||||
import { ReduxAction, ReduxActionTypes } from "constants/ReduxActionConstants";
|
||||
import history from "utils/history";
|
||||
import { showActionConfirmationModal } from "actions/pluginActionActions";
|
||||
|
||||
function* redirectWindowLocationSaga(
|
||||
actionPayload: ReduxAction<{ url: string }>,
|
||||
|
|
@ -21,3 +22,14 @@ export default function* root() {
|
|||
),
|
||||
]);
|
||||
}
|
||||
|
||||
export function* requestModalConfirmationSaga() {
|
||||
yield put(showActionConfirmationModal(true));
|
||||
|
||||
const { accept } = yield race({
|
||||
cancel: take(ReduxActionTypes.CANCEL_ACTION_MODAL),
|
||||
accept: take(ReduxActionTypes.CONFIRM_ACTION_MODAL),
|
||||
});
|
||||
|
||||
return !!accept;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user