Feature: New create app flow (#1375)
* EditableTextWrapper component implemented * create new app flow implemented * test cases for new create new app flow fixed * role update element fixed * before-all hooks fixed * createOrg test cases fixed * loading state test added * editableText input unique identifier added in test-cases * updateApplication API alias name corrected * removed the second className prop on same component * PR feedback implemented
This commit is contained in:
parent
5c26ef5d07
commit
7d6a70d3ce
|
|
@ -29,7 +29,9 @@ describe("Create new org and share with a user", function() {
|
|||
cy.wait(2000);
|
||||
cy.get(homePage.appsContainer).contains(orgid);
|
||||
cy.xpath(homePage.ShareBtn).should("not.exist");
|
||||
cy.get(homePage.applicationCard).trigger("mouseover");
|
||||
cy.get(homePage.applicationCard)
|
||||
.first()
|
||||
.trigger("mouseover");
|
||||
cy.get(homePage.appEditIcon).should("not.exist");
|
||||
cy.launchApp(appid);
|
||||
cy.LogOut();
|
||||
|
|
@ -62,7 +64,9 @@ describe("Create new org and share with a user", function() {
|
|||
cy.xpath(homePage.ShareBtn)
|
||||
.first()
|
||||
.should("be.visible");
|
||||
cy.get(homePage.applicationCard).trigger("mouseover");
|
||||
cy.get(homePage.applicationCard)
|
||||
.first()
|
||||
.trigger("mouseover");
|
||||
cy.get(homePage.appEditIcon)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"createBlankApiCard": ".t--createBlankApiCard",
|
||||
"eachProviderCard": ".t--eachProviderCard",
|
||||
"nameOfApi": ".t--nameOfApi",
|
||||
"ApiNameField": ".bp3-editable-text",
|
||||
"ApiNameField": ".t--action-name-edit-field",
|
||||
"addToPageBtn": ".t--addToPageBtn",
|
||||
"ApiDeleteBtn": ".t--apiFormDeleteBtn",
|
||||
"ApiRunBtn": ".t--apiFormRunBtn",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"viewWidgets": ".t--page-sidebar-ViewWidgets",
|
||||
"widgetsEditor": ".t--nav-link-widgets-editor",
|
||||
"AddPage": ".pages .t--entity-add-btn",
|
||||
"editInput": "input.bp3-editable-text-input",
|
||||
"editInput": ".t--entity-name.editing",
|
||||
"Menuaction": ".bp3-overlay-open>.bp3-transition-container",
|
||||
"Delete": ":nth-child(2) > .bp3-menu-item",
|
||||
"apiEditorIcon": ".t--nav-link-api-editor",
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
"labelTextStyle": ".bp3-ui-text span",
|
||||
"bodyTextStyle": ".bp3-running-text span",
|
||||
"headingTextStyle": ".bp3-heading span",
|
||||
"editWidgetName": ".bp3-editable-text",
|
||||
"editWidgetName": ".t--propery-page-title",
|
||||
"dropDownIcon": ".t--property-control-textstyle span.bp3-icon-chevron-down",
|
||||
"onDateSelectedField": ".t--property-control-ondateselected",
|
||||
"TableRow": ".t--draggable-tablewidget .tbody",
|
||||
|
|
|
|||
|
|
@ -214,28 +214,37 @@ Cypress.Commands.add("CreateAppForOrg", (orgName, appname) => {
|
|||
.scrollIntoView()
|
||||
.should("be.visible")
|
||||
.click();
|
||||
cy.get(homePage.inputAppName).type(appname);
|
||||
cy.get(homePage.CreateApp)
|
||||
.contains("Submit")
|
||||
.click({ force: true });
|
||||
cy.get("#loading").should("not.exist");
|
||||
cy.wait("@createNewApplication").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
201,
|
||||
);
|
||||
cy.wait(1000);
|
||||
cy.get(homePage.applicationName).type(appname + "{enter}");
|
||||
cy.wait("@updateApplication").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
200,
|
||||
);
|
||||
});
|
||||
|
||||
Cypress.Commands.add("CreateApp", appname => {
|
||||
cy.get(homePage.createNew)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
cy.get(homePage.inputAppName).type(appname);
|
||||
cy.get(homePage.CreateApp)
|
||||
.contains("Submit")
|
||||
.click({ force: true });
|
||||
cy.wait("@createNewApplication").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
201,
|
||||
);
|
||||
cy.get("#loading").should("not.exist");
|
||||
cy.wait("@getPagesForCreateApp").should(
|
||||
cy.wait(1000);
|
||||
cy.get(homePage.applicationName).type(appname + "{enter}");
|
||||
cy.wait("@updateApplication").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
200,
|
||||
);
|
||||
cy.get("h2").contains("Drag and drop a widget here");
|
||||
});
|
||||
|
||||
Cypress.Commands.add("DeleteApp", appName => {
|
||||
|
|
@ -301,7 +310,9 @@ Cypress.Commands.add("DeleteApp", appName => {
|
|||
cy.get(commonlocators.homeIcon).click({ force: true });
|
||||
cy.get(homePage.searchInput).type(appName);
|
||||
cy.wait(2000);
|
||||
cy.get(homePage.applicationCard).trigger("mouseover");
|
||||
cy.get(homePage.applicationCard)
|
||||
.first()
|
||||
.trigger("mouseover");
|
||||
cy.get(homePage.appMoreIcon)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
|
|
@ -1787,15 +1798,3 @@ Cypress.Commands.add("callApi", apiname => {
|
|||
Cypress.Commands.add("assertPageSave", () => {
|
||||
cy.get(commonlocators.saveStatusSuccess);
|
||||
});
|
||||
|
||||
Cypress.Commands.add("EditApp", appName => {
|
||||
cy.get(homePage.searchInput).type(appName);
|
||||
cy.wait(2000);
|
||||
cy.get(homePage.applicationCard)
|
||||
.first()
|
||||
.trigger("mouseover");
|
||||
cy.get(homePage.appEditIcon)
|
||||
.first()
|
||||
.click({ force: true });
|
||||
cy.get("#loading").should("not.exist");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,28 +21,28 @@ export enum SavingState {
|
|||
ERROR = "ERROR",
|
||||
}
|
||||
|
||||
type EditableTextProps = CommonComponentProps & {
|
||||
export type EditableTextProps = CommonComponentProps & {
|
||||
defaultValue: string;
|
||||
onTextChanged: (value: string) => void;
|
||||
placeholder: string;
|
||||
placeholder?: string;
|
||||
editInteractionKind: EditInteractionKind;
|
||||
savingState: SavingState;
|
||||
onBlur: (value: string) => void;
|
||||
onTextChanged?: (value: string) => void;
|
||||
className?: string;
|
||||
valueTransform?: (value: string) => string;
|
||||
isEditingDefault?: boolean;
|
||||
forceDefault?: boolean;
|
||||
updating?: boolean;
|
||||
isInvalid?: (value: string) => string | boolean;
|
||||
editInteractionKind: EditInteractionKind;
|
||||
hideEditIcon?: boolean;
|
||||
fill?: boolean;
|
||||
savingState: SavingState;
|
||||
onBlur: (value: string) => void;
|
||||
};
|
||||
|
||||
const EditableTextWrapper = styled.div<{
|
||||
fill?: boolean;
|
||||
}>`
|
||||
width: ${props => (!props.fill ? "234px" : "100%")};
|
||||
.${Classes.TEXT} {
|
||||
.error-message {
|
||||
margin-left: ${props => props.theme.spaces[5]}px;
|
||||
color: ${props => props.theme.colors.danger.main};
|
||||
}
|
||||
|
|
@ -70,10 +70,6 @@ const TextContainer = styled.div<{
|
|||
}>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
${props =>
|
||||
props.isEditing && props.isInvalid
|
||||
? `margin-bottom: ${props.theme.spaces[2]}px`
|
||||
: null};
|
||||
.bp3-editable-text.bp3-editable-text-editing::before,
|
||||
.bp3-editable-text.bp3-disabled::before {
|
||||
display: none;
|
||||
|
|
@ -143,7 +139,6 @@ export const EditableText = (props: EditableTextProps) => {
|
|||
const [savingState, setSavingState] = useState<SavingState>(
|
||||
SavingState.NOT_STARTED,
|
||||
);
|
||||
const valueRef = React.useRef(defaultValue);
|
||||
|
||||
useEffect(() => {
|
||||
setSavingState(props.savingState);
|
||||
|
|
@ -178,14 +173,14 @@ export const EditableText = (props: EditableTextProps) => {
|
|||
|
||||
const onConfirm = useCallback(
|
||||
(_value: string) => {
|
||||
if (savingState === SavingState.ERROR || isInvalid) {
|
||||
if (savingState === SavingState.ERROR || isInvalid || _value === "") {
|
||||
setValue(lastValidValue);
|
||||
onBlur(lastValidValue);
|
||||
setSavingState(SavingState.NOT_STARTED);
|
||||
} else if (changeStarted) {
|
||||
onTextChanged(_value);
|
||||
onBlur(_value);
|
||||
onTextChanged && onTextChanged(_value);
|
||||
}
|
||||
onBlur(_value);
|
||||
setIsEditing(false);
|
||||
setChangeStarted(false);
|
||||
},
|
||||
|
|
@ -204,10 +199,9 @@ export const EditableText = (props: EditableTextProps) => {
|
|||
const finalVal: string = _value;
|
||||
const errorMessage = inputValidation && inputValidation(finalVal);
|
||||
const error = errorMessage ? errorMessage : false;
|
||||
if (!error) {
|
||||
if (!error && _value !== "") {
|
||||
setLastValidValue(finalVal);
|
||||
valueRef.current = finalVal;
|
||||
onTextChanged(finalVal);
|
||||
onTextChanged && onTextChanged(finalVal);
|
||||
}
|
||||
setValue(finalVal);
|
||||
setIsInvalid(error);
|
||||
|
|
@ -258,8 +252,8 @@ export const EditableText = (props: EditableTextProps) => {
|
|||
onChange={onInputchange}
|
||||
onConfirm={onConfirm}
|
||||
value={value}
|
||||
selectAllOnFocus
|
||||
placeholder={props.placeholder}
|
||||
selectAllOnFocus={true}
|
||||
placeholder={props.placeholder || defaultValue}
|
||||
className={props.className}
|
||||
onCancel={onConfirm}
|
||||
/>
|
||||
|
|
@ -267,13 +261,15 @@ export const EditableText = (props: EditableTextProps) => {
|
|||
<IconWrapper className="icon-wrapper">
|
||||
{savingState === SavingState.STARTED ? (
|
||||
<Spinner size={IconSize.XL} />
|
||||
) : (
|
||||
) : value ? (
|
||||
<Icon name={iconName} size={IconSize.XL} />
|
||||
)}
|
||||
) : null}
|
||||
</IconWrapper>
|
||||
</TextContainer>
|
||||
{isEditing && !!isInvalid ? (
|
||||
<Text type={TextType.P2}>{isInvalid}</Text>
|
||||
<Text className="error-message" type={TextType.P2}>
|
||||
{isInvalid}
|
||||
</Text>
|
||||
) : null}
|
||||
</EditableTextWrapper>
|
||||
);
|
||||
|
|
|
|||
82
app/client/src/components/ads/EditableTextWrapper.tsx
Normal file
82
app/client/src/components/ads/EditableTextWrapper.tsx
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import EditableText, { EditableTextProps, SavingState } from "./EditableText";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import { Classes } from "@blueprintjs/core";
|
||||
|
||||
type EditableTextWrapperProps = EditableTextProps & {
|
||||
variant: "UNDERLINE" | "ICON";
|
||||
isNewApp: boolean;
|
||||
};
|
||||
|
||||
const Container = styled.div<{
|
||||
isEditing?: boolean;
|
||||
savingState: SavingState;
|
||||
isInvalid: boolean;
|
||||
}>`
|
||||
&&& .${Classes.EDITABLE_TEXT}, .icon-wrapper {
|
||||
padding: 5px 10px;
|
||||
height: 25px;
|
||||
text-decoration: ${props => (props.isEditing ? "unset" : "underline")};
|
||||
text-decoration-style: dotted;
|
||||
background-color: ${props =>
|
||||
(props.isInvalid && props.isEditing) ||
|
||||
props.savingState === SavingState.ERROR
|
||||
? props.theme.colors.editableText.dangerBg
|
||||
: "transparent"};
|
||||
}
|
||||
|
||||
&&& .${Classes.EDITABLE_TEXT_CONTENT}, &&& .${Classes.EDITABLE_TEXT_INPUT} {
|
||||
text-align: center;
|
||||
color: #d4d4d4;
|
||||
font-size: ${props => props.theme.typography.h4.fontSize}px;
|
||||
line-height: ${props => props.theme.typography.h4.lineHeight}px;
|
||||
letter-spacing: ${props => props.theme.typography.h4.letterSpacing}px;
|
||||
font-weight: ${props => props.theme.typography.h4.fontWeight}px;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
margin-top: 2px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default function EditableTextWrapper(props: EditableTextWrapperProps) {
|
||||
const [isEditing, setIsEditing] = useState(props.isNewApp);
|
||||
const [isValid, setIsValid] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setIsEditing(props.isNewApp);
|
||||
}, [props.isNewApp]);
|
||||
|
||||
return (
|
||||
<Container
|
||||
isEditing={isEditing}
|
||||
savingState={props.savingState}
|
||||
isInvalid={isValid}
|
||||
>
|
||||
<EditableText
|
||||
defaultValue={props.defaultValue}
|
||||
editInteractionKind={props.editInteractionKind}
|
||||
placeholder={props.placeholder}
|
||||
hideEditIcon={props.hideEditIcon}
|
||||
isEditingDefault={props.isNewApp}
|
||||
savingState={props.savingState}
|
||||
fill={props.fill}
|
||||
onBlur={value => {
|
||||
setIsEditing(false);
|
||||
props.onBlur(value);
|
||||
}}
|
||||
className={props.className}
|
||||
onTextChanged={(value: string) => setIsEditing(true)}
|
||||
isInvalid={(value: string) => {
|
||||
setIsEditing(true);
|
||||
if (props.isInvalid) {
|
||||
setIsValid(Boolean(props.isInvalid(value)));
|
||||
return props.isInvalid(value);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
|
@ -204,7 +204,6 @@ const AppNameWrapper = styled.div<{ isFetching: boolean }>`
|
|||
: null};
|
||||
`;
|
||||
type ApplicationCardProps = {
|
||||
activeAppCard?: boolean;
|
||||
application: ApplicationPayload;
|
||||
duplicate?: (applicationId: string) => void;
|
||||
share?: (applicationId: string) => void;
|
||||
|
|
@ -275,11 +274,6 @@ export const ApplicationCard = (props: ApplicationCardProps) => {
|
|||
addDeleteOption();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
if (props.activeAppCard) {
|
||||
setShowOverlay(true);
|
||||
}
|
||||
}, [props.activeAppCard]);
|
||||
|
||||
const appIcon = (props.application?.icon ||
|
||||
getApplicationIcon(props.application.id)) as AppIconName;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Component, useState } from "react";
|
||||
import React, { Component, Fragment, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import { connect, useSelector, useDispatch } from "react-redux";
|
||||
import { AppState } from "reducers";
|
||||
|
|
@ -53,11 +53,11 @@ import PerformanceTracker, {
|
|||
PerformanceTransactionName,
|
||||
} from "utils/PerformanceTracker";
|
||||
import { loadingUserOrgs } from "./ApplicationLoaders";
|
||||
import CreateApplicationForm from "./CreateApplicationForm";
|
||||
import { creatingApplicationMap } from "reducers/uiReducers/applicationsReducer";
|
||||
import CenteredWrapper from "../../components/designSystems/appsmith/CenteredWrapper";
|
||||
import NoSearchImage from "../../assets/images/NoSearchResult.svg";
|
||||
import organizationList from "../../mockResponses/OrganisationListResponse";
|
||||
import { getNextEntityName } from "utils/AppsmithUtils";
|
||||
import Spinner from "components/ads/Spinner";
|
||||
|
||||
const OrgDropDown = styled.div`
|
||||
display: flex;
|
||||
|
|
@ -348,7 +348,7 @@ function LeftPane() {
|
|||
isFetchingApplications ? BlueprintClasses.SKELETON : ""
|
||||
}
|
||||
icon="workspace"
|
||||
key={org.organization.name}
|
||||
key={org.organization.id}
|
||||
href={`${window.location.pathname}#${org.organization.name}`}
|
||||
text={org.organization.name}
|
||||
ellipsize={20}
|
||||
|
|
@ -405,18 +405,6 @@ ${props => {
|
|||
}
|
||||
`;
|
||||
|
||||
const AddApplicationCard = (
|
||||
<ApplicationAddCardWrapper>
|
||||
<Icon
|
||||
className="t--create-app-popup"
|
||||
name={"plus"}
|
||||
size={IconSize.LARGE}
|
||||
></Icon>
|
||||
<CreateNewLabel type={TextType.H4} className="createnew">
|
||||
Create New
|
||||
</CreateNewLabel>
|
||||
</ApplicationAddCardWrapper>
|
||||
);
|
||||
const NoSearchResultImg = styled.img`
|
||||
margin: 1em;
|
||||
`;
|
||||
|
|
@ -513,6 +501,7 @@ const ApplicationsSection = (props: any) => {
|
|||
};
|
||||
|
||||
const createNewApplication = (applicationName: string, orgId: string) => {
|
||||
console.log(applicationName, orgId);
|
||||
return dispatch({
|
||||
type: ReduxActionTypes.CREATE_APPLICATION_INIT,
|
||||
payload: {
|
||||
|
|
@ -601,14 +590,40 @@ const ApplicationsSection = (props: any) => {
|
|||
) &&
|
||||
!isFetchingApplications && (
|
||||
<PaddingWrapper>
|
||||
<FormDialogComponent
|
||||
permissions={organization.userPermissions}
|
||||
permissionRequired={PERMISSION_TYPE.CREATE_APPLICATION}
|
||||
trigger={AddApplicationCard}
|
||||
Form={CreateApplicationForm}
|
||||
orgId={organization.id}
|
||||
title={CREATE_APPLICATION_FORM_NAME}
|
||||
/>
|
||||
<ApplicationAddCardWrapper
|
||||
onClick={() => {
|
||||
if (
|
||||
Object.entries(creatingApplicationMap).length === 0
|
||||
) {
|
||||
createNewApplication(
|
||||
getNextEntityName(
|
||||
"Untitled application ",
|
||||
applications.map((el: any) => el.name),
|
||||
),
|
||||
organization.id,
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{creatingApplicationMap &&
|
||||
creatingApplicationMap[organization.id] ? (
|
||||
<Spinner size={IconSize.XXXL} />
|
||||
) : (
|
||||
<Fragment>
|
||||
<Icon
|
||||
className="t--create-app-popup"
|
||||
name={"plus"}
|
||||
size={IconSize.LARGE}
|
||||
></Icon>
|
||||
<CreateNewLabel
|
||||
type={TextType.H4}
|
||||
className="createnew"
|
||||
>
|
||||
Create New
|
||||
</CreateNewLabel>
|
||||
</Fragment>
|
||||
)}
|
||||
</ApplicationAddCardWrapper>
|
||||
</PaddingWrapper>
|
||||
)}
|
||||
{applications.map((application: any) => {
|
||||
|
|
@ -619,11 +634,6 @@ const ApplicationsSection = (props: any) => {
|
|||
key={application.id}
|
||||
application={application}
|
||||
orgId={organization.id}
|
||||
activeAppCard={
|
||||
props.newApplicationList[
|
||||
props.newApplicationList.length - 1
|
||||
] === application.id
|
||||
}
|
||||
delete={deleteApplication}
|
||||
update={updateApplicationDispatch}
|
||||
duplicate={duplicateApplicationDispatch}
|
||||
|
|
@ -664,14 +674,13 @@ type ApplicationProps = {
|
|||
};
|
||||
class Applications extends Component<
|
||||
ApplicationProps,
|
||||
{ selectedOrgId: string; newApplicationList: any }
|
||||
{ selectedOrgId: string }
|
||||
> {
|
||||
constructor(props: ApplicationProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
selectedOrgId: "",
|
||||
newApplicationList: [],
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -679,22 +688,6 @@ class Applications extends Component<
|
|||
PerformanceTracker.stopTracking(PerformanceTransactionName.LOGIN_CLICK);
|
||||
PerformanceTracker.stopTracking(PerformanceTransactionName.SIGN_UP);
|
||||
this.props.getAllApplication();
|
||||
if (this.props.applicationList.length > 0) {
|
||||
this.setState({
|
||||
newApplicationList: this.props.applicationList.map(el => el.id),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (
|
||||
this.props.applicationList.length > 0 &&
|
||||
this.props.applicationList.length !== this.state.newApplicationList.length
|
||||
) {
|
||||
this.setState({
|
||||
newApplicationList: this.props.applicationList.map(el => el.id),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
|
|
@ -708,7 +701,6 @@ class Applications extends Component<
|
|||
}}
|
||||
/>
|
||||
<ApplicationsSection
|
||||
newApplicationList={this.state.newApplicationList}
|
||||
searchKeyword={this.props.searchKeyword}
|
||||
></ApplicationsSection>
|
||||
</PageWrapper>
|
||||
|
|
|
|||
|
|
@ -25,10 +25,17 @@ import {
|
|||
getIsPublishingApplication,
|
||||
} from "selectors/editorSelectors";
|
||||
import { getCurrentOrgId } from "selectors/organizationSelectors";
|
||||
import { connect } from "react-redux";
|
||||
import { connect, useDispatch, useSelector } from "react-redux";
|
||||
import { HeaderIcons } from "icons/HeaderIcons";
|
||||
import ThreeDotLoading from "components/designSystems/appsmith/header/ThreeDotsLoading";
|
||||
import DeployLinkButtonDialog from "components/designSystems/appsmith/header/DeployLinkButton";
|
||||
import { EditInteractionKind, SavingState } from "components/ads/EditableText";
|
||||
import { updateApplication } from "actions/applicationActions";
|
||||
import {
|
||||
getApplicationList,
|
||||
getIsSavingAppName,
|
||||
} from "selectors/applicationSelectors";
|
||||
import EditableTextWrapper from "components/ads/EditableTextWrapper";
|
||||
|
||||
const HeaderWrapper = styled(StyledHeader)`
|
||||
background: ${Colors.BALTIC_SEA};
|
||||
|
|
@ -143,6 +150,10 @@ export const EditorHeader = (props: EditorHeaderProps) => {
|
|||
publishApplication,
|
||||
} = props;
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const isSavingName = useSelector(getIsSavingAppName);
|
||||
const applicationList = useSelector(getApplicationList);
|
||||
|
||||
const handlePublish = () => {
|
||||
if (applicationId) {
|
||||
publishApplication(applicationId);
|
||||
|
|
@ -180,6 +191,10 @@ export const EditorHeader = (props: EditorHeaderProps) => {
|
|||
}
|
||||
}
|
||||
|
||||
const updateApplicationDispatch = (id: string, data: { name: string }) => {
|
||||
dispatch(updateApplication(id, data));
|
||||
};
|
||||
|
||||
return (
|
||||
<HeaderWrapper>
|
||||
<HeaderSection>
|
||||
|
|
@ -192,8 +207,26 @@ export const EditorHeader = (props: EditorHeaderProps) => {
|
|||
</Link>
|
||||
</HeaderSection>
|
||||
<HeaderSection flex-direction={"row"}>
|
||||
<ApplicationName>{currentApplication?.name} </ApplicationName>
|
||||
<PageName>{pageName} </PageName>
|
||||
{currentApplication ? (
|
||||
<EditableTextWrapper
|
||||
variant="UNDERLINE"
|
||||
defaultValue={currentApplication?.name || ""}
|
||||
editInteractionKind={EditInteractionKind.SINGLE}
|
||||
hideEditIcon={true}
|
||||
className="t--application-name"
|
||||
fill={false}
|
||||
savingState={
|
||||
isSavingName ? SavingState.STARTED : SavingState.NOT_STARTED
|
||||
}
|
||||
isNewApp={
|
||||
applicationList.filter(el => el.id === applicationId).length > 0
|
||||
}
|
||||
onBlur={(value: string) =>
|
||||
updateApplicationDispatch(applicationId || "", { name: value })
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
{/* <PageName>{pageName} </PageName> */}
|
||||
</HeaderSection>
|
||||
<HeaderSection>
|
||||
<SaveStatusContainer className={"t--save-status-container"}>
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ const PageListItem = withTheme((props: PageListItemProps) => {
|
|||
editInteractionKind={EditInteractionKind.DOUBLE}
|
||||
onTextChanged={onEditPageName}
|
||||
hideEditIcon
|
||||
className="t--page-list-item"
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ const PropertyPaneTitle = memo((props: PropertyPaneTitleProps) => {
|
|||
onBlur={exitEditMode}
|
||||
hideEditIcon
|
||||
minimal
|
||||
className="t--propery-page-title"
|
||||
/>
|
||||
{updating && <Spinner size={16} />}
|
||||
</NameWrapper>
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ const applicationsReducer = createReducer(initialState, {
|
|||
return {
|
||||
...state,
|
||||
userOrgs: _organizations,
|
||||
isSavingAppName: isSavingAppName,
|
||||
isSavingAppName: true,
|
||||
};
|
||||
},
|
||||
[ReduxActionTypes.UPDATE_APPLICATION_SUCCESS]: (
|
||||
|
|
|
|||
|
|
@ -212,6 +212,10 @@ export function* updateApplicationSaga(
|
|||
type: ReduxActionTypes.UPDATE_APPLICATION_SUCCESS,
|
||||
payload: response.data,
|
||||
});
|
||||
AppToaster.show({
|
||||
message: `Application updated`,
|
||||
type: "success",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
yield put({
|
||||
|
|
@ -220,6 +224,10 @@ export function* updateApplicationSaga(
|
|||
error,
|
||||
},
|
||||
});
|
||||
AppToaster.show({
|
||||
message: error,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user