diff --git a/app/client/src/actions/crudInfoModalActions.ts b/app/client/src/actions/crudInfoModalActions.ts index 2dd88b7874..484507a74e 100644 --- a/app/client/src/actions/crudInfoModalActions.ts +++ b/app/client/src/actions/crudInfoModalActions.ts @@ -1,6 +1,14 @@ import { ReduxActionTypes } from "constants/ReduxActionConstants"; -export const setCrudInfoModalOpen = (payload: boolean) => { +export type SetCrudInfoModalOpenPayload = { + open: boolean; + generateCRUDSuccessInfo?: { + successImageUrl: string; + successMessage: string; + }; +}; + +export const setCrudInfoModalData = (payload: SetCrudInfoModalOpenPayload) => { return { type: ReduxActionTypes.SET_CRUD_INFO_MODAL_OPEN, payload, diff --git a/app/client/src/actions/pageActions.tsx b/app/client/src/actions/pageActions.tsx index bdd0b56dc2..0505709eca 100644 --- a/app/client/src/actions/pageActions.tsx +++ b/app/client/src/actions/pageActions.tsx @@ -319,25 +319,20 @@ export interface ReduxActionWithExtraParams extends ReduxAction { extraParams: Record; } -export const generateTemplateSuccess = ({ - isNewPage, - layoutId, - pageId, - pageName, -}: { - layoutId: string; - pageId: string; - pageName: string; +export type GenerateCRUDSuccess = { + page: { + layouts: Array; + id: string; + name: string; + isDefault?: boolean; + }; isNewPage: boolean; -}) => { +}; + +export const generateTemplateSuccess = (payload: GenerateCRUDSuccess) => { return { type: ReduxActionTypes.GENERATE_TEMPLATE_PAGE_SUCCESS, - payload: { - layoutId, - pageId, - pageName, - isNewPage, - }, + payload, }; }; diff --git a/app/client/src/constants/messages.ts b/app/client/src/constants/messages.ts index 50d7a316d0..e278da2c47 100644 --- a/app/client/src/constants/messages.ts +++ b/app/client/src/constants/messages.ts @@ -395,11 +395,13 @@ export const GENERATE_PAGE_ACTION_SUBTITLE = () => export const GENERATE_PAGE_FORM_TITLE = () => "Generate from Data"; -export const GEN_CRUD_INFO_DIALOG_HEADING = () => +export const GEN_CRUD_SUCCESS_MESSAGE = () => "Hurray! Your application is ready to use."; +export const GEN_CRUD_SUCCESS_DESC = () => + "Search through your data in the table and update it using the form"; export const GEN_CRUD_INFO_DIALOG_TITLE = () => "How it works?"; export const GEN_CRUD_INFO_DIALOG_SUBTITLE = () => - "Search through your data in the table and update it using the form."; + "CRUD page is generated from selected datasource. You can use the Form to modify the data. Since all your data is already connected you can add more queries and modify the bindings"; // Actions Right pane export const SEE_CONNECTED_ENTITIES = () => "See all connected entities"; diff --git a/app/client/src/pages/Editor/GeneratePage/components/CrudInfoModal.tsx b/app/client/src/pages/Editor/GeneratePage/components/CrudInfoModal.tsx index ae23ff8e6c..578d2ef337 100644 --- a/app/client/src/pages/Editor/GeneratePage/components/CrudInfoModal.tsx +++ b/app/client/src/pages/Editor/GeneratePage/components/CrudInfoModal.tsx @@ -1,47 +1,43 @@ -import React from "react"; +import React, { useState, useEffect } from "react"; import styled from "styled-components"; import { connect, useDispatch } from "react-redux"; import { AppState } from "reducers"; import AnalyticsUtil from "utils/AnalyticsUtil"; import Button, { Category, Size } from "components/ads/Button"; import Text, { TextType } from "components/ads/Text"; -import { getCrudInfoModalOpen } from "selectors/crudInfoModalSelectors"; -import { setCrudInfoModalOpen } from "actions/crudInfoModalActions"; +import { getCrudInfoModalData } from "selectors/crudInfoModalSelectors"; +import { setCrudInfoModalData } from "actions/crudInfoModalActions"; import { Colors } from "constants/Colors"; import { S3_BUCKET_URL } from "constants/ThirdPartyConstants"; import Dialog from "components/ads/DialogComponent"; -import { GEN_CRUD_INFO_DIALOG_HEADING } from "../../../../constants/messages"; +import { GenerateCRUDSuccessInfoData } from "../../../../reducers/uiReducers/crudInfoModalReducer"; import { GEN_CRUD_INFO_DIALOG_SUBTITLE, - GEN_CRUD_INFO_DIALOG_TITLE, + GEN_CRUD_SUCCESS_MESSAGE, + GEN_CRUD_SUCCESS_DESC, + createMessage, } from "constants/messages"; +import { getTypographyByKey } from "constants/DefaultTheme"; type Props = { crudInfoModalOpen: boolean; + generateCRUDSuccessInfo: GenerateCRUDSuccessInfoData | null; }; -const HeaderContents = styled.div` - padding: ${(props) => props.theme.spaces[9]}px; - display: flex; - justify-content: space-between; - align-items: center; - padding-bottom: ${(props) => props.theme.spaces[7]}px; - background-color: ${Colors.FOAM}; -`; +const getSuccessGIF = () => `${S3_BUCKET_URL}/crud/check_mark_verified.gif`; const Heading = styled.div` - color: ${(props) => props.theme.colors.modal.headerText}; + color: ${Colors.CODE_GRAY}; display: flex; justify-content: center; font-size: 20px; line-height: 24px; - color: ${(props) => props.theme.colors.success.dark}; `; const ActionButtonWrapper = styled.div` display: flex; - justify-content: flex-end; + justify-content: center; margin: 30px 0px 0px; `; @@ -63,17 +59,22 @@ const Content = styled.div` flex-direction: column; `; +const Desc = styled.p` + ${(props) => getTypographyByKey(props, "p1")} + color: ${Colors.DOVE_GRAY2}; + margin-top: 8px; +`; + const Wrapper = styled.div` display: flex; flex-direction: column; height: 100%; - - .info-title { - font-weight: bold; - } + max-height: 700px; + min-height: 500px; .info-subtitle { padding-top: 5px; + text-align: center; } `; @@ -89,27 +90,83 @@ const ImageWrapper = styled.div` justify-content: center; `; -function Header() { +const SuccessContentWrapper = styled.div` + display: flex; + flex: 1; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; +`; + +const SuccessImage = styled.img` + margin: ${(props) => props.theme.spaces[6]}px; +`; + +const STEP = { + SHOW_SUCCESS_GIF: "show_success_gif", + SHOW_INFO: "show_info", +}; + +function InfoContent({ + onClose, + successMessage, +}: { + onClose: () => void; + successMessage: string; +}) { return ( - - {GEN_CRUD_INFO_DIALOG_HEADING()} - + <> + + + + + + + + + { + onClose(); + }} + size={Size.medium} + text="GOT IT" + /> + + ); } - const getInfoImage = (): string => `${S3_BUCKET_URL}/crud/working-flow-chart.png`; function GenCRUDSuccessModal(props: Props) { - const { crudInfoModalOpen } = props; + const { crudInfoModalOpen, generateCRUDSuccessInfo } = props; const dispatch = useDispatch(); + const [step, setStep] = useState(STEP.SHOW_SUCCESS_GIF); const onClose = () => { AnalyticsUtil.logEvent("CLOSE_GEN_PAGE_INFO_MODAL"); - dispatch(setCrudInfoModalOpen(false)); + dispatch(setCrudInfoModalData({ open: false })); }; + const successMessage = + (generateCRUDSuccessInfo && generateCRUDSuccessInfo.successMessage) || + createMessage(GEN_CRUD_INFO_DIALOG_SUBTITLE); + + useEffect(() => { + setTimeout(() => { + setStep(STEP.SHOW_INFO); + }, 2000); + }, [setStep]); + return ( -
- - - {GEN_CRUD_INFO_DIALOG_TITLE()} - - - - {GEN_CRUD_INFO_DIALOG_SUBTITLE()} - - - - - - - - { - onClose(); - }} - size={Size.medium} - text="GOT IT" - /> - + {step === STEP.SHOW_SUCCESS_GIF ? ( + + + {createMessage(GEN_CRUD_SUCCESS_MESSAGE)} + {createMessage(GEN_CRUD_SUCCESS_DESC)} + + ) : null} + {step === STEP.SHOW_INFO ? ( + + ) : null}
); } const mapStateToProps = (state: AppState) => ({ - crudInfoModalOpen: getCrudInfoModalOpen(state), + crudInfoModalOpen: getCrudInfoModalData(state).crudInfoModalOpen, + generateCRUDSuccessInfo: getCrudInfoModalData(state).generateCRUDSuccessInfo, }); export default connect(mapStateToProps)(GenCRUDSuccessModal); diff --git a/app/client/src/reducers/entityReducers/pageListReducer.tsx b/app/client/src/reducers/entityReducers/pageListReducer.tsx index 3e6111a973..56cb03e15b 100644 --- a/app/client/src/reducers/entityReducers/pageListReducer.tsx +++ b/app/client/src/reducers/entityReducers/pageListReducer.tsx @@ -7,6 +7,7 @@ import { ReduxActionErrorTypes, } from "constants/ReduxActionConstants"; import { createReducer } from "utils/AppsmithUtils"; +import { GenerateCRUDSuccess } from "actions/pageActions"; const initialState: PageListReduxState = { pages: [], @@ -114,27 +115,24 @@ export const pageListReducer = createReducer(initialState, { }, [ReduxActionTypes.GENERATE_TEMPLATE_PAGE_SUCCESS]: ( state: PageListReduxState, - action: ReduxAction<{ - pageName: string; - pageId: string; - layoutId: string; - isDefault: boolean; - isNewPage: boolean; - }>, + action: ReduxAction, ) => { const _state = state; if (action.payload.isNewPage) { _state.pages = state.pages.map((page) => ({ ...page, latest: false })); const newPage = { - pageName: action.payload.pageName, - pageId: action.payload.pageId, - layoutId: action.payload.layoutId, - isDefault: action.payload.isDefault, + pageName: action.payload.page.name, + pageId: action.payload.page.id, + layoutId: action.payload.page.layouts[0].id, + isDefault: !!action.payload.page.isDefault, }; _state.pages.push({ ...newPage, latest: true }); } - return { ..._state, isGeneratingTemplatePage: false }; + return { + ..._state, + isGeneratingTemplatePage: false, + }; }, [ReduxActionErrorTypes.GENERATE_TEMPLATE_PAGE_ERROR]: ( state: PageListReduxState, diff --git a/app/client/src/reducers/uiReducers/crudInfoModalReducer.ts b/app/client/src/reducers/uiReducers/crudInfoModalReducer.ts index e460553cc9..e006481f43 100644 --- a/app/client/src/reducers/uiReducers/crudInfoModalReducer.ts +++ b/app/client/src/reducers/uiReducers/crudInfoModalReducer.ts @@ -1,21 +1,33 @@ import { createReducer } from "utils/AppsmithUtils"; import { ReduxAction, ReduxActionTypes } from "constants/ReduxActionConstants"; +import { SetCrudInfoModalOpenPayload } from "actions/crudInfoModalActions"; const initialState: CrudInfoModalReduxState = { crudInfoModalOpen: false, + generateCRUDSuccessInfo: null, }; const crudInfoModalReducer = createReducer(initialState, { [ReduxActionTypes.SET_CRUD_INFO_MODAL_OPEN]: ( state: CrudInfoModalReduxState, - action: ReduxAction, + action: ReduxAction, ) => { - return { ...state, crudInfoModalOpen: action.payload }; + return { + ...state, + crudInfoModalOpen: action.payload.open, + generateCRUDSuccessInfo: action.payload.generateCRUDSuccessInfo, + }; }, }); +export type GenerateCRUDSuccessInfoData = { + successImageUrl: string; + successMessage: string; +}; + export interface CrudInfoModalReduxState { crudInfoModalOpen: boolean; + generateCRUDSuccessInfo: GenerateCRUDSuccessInfoData | null; } export default crudInfoModalReducer; diff --git a/app/client/src/sagas/PageSagas.tsx b/app/client/src/sagas/PageSagas.tsx index 6b680ad734..d06a53e777 100644 --- a/app/client/src/sagas/PageSagas.tsx +++ b/app/client/src/sagas/PageSagas.tsx @@ -67,7 +67,7 @@ import { import { getDataTree } from "selectors/dataTreeSelectors"; import { IncorrectBindingError, validateResponse } from "./ErrorSagas"; import { executePageLoadActions } from "actions/widgetActions"; -import { ApiResponse } from "api/ApiResponses"; +import { ApiResponse, GenericApiResponse } from "api/ApiResponses"; import { getCurrentApplicationId, getCurrentLayoutId, @@ -101,7 +101,7 @@ import { generateTemplateSuccess, } from "../actions/pageActions"; import { getAppMode } from "selectors/applicationSelectors"; -import { setCrudInfoModalOpen } from "actions/crudInfoModalActions"; +import { setCrudInfoModalData } from "actions/crudInfoModalActions"; import { selectMultipleWidgetsAction } from "actions/widgetSelectionActions"; const getWidgetName = (state: AppState, widgetId: string) => @@ -898,26 +898,29 @@ export function* generateTemplatePageSaga( try { const request: GenerateTemplatePageRequest = action.payload; // if pageId is available in request, it will just update that page else it will generate new page. - const response: ApiResponse = yield call( - PageApi.generateTemplatePage, - request, - ); + const response: GenericApiResponse<{ + page: any; + successImageUrl: string; + successMessage: string; + }> = yield call(PageApi.generateTemplatePage, request); const isValidResponse: boolean = yield validateResponse(response); if (isValidResponse) { - const pageId = response.data.id; + const pageId = response.data.page.id; const applicationId = - response.data.applicationId || request.applicationId; + response.data.page.applicationId || request.applicationId; yield handleFetchedPage({ - fetchPageResponse: response, + fetchPageResponse: { + data: response.data.page, + responseMeta: response.responseMeta, + }, pageId, }); + // TODO : Add this to onSuccess (Redux Action) yield put( generateTemplateSuccess({ - pageId: response.data.id, - pageName: response.data.name, - layoutId: response.data.layouts[0].id, + page: response.data.page, isNewPage: !request.pageId, // if pageId if not defined, that means a new page is generated. }), ); @@ -931,7 +934,15 @@ export function* generateTemplatePageSaga( variant: Variant.success, }); - yield put(setCrudInfoModalOpen(true)); + yield put( + setCrudInfoModalData({ + open: true, + generateCRUDSuccessInfo: { + successImageUrl: response.data.successImageUrl, + successMessage: response.data.successMessage, + }, + }), + ); } } catch (error) { yield put(generateTemplateError()); diff --git a/app/client/src/selectors/crudInfoModalSelectors.ts b/app/client/src/selectors/crudInfoModalSelectors.ts index c2667b9812..8a89449fa1 100644 --- a/app/client/src/selectors/crudInfoModalSelectors.ts +++ b/app/client/src/selectors/crudInfoModalSelectors.ts @@ -1,4 +1,24 @@ import { AppState } from "reducers"; +import { createSelector } from "reselect"; +import { + CrudInfoModalReduxState, + GenerateCRUDSuccessInfoData, +} from "reducers/uiReducers/crudInfoModalReducer"; -export const getCrudInfoModalOpen = (state: AppState): boolean => - state.ui.crudInfoModal.crudInfoModalOpen; +export type CrudInfoModalData = { + crudInfoModalOpen: boolean; + generateCRUDSuccessInfo: GenerateCRUDSuccessInfoData | null; +}; + +const getCrudInfoModalState = (state: AppState): CrudInfoModalReduxState => + state.ui.crudInfoModal; + +export const getCrudInfoModalData = createSelector( + getCrudInfoModalState, + (crudInfoModal) => { + return { + crudInfoModalOpen: crudInfoModal.crudInfoModalOpen, + generateCRUDSuccessInfo: crudInfoModal.generateCRUDSuccessInfo, + }; + }, +); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/Resources.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/Resources.java new file mode 100644 index 0000000000..588daaa0ea --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/constants/Resources.java @@ -0,0 +1,7 @@ +package com.appsmith.server.constants; + +public class Resources { + + public static final String GENERATE_CRUD_PAGE_SUCCESS_URL_TABULAR = "https://assets.appsmith.com/crud/working-flow-chart.png"; + +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/PageController.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/PageController.java index 93af1e2d62..ec531c59f1 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/PageController.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/PageController.java @@ -3,6 +3,7 @@ package com.appsmith.server.controllers; import com.appsmith.server.constants.Url; import com.appsmith.server.dtos.ApplicationPagesDTO; import com.appsmith.server.dtos.CRUDPageResourceDTO; +import com.appsmith.server.dtos.CRUDPageResponseDTO; import com.appsmith.server.dtos.PageDTO; import com.appsmith.server.dtos.ResponseDTO; import com.appsmith.server.services.ApplicationPageService; @@ -57,7 +58,7 @@ public class PageController { @PostMapping("/crud-page") @ResponseStatus(HttpStatus.CREATED) - public Mono> createCRUDPage(@RequestBody @NonNull CRUDPageResourceDTO resource) { + public Mono> createCRUDPage(@RequestBody @NonNull CRUDPageResourceDTO resource) { log.debug("Going to create crud-page"); return createDBTablePageSolution.createPageFromDBTable(null, resource) .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); @@ -65,8 +66,8 @@ public class PageController { @PutMapping("/crud-page/{pageId}") @ResponseStatus(HttpStatus.OK) - public Mono> createCRUDPage(@PathVariable String pageId, - @NonNull @RequestBody CRUDPageResourceDTO resource) { + public Mono> createCRUDPage(@PathVariable String pageId, + @NonNull @RequestBody CRUDPageResourceDTO resource) { log.debug("Going to update resource {}", pageId); return createDBTablePageSolution.createPageFromDBTable(pageId, resource) .map(created -> new ResponseDTO<>(HttpStatus.CREATED.value(), created, null)); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/CRUDPageResponseDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/CRUDPageResponseDTO.java new file mode 100644 index 0000000000..0deec432a0 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/CRUDPageResponseDTO.java @@ -0,0 +1,24 @@ +package com.appsmith.server.dtos; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +/** + * This class will hold the fields that will be consumed by the client after the successful CRUD page generation + */ +@NoArgsConstructor +@Getter +@Setter +public class CRUDPageResponseDTO { + + PageDTO page; + + // This field will give some guidelines how to interact with the widgets on the canvas created by CreateDBTablePageSolution + // e.g. We have generated the table from Datasource. You can use the Form> to modify it. Since all your data is + // already connected you can add more queries and modify the bindings + String successMessage; + + // This field will be used to display the image on how to use the template application + String successImageUrl; +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/CreateDBTablePageSolution.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/CreateDBTablePageSolution.java index 41f83ee802..d7593cc08b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/CreateDBTablePageSolution.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/CreateDBTablePageSolution.java @@ -11,6 +11,7 @@ import com.appsmith.server.acl.AclPermission; import com.appsmith.server.constants.AnalyticsEvents; import com.appsmith.server.constants.Entity; import com.appsmith.server.constants.FieldName; +import com.appsmith.server.constants.Resources; import com.appsmith.server.domains.ApplicationJson; import com.appsmith.server.domains.Datasource; import com.appsmith.server.domains.Layout; @@ -19,6 +20,7 @@ import com.appsmith.server.domains.NewPage; import com.appsmith.server.domains.Plugin; import com.appsmith.server.dtos.ActionDTO; import com.appsmith.server.dtos.CRUDPageResourceDTO; +import com.appsmith.server.dtos.CRUDPageResponseDTO; import com.appsmith.server.dtos.PageDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; @@ -119,7 +121,7 @@ public class CreateDBTablePageSolution { * @param pageResourceDTO * @return generated pageDTO from the template resource */ - public Mono createPageFromDBTable(String pageId, CRUDPageResourceDTO pageResourceDTO) { + public Mono createPageFromDBTable(String pageId, CRUDPageResourceDTO pageResourceDTO) { /* 1. Fetch page from the application @@ -349,7 +351,14 @@ public class CreateDBTablePageSolution { || StringUtils.equals(actionDTO.getName(), LIST_QUERY) ? layoutActionService.setExecuteOnLoad(actionDTO.getId(), true) : Mono.just(actionDTO)) .then(applicationPageService.getPage(savedPageId, false) - .flatMap(pageDTO -> sendGenerateCRUDPageAnalyticsEvent(pageDTO, datasource, plugin.getName())) + .flatMap(pageDTO -> { + CRUDPageResponseDTO crudPage = new CRUDPageResponseDTO(); + crudPage.setPage(pageDTO); + crudPage.setSuccessMessage(createSuccessMessage(plugin)); + // Update the S3 image once received + crudPage.setSuccessImageUrl(Resources.GENERATE_CRUD_PAGE_SUCCESS_URL_TABULAR); + return sendGenerateCRUDPageAnalyticsEvent(crudPage, datasource, plugin.getName()); + }) ); }); } @@ -881,7 +890,21 @@ public class CreateDBTablePageSolution { return actionConfiguration; } - private Mono sendGenerateCRUDPageAnalyticsEvent(PageDTO page, Datasource datasource, String pluginName) { + private String createSuccessMessage(Plugin plugin) { + + String displayWidget = Entity.S3_PLUGIN_PACKAGE_NAME.equals(plugin.getPackageName()) ? "LIST" : "TABLE"; + String updateWidget = Entity.S3_PLUGIN_PACKAGE_NAME.equals(plugin.getPackageName()) ? "FILEPICKER" : "FORM"; + + // Field used to send success message after the successful page creation + String successMessage = "We have generated the " + displayWidget + " from the " + plugin.getName() + + " Datasource. You can use the " + updateWidget + " to modify it. Since all your " + + "data is already connected you can add more queries and modify the bindings"; + + return successMessage; + } + + private Mono sendGenerateCRUDPageAnalyticsEvent(CRUDPageResponseDTO crudPage, Datasource datasource, String pluginName) { + PageDTO page = crudPage.getPage(); return sessionUserService.getCurrentUser() .map(currentUser -> { try { @@ -897,7 +920,7 @@ public class CreateDBTablePageSolution { } catch (Exception e) { log.warn("Error sending generate CRUD DB table page data point", e); } - return page; + return crudPage; }); } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/CreateDBTablePageSolutionTests.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/CreateDBTablePageSolutionTests.java index 80ba76de0e..b373646191 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/CreateDBTablePageSolutionTests.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/CreateDBTablePageSolutionTests.java @@ -16,6 +16,7 @@ import com.appsmith.server.domains.NewAction; import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.Plugin; import com.appsmith.server.dtos.CRUDPageResourceDTO; +import com.appsmith.server.dtos.CRUDPageResponseDTO; import com.appsmith.server.dtos.PageDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; @@ -182,7 +183,7 @@ public class CreateDBTablePageSolutionTests { @WithUserDetails(value = "api_user") public void createPageWithInvalidApplicationIdTest() { - Mono resultMono = solution.createPageFromDBTable(testApp.getPages().get(0).getId(), resource); + Mono resultMono = solution.createPageFromDBTable(testApp.getPages().get(0).getId(), resource); StepVerifier .create(resultMono) @@ -202,7 +203,7 @@ public class CreateDBTablePageSolutionTests { invalidDatasource.setDatasourceConfiguration(new DatasourceConfiguration()); resource.setDatasourceId(invalidDatasource.getId()); - Mono resultMono = datasourceService.create(invalidDatasource) + Mono resultMono = datasourceService.create(invalidDatasource) .flatMap(datasource -> { resource.setApplicationId(testApp.getId()); resource.setDatasourceId(datasource.getId()); @@ -220,7 +221,7 @@ public class CreateDBTablePageSolutionTests { @Test @WithUserDetails(value = "api_user") public void createPageWithInvalidRequestBodyTest() { - Mono resultMono = solution.createPageFromDBTable(testApp.getPages().get(0).getId(), new CRUDPageResourceDTO()); + Mono resultMono = solution.createPageFromDBTable(testApp.getPages().get(0).getId(), new CRUDPageResourceDTO()); StepVerifier .create(resultMono) @@ -234,11 +235,12 @@ public class CreateDBTablePageSolutionTests { public void createPageWithNullPageId() { resource.setApplicationId(testApp.getId()); - Mono resultMono = solution.createPageFromDBTable(null, resource); + Mono resultMono = solution.createPageFromDBTable(null, resource); StepVerifier .create(resultMono) - .assertNext(page -> { + .assertNext(crudPage -> { + PageDTO page = crudPage.getPage(); Layout layout = page.getLayouts().get(0); assertThat(page.getName()).isEqualTo("SampleTable"); assertThat(page.getLayouts()).isNotEmpty(); @@ -249,6 +251,8 @@ public class CreateDBTablePageSolutionTests { assertThat(layout.getActionsUsedInDynamicBindings()).isNotEmpty(); assertThat(layout.getDsl().get("children").toString().replaceAll(specialCharactersRegex, "")) .containsIgnoringCase(dropdownOptions.replaceAll(specialCharactersRegex, "")); + assertThat(crudPage.getSuccessMessage()).isNotNull(); + assertThat(crudPage.getSuccessImageUrl()).isNotNull(); }) .verifyComplete(); } @@ -263,7 +267,8 @@ public class CreateDBTablePageSolutionTests { newPage.setName("crud-admin-page"); Mono resultMono = applicationPageService.createPage(newPage) - .flatMap(savedPage -> solution.createPageFromDBTable(savedPage.getId(), resource)); + .flatMap(savedPage -> solution.createPageFromDBTable(savedPage.getId(), resource)) + .map(crudPageResponseDTO -> crudPageResponseDTO.getPage()); StepVerifier .create(resultMono.zipWhen(pageDTO -> getActions(pageDTO.getId()))) @@ -303,9 +308,11 @@ public class CreateDBTablePageSolutionTests { PageDTO newPage = new PageDTO(); newPage.setApplicationId(testApp.getId()); newPage.setName("crud-admin-page-mysql"); + StringBuilder pluginName = new StringBuilder(); Mono datasourceMono = pluginRepository.findByName("Mysql") .flatMap(plugin -> { + pluginName.append(plugin.getName()); Datasource datasource = new Datasource(); datasource.setPluginId(plugin.getId()); datasource.setOrganizationId(testOrg.getId()); @@ -315,7 +322,7 @@ public class CreateDBTablePageSolutionTests { return datasourceService.create(datasource); }); - Mono resultMono = datasourceMono + Mono resultMono = datasourceMono .flatMap(datasource1 -> { resource.setDatasourceId(datasource1.getId()); return applicationPageService.createPage(newPage); @@ -323,9 +330,10 @@ public class CreateDBTablePageSolutionTests { .flatMap(savedPage -> solution.createPageFromDBTable(savedPage.getId(), resource)); StepVerifier - .create(resultMono.zipWhen(pageDTO -> getActions(pageDTO.getId()))) + .create(resultMono.zipWhen(crudPageResponseDTO -> getActions(crudPageResponseDTO.getPage().getId()))) .assertNext(tuple -> { - PageDTO page = tuple.getT1(); + CRUDPageResponseDTO crudPageResponseDTO = tuple.getT1(); + PageDTO page = crudPageResponseDTO.getPage(); List actions = tuple.getT2(); Layout layout = page.getLayouts().get(0); assertThat(page.getName()).isEqualTo(newPage.getName()); @@ -351,6 +359,9 @@ public class CreateDBTablePageSolutionTests { assertThat(action.getUnpublishedAction().getExecuteOnLoad()).isFalse(); } } + assertThat(crudPageResponseDTO.getSuccessMessage()).containsIgnoringCase(pluginName); + assertThat(crudPageResponseDTO.getSuccessMessage()).containsIgnoringCase("TABLE"); + assertThat(crudPageResponseDTO.getSuccessImageUrl()).isNotNull(); }) .verifyComplete(); } @@ -380,7 +391,8 @@ public class CreateDBTablePageSolutionTests { resource.setDatasourceId(datasource1.getId()); return applicationPageService.createPage(newPage); }) - .flatMap(savedPage -> solution.createPageFromDBTable(savedPage.getId(), resource)); + .flatMap(savedPage -> solution.createPageFromDBTable(savedPage.getId(), resource)) + .map(crudPageResponseDTO -> crudPageResponseDTO.getPage()); StepVerifier .create(resultMono.zipWhen(pageDTO -> getActions(pageDTO.getId()))) @@ -433,7 +445,8 @@ public class CreateDBTablePageSolutionTests { .flatMap(datasource1 -> { resource.setDatasourceId(datasource1.getId()); return solution.createPageFromDBTable(null, resource); - }); + }) + .map(crudPageResponseDTO -> crudPageResponseDTO.getPage()); StepVerifier .create(resultMono.zipWhen(pageDTO -> getActions(pageDTO.getId()))) @@ -486,7 +499,8 @@ public class CreateDBTablePageSolutionTests { .flatMap(datasource1 -> { resource.setDatasourceId(datasource1.getId()); return solution.createPageFromDBTable(null, resource); - }); + }) + .map(crudPageResponseDTO -> crudPageResponseDTO.getPage()); StepVerifier .create(resultMono.zipWhen(pageDTO -> getActions(pageDTO.getId()))) @@ -522,6 +536,7 @@ public class CreateDBTablePageSolutionTests { public void createPageWithNullPageIdForS3() { resource.setApplicationId(testApp.getId()); + StringBuilder pluginName = new StringBuilder(); Mono datasourceMono = pluginRepository.findByName("S3") .flatMap(plugin -> { @@ -530,19 +545,21 @@ public class CreateDBTablePageSolutionTests { datasource.setOrganizationId(testOrg.getId()); datasource.setName("S3-CRUD-Page-Table-DS"); datasource.setDatasourceConfiguration(datasourceConfiguration); + pluginName.append(plugin.getName()); return datasourceService.create(datasource); }); - Mono resultMono = datasourceMono + Mono resultMono = datasourceMono .flatMap(datasource1 -> { resource.setDatasourceId(datasource1.getId()); return solution.createPageFromDBTable(null, resource); }); StepVerifier - .create(resultMono.zipWhen(pageDTO -> getActions(pageDTO.getId()))) + .create(resultMono.zipWhen(crudPageResponseDTO -> getActions(crudPageResponseDTO.getPage().getId()))) .assertNext(tuple -> { - PageDTO page = tuple.getT1(); + CRUDPageResponseDTO crudPage = tuple.getT1(); + PageDTO page = crudPage.getPage(); List actions = tuple.getT2(); Layout layout = page.getLayouts().get(0); assertThat(page.getName()).isEqualTo("SampleTable"); @@ -561,6 +578,9 @@ public class CreateDBTablePageSolutionTests { assertThat(actionConfiguration.getPluginSpecifiedTemplates().get(1).getValue().toString()) .isEqualTo(resource.getTableName()); } + + assertThat(crudPage.getSuccessMessage()).containsIgnoringCase(pluginName); + assertThat(crudPage.getSuccessMessage()).containsIgnoringCase("LIST"); }) .verifyComplete(); } @@ -596,7 +616,8 @@ public class CreateDBTablePageSolutionTests { resource.setDatasourceId(datasource1.getId()); return applicationPageService.createPage(newPage); }) - .flatMap(savedPage -> solution.createPageFromDBTable(savedPage.getId(), resource)); + .flatMap(savedPage -> solution.createPageFromDBTable(savedPage.getId(), resource)) + .map(crudPageResponseDTO -> crudPageResponseDTO.getPage()); StepVerifier .create(resultMono.zipWhen(pageDTO -> getActions(pageDTO.getId()))) @@ -656,7 +677,8 @@ public class CreateDBTablePageSolutionTests { resource.setDatasourceId(datasource1.getId()); return applicationPageService.createPage(newPage); }) - .flatMap(savedPage -> solution.createPageFromDBTable(savedPage.getId(), resource)); + .flatMap(savedPage -> solution.createPageFromDBTable(savedPage.getId(), resource)) + .map(crudPageResponseDTO -> crudPageResponseDTO.getPage()); StepVerifier .create(resultMono.zipWhen(pageDTO -> getActions(pageDTO.getId())))