Merge pull request #31719 from appsmithorg/release
13/03 daily promotion
This commit is contained in:
commit
498fb004bd
2
.github/config.json
vendored
2
.github/config.json
vendored
File diff suppressed because one or more lines are too long
|
|
@ -11,6 +11,7 @@ const publish = require("../../../../locators/publishWidgetspage.json");
|
|||
const testdata = require("../../../../fixtures/testdata.json");
|
||||
const pageid = "MyPage";
|
||||
import { agHelper, propPane } from "../../../../support/Objects/ObjectsCore";
|
||||
import PageList from "../../../../support/Pages/PageList";
|
||||
|
||||
describe(
|
||||
"Binding the multiple Widgets and validating NavigateTo Page",
|
||||
|
|
@ -33,7 +34,7 @@ describe(
|
|||
agHelper.AddDsl("displayWidgetDsl");
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(3000);
|
||||
cy.CheckAndUnfoldEntityItem("Pages");
|
||||
PageList.ShowList();
|
||||
PageLeftPane.assertPresence(pageid);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
propPane,
|
||||
deployMode,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
import PageList from "../../../../support/Pages/PageList";
|
||||
|
||||
describe(
|
||||
"Table Widget V2 and Navigate to functionality validation",
|
||||
|
|
@ -34,7 +35,7 @@ describe(
|
|||
agHelper.AddDsl("displayWidgetDsl");
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(500);
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
PageLeftPane.assertPresence(pageid);
|
||||
//Table Widget V2 Functionality with multiple page
|
||||
EditorNavigation.SelectEntityByName("Page1", EntityType.Page);
|
||||
|
|
|
|||
|
|
@ -4,14 +4,15 @@ import EditorNavigation, {
|
|||
} from "../../../../support/Pages/EditorNavigation";
|
||||
|
||||
import * as _ from "../../../../support/Objects/ObjectsCore";
|
||||
import PageList from "../../../../support/Pages/PageList";
|
||||
|
||||
describe(
|
||||
"Hide / Show page test functionality",
|
||||
{ tags: ["@tag.IDE"] },
|
||||
function () {
|
||||
it("1. Hide/Show page test ", function () {
|
||||
cy.CreatePage(); // Page2
|
||||
cy.CreatePage(); // Page3
|
||||
PageList.AddNewPage(); // Page2
|
||||
PageList.AddNewPage(); // Page3
|
||||
EditorNavigation.SelectEntityByName("Page1", EntityType.Page);
|
||||
_.entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "Page2",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
deployMode,
|
||||
entityExplorer,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
import PageList from "../../../../support/Pages/PageList";
|
||||
|
||||
describe("Page Load tests", { tags: ["@tag.IDE"] }, () => {
|
||||
afterEach(() => {
|
||||
|
|
@ -20,7 +21,7 @@ describe("Page Load tests", { tags: ["@tag.IDE"] }, () => {
|
|||
|
||||
before(() => {
|
||||
agHelper.AddDsl("PageLoadDsl");
|
||||
cy.CreatePage();
|
||||
PageList.AddNewPage();
|
||||
cy.get("h2").contains("Drag and drop a widget here");
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ describe("Git discard changes:", { tags: ["@tag.Git"] }, function () {
|
|||
});
|
||||
|
||||
it("4. Delete page2 and trigger discard flow, page2 should be available again", () => {
|
||||
cy.Deletepage(page2);
|
||||
PageList.DeletePage(page2);
|
||||
// verify page is deleted
|
||||
//entityExplorer.ExpandCollapseEntity("Pages");
|
||||
PageLeftPane.assertAbsence(page2);
|
||||
|
|
@ -161,7 +161,7 @@ describe("Git discard changes:", { tags: ["@tag.Git"] }, function () {
|
|||
// discard changes
|
||||
gitSync.DiscardChanges();
|
||||
// verify page3 is removed
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
PageLeftPane.assertAbsence(page3);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import EditorNavigation, {
|
|||
PageLeftPane,
|
||||
PagePaneSegment,
|
||||
} from "../../../../../support/Pages/EditorNavigation";
|
||||
import PageList from "../../../../../support/Pages/PageList";
|
||||
|
||||
const pagename = "ChildPage";
|
||||
const tempBranch = "feat/tempBranch";
|
||||
|
|
@ -48,11 +49,10 @@ describe("Git sync Bug #10773", { tags: ["@tag.Git"] }, function () {
|
|||
cy.wait(2000);
|
||||
gitSync.CreateGitBranch(tempBranch, false);
|
||||
//cy.createGitBranch(tempBranch);
|
||||
cy.CheckAndUnfoldEntityItem("Pages");
|
||||
// verify tempBranch should contain this page
|
||||
EditorNavigation.SelectEntityByName(pagename, EntityType.Page);
|
||||
// delete page from tempBranch and merge to master
|
||||
cy.Deletepage(pagename);
|
||||
PageList.DeletePage(pagename);
|
||||
cy.get(homePageLocators.publishButton).click();
|
||||
cy.get(gitSyncLocators.commitCommentInput).type("Initial Commit");
|
||||
cy.get(gitSyncLocators.commitButton).click();
|
||||
|
|
@ -62,12 +62,12 @@ describe("Git sync Bug #10773", { tags: ["@tag.Git"] }, function () {
|
|||
cy.get(gitSyncLocators.closeGitSyncModal).click();
|
||||
// verify ChildPage is not on master
|
||||
cy.switchGitBranch(mainBranch);
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
PageLeftPane.assertAbsence(pagename);
|
||||
// create another branch and verify deleted page doesn't exist on it
|
||||
//cy.createGitBranch(tempBranch0);
|
||||
gitSync.CreateGitBranch(tempBranch0, false);
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
PageLeftPane.assertAbsence(pagename);
|
||||
gitSync.DeleteTestGithubRepo(repoName);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -277,7 +277,6 @@ describe("Git sync apps", { tags: ["@tag.Git"] }, function () {
|
|||
);
|
||||
dataSources.RunQuery();
|
||||
// create a new page
|
||||
cy.CheckAndUnfoldEntityItem("Pages");
|
||||
cy.Createpage("Child_Page");
|
||||
EditorNavigation.SelectEntityByName(`${newPage} Copy`, EntityType.Page);
|
||||
EditorNavigation.SelectEntityByName("get_users", EntityType.Query);
|
||||
|
|
@ -459,7 +458,7 @@ describe("Git sync apps", { tags: ["@tag.Git"] }, function () {
|
|||
// delete page from page settings
|
||||
EditorNavigation.SelectEntityByName("Child_Page Copy", EntityType.Page);
|
||||
cy.wait("@getConsolidatedData");
|
||||
cy.Deletepage("Child_Page Copy");
|
||||
PageList.DeletePage("Child_Page Copy");
|
||||
cy.get(homePageLocators.publishButton).click();
|
||||
cy.get(gitSyncLocators.commitCommentInput).type("Initial Commit");
|
||||
cy.get(gitSyncLocators.commitButton).click();
|
||||
|
|
@ -482,11 +481,11 @@ describe("Git sync apps", { tags: ["@tag.Git"] }, function () {
|
|||
expect(cellData).to.be.equal("New Config");
|
||||
});
|
||||
agHelper.AssertAutoSave();
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
PageLeftPane.assertAbsence("Child_Page Copy");
|
||||
// create another branch and verify deleted page doesn't exist on it
|
||||
gitSync.CreateGitBranch(tempBranch0, true);
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
PageLeftPane.assertAbsence("Child_Page Copy");
|
||||
});
|
||||
|
||||
|
|
@ -498,7 +497,7 @@ describe("Git sync apps", { tags: ["@tag.Git"] }, function () {
|
|||
// import application from git
|
||||
cy.importAppFromGit(repoName);
|
||||
// verify page order remains same as in orignal app
|
||||
cy.CheckAndUnfoldEntityItem("Pages");
|
||||
PageList.ShowList();
|
||||
cy.get(".t--entity-item").eq(1).contains("crudpage_1");
|
||||
cy.get(".t--entity-item").eq(2).contains("crudpage_1 Copy");
|
||||
cy.get(".t--entity-item").eq(3).contains("ApiCalls_1");
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import widgetsPage from "../../../../../locators/Widgets.json";
|
||||
import commonlocators from "../../../../../locators/commonlocators.json";
|
||||
import gitSyncLocators from "../../../../../locators/gitSyncLocators";
|
||||
import homePage from "../../../../../locators/HomePage";
|
||||
import * as _ from "../../../../../support/Objects/ObjectsCore";
|
||||
import {
|
||||
PageLeftPane,
|
||||
PagePaneSegment,
|
||||
} from "../../../../../support/Pages/EditorNavigation";
|
||||
import PageList from "../../../../../support/Pages/PageList";
|
||||
|
||||
let tempBranch = "tempBranch",
|
||||
tempBranch0 = "tempBranch0",
|
||||
|
|
@ -57,7 +55,6 @@ describe(
|
|||
//cy.switchGitBranch(mainBranch);
|
||||
_.gitSync.CreateGitBranch(tempBranch2, true);
|
||||
PageLeftPane.switchSegment(PagePaneSegment.UI);
|
||||
cy.CheckAndUnfoldEntityItem("Pages");
|
||||
cy.Createpage("NewPage");
|
||||
cy.commitAndPush();
|
||||
cy.merge(mainBranch);
|
||||
|
|
@ -79,7 +76,7 @@ describe(
|
|||
});
|
||||
|
||||
it("3. Checks clean url updates across branches", () => {
|
||||
cy.Deletepage("NewPage");
|
||||
PageList.DeletePage("NewPage");
|
||||
cy.wait(1000);
|
||||
let legacyPathname = "";
|
||||
let newPathname = "";
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ describe("Git sync:", { tags: ["@tag.Git"] }, function () {
|
|||
|
||||
cy.switchGitBranch(parentBranchKey);
|
||||
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
PageLeftPane.assertAbsence("ParentPageRenamed");
|
||||
PageLeftPane.switchSegment(PagePaneSegment.Queries);
|
||||
PageLeftPane.assertAbsence("ParentApiRenamed");
|
||||
|
|
@ -212,7 +212,6 @@ describe("Git sync:", { tags: ["@tag.Git"] }, function () {
|
|||
cy.generateUUID().then((uuid) => {
|
||||
gitSync.CreateGitBranch(childBranchKey, true);
|
||||
//cy.createGitBranch(childBranchKey);
|
||||
cy.CheckAndUnfoldEntityItem("Pages");
|
||||
PageList.AddNewPage();
|
||||
cy.get(gitSyncLocators.branchButton).click({ force: true });
|
||||
cy.get(gitSyncLocators.branchSearchInput).type("{selectall}master");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
const commonlocators = require("../../../../locators/commonlocators.json");
|
||||
const pages = require("../../../../locators/Pages.json");
|
||||
import PageList from "../../../../support/Pages/PageList";
|
||||
|
||||
describe("Dynamic Layout Functionality", function () {
|
||||
it("1. Dynamic Layout - Change Layout", function () {
|
||||
|
|
@ -7,7 +7,7 @@ describe("Dynamic Layout Functionality", function () {
|
|||
cy.get(commonlocators.canvas).invoke("width").should("be.eq", 450);
|
||||
|
||||
//Dynamic Layout - New Page should have selected Layout
|
||||
cy.get(pages.AddPage).first().click();
|
||||
PageList.AddNewPage();
|
||||
cy.get(commonlocators.canvas).invoke("width").should("be.eq", 450);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -167,247 +167,15 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
});
|
||||
});
|
||||
|
||||
it("3. Checks if the theme can be saved", () => {
|
||||
//Click on dropDown elipses
|
||||
cy.contains("Theme properties")
|
||||
.closest("div")
|
||||
.siblings()
|
||||
.first()
|
||||
.find("button")
|
||||
.click({ force: true });
|
||||
|
||||
agHelper.AssertAutoSave();
|
||||
|
||||
//Click on save theme dropdown option
|
||||
cy.contains("Save theme").click({ force: true });
|
||||
|
||||
//Type the name of the theme:
|
||||
agHelper.TypeText("input[placeholder='My theme']", "testtheme");
|
||||
//Click on save theme button
|
||||
agHelper.ClickButton("Save theme");
|
||||
agHelper.ValidateToastMessage("Theme testtheme saved");
|
||||
appSettings.ClosePane();
|
||||
});
|
||||
|
||||
it("4. Verify Save Theme after changing all properties & widgets conform to the selected theme", () => {
|
||||
cy.dragAndDropToCanvas("iconbuttonwidget", { x: 300, y: 300 });
|
||||
cy.assertPageSave();
|
||||
cy.get("canvas").first(0).trigger("click", { force: true });
|
||||
|
||||
appSettings.OpenAppSettings();
|
||||
appSettings.GoToThemeSettings();
|
||||
//#region Change Font & verify widgets:
|
||||
|
||||
agHelper.GetNClick(".rc-select-selection-search-input").then(($elem) => {
|
||||
cy.get($elem).click({ force: true });
|
||||
cy.wait(250);
|
||||
cy.get(".rc-virtual-list-holder div")
|
||||
.children()
|
||||
.eq(4)
|
||||
.then(($childElem) => {
|
||||
cy.get($childElem).click({ force: true });
|
||||
cy.get(widgetsPage.iconWidgetBtn).should(
|
||||
"have.css",
|
||||
"font-family",
|
||||
`${$childElem.children().last().text()}Inter, sans-serif`,
|
||||
);
|
||||
cy.get(widgetsPage.widgetBtn).should(
|
||||
"have.css",
|
||||
"font-family",
|
||||
`${$childElem.children().last().text()}Inter, sans-serif`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
cy.get(widgetsPage.colorPickerV2Popover).click({ force: true }).click();
|
||||
cy.get(widgetsPage.colorPickerV2Color)
|
||||
.eq(-15)
|
||||
.then(($elem) => {
|
||||
cy.get($elem).click({ force: true });
|
||||
cy.get(widgetsPage.iconWidgetBtn).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
$elem.css("background-color"),
|
||||
);
|
||||
cy.get(widgetsPage.widgetBtn).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
$elem.css("background-color"),
|
||||
);
|
||||
});
|
||||
|
||||
//Change the background color:
|
||||
cy.get("[data-testid='theme-backgroundColor']").click({ force: true });
|
||||
cy.wait(500);
|
||||
cy.get(widgetsPage.colorPickerV2Popover).click({ force: true }).click();
|
||||
cy.get(widgetsPage.colorPickerV2TailwindColor)
|
||||
.eq(23)
|
||||
.then(($elem) => {
|
||||
cy.get($elem).click({ force: true });
|
||||
cy.get(commonlocators.canvas).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
$elem.css("background-color"),
|
||||
);
|
||||
});
|
||||
|
||||
cy.get(commonlocators.themeAppBorderRadiusBtn).eq(2).click({ force: true });
|
||||
cy.get(`${commonlocators.themeAppBorderRadiusBtn}`)
|
||||
.eq(2)
|
||||
.invoke("css", "border-top-left-radius")
|
||||
.then((borderRadius) => {
|
||||
cy.get(widgetsPage.iconWidgetBtn).should(
|
||||
"have.css",
|
||||
"border-radius",
|
||||
borderRadius,
|
||||
);
|
||||
cy.get(widgetsPage.widgetBtn).should(
|
||||
"have.css",
|
||||
"border-radius",
|
||||
borderRadius,
|
||||
);
|
||||
});
|
||||
|
||||
//#region Change the shadow & verify widgets
|
||||
cy.get("[data-value='L']").eq(1).click({ force: true });
|
||||
cy.get("[data-value='L']")
|
||||
.eq(1)
|
||||
.invoke("css", "box-shadow")
|
||||
.then((boxShadow) => {
|
||||
cy.get(containerShadowElement).should(
|
||||
"have.css",
|
||||
"box-shadow",
|
||||
boxShadow,
|
||||
);
|
||||
});
|
||||
|
||||
//#region Click on dropDown elipses
|
||||
cy.contains("Theme properties")
|
||||
.closest("div")
|
||||
.siblings()
|
||||
.first()
|
||||
.find("button")
|
||||
.click({ force: true });
|
||||
cy.wait(300);
|
||||
|
||||
//Click on save theme dropdown option & close it
|
||||
cy.contains("Save theme").click({ force: true });
|
||||
cy.wait(200);
|
||||
cy.get(".ads-v2-modal__content-header-close-button").click();
|
||||
|
||||
//Click on save theme dropdown option & cancel it
|
||||
cy.contains("Theme properties")
|
||||
.closest("div")
|
||||
.siblings()
|
||||
.first()
|
||||
.find("button")
|
||||
.click({ force: true });
|
||||
cy.wait(300);
|
||||
cy.contains("Save theme").click({ force: true });
|
||||
cy.wait(200);
|
||||
cy.xpath("//span[text()='Cancel']/parent::div").click();
|
||||
|
||||
//Click on save theme dropdown option, give duplicte name & save it
|
||||
cy.contains("Theme properties")
|
||||
.closest("div")
|
||||
.siblings()
|
||||
.first()
|
||||
.find("button")
|
||||
.click({ force: true });
|
||||
cy.wait(300);
|
||||
cy.contains("Save theme").click({ force: true });
|
||||
cy.wait(200);
|
||||
//Type the name of the theme:
|
||||
agHelper.TypeText("input[placeholder='My theme']", "testtheme");
|
||||
cy.contains("Name must be unique");
|
||||
|
||||
cy.get("input[placeholder='My theme']").clear().type("VioletYellowTheme");
|
||||
|
||||
//Click on save theme button
|
||||
agHelper.ClickButton("Save theme");
|
||||
agHelper.ValidateToastMessage("Theme VioletYellowTheme saved");
|
||||
});
|
||||
|
||||
it("5. Verify Themes exists under respective section when ChangeTheme button is cicked in properties with Apply Theme & Trash as applicable", () => {
|
||||
//Click on change theme:
|
||||
it("4. Verify user able to change between saved theme & already existing Featured themes", () => {
|
||||
cy.get(commonlocators.changeThemeBtn).click({ force: true });
|
||||
cy.xpath(applyTheme("Your themes", "testtheme"))
|
||||
.click({ force: true })
|
||||
.wait(1000); //Changing to testtheme
|
||||
|
||||
cy.contains("Applied theme")
|
||||
.click()
|
||||
.parent()
|
||||
.siblings()
|
||||
.find(".t--theme-card > main > main")
|
||||
.invoke("css", "background-color")
|
||||
.then((backgroudColor) => {
|
||||
expect(backgroudColor).to.eq("rgb(236, 72, 153)");
|
||||
});
|
||||
|
||||
//Check if the saved theme is present under 'Yours Themes' section with Trash button
|
||||
cy.xpath(applyTheme("Your themes", "testtheme")).should("exist");
|
||||
cy.xpath(themesDeletebtn("Your themes", "testtheme")).should("exist");
|
||||
|
||||
cy.xpath(applyTheme("Your themes", "VioletYellowTheme")).should("exist");
|
||||
cy.xpath(themesDeletebtn("Your themes", "VioletYellowTheme")).should(
|
||||
"exist",
|
||||
);
|
||||
|
||||
cy.xpath(applyTheme("Featured themes", "Earth")).should("exist");
|
||||
cy.xpath(themesDeletebtn("Featured themes", "Earth")).should("not.exist");
|
||||
|
||||
cy.xpath(applyTheme("Featured themes", "Sunrise")).should("exist");
|
||||
cy.xpath(themesDeletebtn("Featured themes", "Sunrise")).should("not.exist");
|
||||
|
||||
cy.xpath(applyTheme("Featured themes", "Pacific")).should("exist");
|
||||
cy.xpath(themesDeletebtn("Featured themes", "Pacific")).should("not.exist");
|
||||
|
||||
cy.xpath(applyTheme("Featured themes", "Pampas")).should("exist");
|
||||
cy.xpath(themesDeletebtn("Featured themes", "Pampas")).should("not.exist");
|
||||
});
|
||||
|
||||
it("6. Verify the custom theme can be deleted", () => {
|
||||
//Delete the created theme
|
||||
cy.xpath(themesDeletebtn("Your themes", "testtheme"))
|
||||
.click({ force: true })
|
||||
.wait(200);
|
||||
cy.contains(
|
||||
"Do you really want to delete this theme? This process cannot be undone.",
|
||||
);
|
||||
|
||||
//Click on Delete theme trash icon & close it
|
||||
cy.xpath("//*[text()='Are you sure?']/following-sibling::button").click();
|
||||
cy.get(commonlocators.toastMsg).should("not.exist");
|
||||
|
||||
//Click on Delete theme trash icon & cancel it
|
||||
cy.xpath(themesDeletebtn("Your themes", "testtheme"))
|
||||
.click({ force: true })
|
||||
.wait(200);
|
||||
cy.xpath("//span[text()='No']/parent::div").click();
|
||||
cy.get(commonlocators.toastMsg).should("not.exist");
|
||||
|
||||
//Click on Delete theme trash icon & delete it
|
||||
cy.xpath(themesDeletebtn("Your themes", "testtheme"))
|
||||
.click({ force: true })
|
||||
.wait(200);
|
||||
agHelper.ClickButton("Delete");
|
||||
// cy.contains("Delete").click({ force: true });
|
||||
|
||||
//check for delete alert
|
||||
// cy.wait(500);
|
||||
agHelper.ValidateToastMessage("Theme testtheme deleted");
|
||||
//cy.get(commonlocators.toastMsg).contains("Theme testtheme deleted");
|
||||
cy.xpath(applyTheme("Your themes", "testtheme")).should("not.exist");
|
||||
});
|
||||
|
||||
it("7. Verify user able to change between saved theme & already existing Featured themes", () => {
|
||||
//#region Pampas
|
||||
cy.xpath(applyTheme("Featured themes", "Pampas"))
|
||||
.click({ force: true })
|
||||
.wait(1000); //Changing to one of Featured themes
|
||||
cy.contains("Applied theme")
|
||||
// .click()
|
||||
.click()
|
||||
.parent()
|
||||
.siblings()
|
||||
.find(".t--theme-card > main > section > div > main")
|
||||
|
|
@ -620,70 +388,38 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
expect(backgroudColor).to.eq("rgb(248, 250, 252)");
|
||||
});
|
||||
//#endregion
|
||||
|
||||
//#region VioletYellowTheme
|
||||
cy.xpath(applyTheme("Your themes", "VioletYellowTheme"))
|
||||
.click({ force: true })
|
||||
.wait(1000); //Changing to created test theme
|
||||
|
||||
cy.contains("Applied theme")
|
||||
// .click()
|
||||
.parent()
|
||||
.siblings()
|
||||
.find(".t--theme-card > main > section > div > main")
|
||||
.eq(0)
|
||||
.invoke("css", "background-color")
|
||||
.then((backgroudColor) => {
|
||||
expect(backgroudColor).to.eq("rgb(219, 234, 254)");
|
||||
});
|
||||
|
||||
cy.contains("Applied theme")
|
||||
// .click()
|
||||
.parent()
|
||||
.siblings()
|
||||
.find(".t--theme-card > main > section > div > main")
|
||||
.eq(1)
|
||||
.invoke("css", "background-color")
|
||||
.then((backgroudColor) => {
|
||||
expect(backgroudColor).to.eq("rgb(29, 78, 216)");
|
||||
});
|
||||
|
||||
//#endregion
|
||||
});
|
||||
|
||||
it("8. Verify widgets conform to the selected theme in Publish mode", () => {
|
||||
it("5. Verify widgets conform to the selected theme in Publish mode", () => {
|
||||
deployMode.DeployApp();
|
||||
|
||||
//cy.wait(4000); //for theme to settle
|
||||
|
||||
cy.get("body").should("have.css", "font-family", "Inter, sans-serif"); //Font
|
||||
cy.get("body").should(
|
||||
"have.css",
|
||||
"font-family",
|
||||
`"Nunito Sans", sans-serif`,
|
||||
); //Font
|
||||
|
||||
cy.xpath("//div[@id='root']//section/parent::div").should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(29, 78, 216)",
|
||||
"rgb(248, 250, 252)",
|
||||
); //Background Color
|
||||
cy.get(widgetsPage.widgetBtn).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(219, 234, 254)",
|
||||
); //Widget Color
|
||||
cy.get(publish.iconWidgetBtn).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(219, 234, 254)",
|
||||
"rgb(100, 116, 139)",
|
||||
); //Widget Color
|
||||
|
||||
cy.get(widgetsPage.widgetBtn).should("have.css", "border-radius", "24px"); //Border Radius
|
||||
cy.get(publish.iconWidgetBtn).should("have.css", "border-radius", "24px"); //Border Radius
|
||||
cy.get(widgetsPage.widgetBtn).should("have.css", "border-radius", "0px"); //Border Radius
|
||||
|
||||
cy.get(widgetsPage.widgetBtn).should("have.css", "box-shadow", "none"); //Shadow
|
||||
cy.get(publish.iconWidgetBtn).should("have.css", "box-shadow", "none"); //Shadow
|
||||
|
||||
deployMode.NavigateBacktoEditor();
|
||||
});
|
||||
|
||||
it("9. Verify Adding new Individual widgets & it can change Color, Border radius, Shadow & can revert [Color/Border Radius] to already selected theme", () => {
|
||||
it("6. Verify Adding new Individual widgets & it can change Color, Border radius, Shadow & can revert [Color/Border Radius] to already selected theme", () => {
|
||||
cy.dragAndDropToCanvas("buttonwidget", { x: 200, y: 400 }); //another button widget
|
||||
cy.moveToStyleTab();
|
||||
//Change Color & verify
|
||||
|
|
@ -701,13 +437,8 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
cy.get(".t--widget-button1 button").should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(219, 234, 254)",
|
||||
"rgb(100, 116, 139)",
|
||||
); //old widgets still conforming to theme color
|
||||
cy.get(widgetsPage.iconWidgetBtn).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(219, 234, 254)",
|
||||
);
|
||||
});
|
||||
|
||||
//Change Border & verify
|
||||
|
|
@ -722,22 +453,16 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
"border-radius",
|
||||
borderRadius, //0px
|
||||
);
|
||||
cy.get(widgetsPage.iconWidgetBtn).should(
|
||||
"have.css",
|
||||
"border-radius",
|
||||
"24px",
|
||||
);
|
||||
cy.get(".t--widget-button1 button").should(
|
||||
"have.css",
|
||||
"border-radius",
|
||||
"24px",
|
||||
"0px",
|
||||
);
|
||||
});
|
||||
|
||||
//Change Shadow & verify
|
||||
cy.contains(".ads-v2-segmented-control-value-0", "Large").click();
|
||||
|
||||
cy.get(widgetsPage.iconWidgetBtn).should("have.css", "box-shadow", "none");
|
||||
cy.get(".t--widget-button1 button").should(
|
||||
"have.css",
|
||||
"box-shadow",
|
||||
|
|
@ -748,23 +473,17 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
deployMode.DeployApp();
|
||||
|
||||
//Verify Background color
|
||||
cy.get(".t--widget-buttonwidget:nth-child(4) button").should(
|
||||
cy.get(".t--widget-button2 button").should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(190, 24, 93)",
|
||||
); //new widget with its own color
|
||||
|
||||
////old widgets still conforming to theme color
|
||||
cy.get(".t--widget-buttonwidget button").should(
|
||||
cy.get(".t--widget-button1 button").should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(219, 234, 254)",
|
||||
);
|
||||
|
||||
cy.get(publish.iconWidgetBtn).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(219, 234, 254)",
|
||||
"rgb(100, 116, 139)",
|
||||
);
|
||||
|
||||
//Verify Border radius
|
||||
|
|
@ -773,11 +492,10 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
"border-radius",
|
||||
"0px",
|
||||
);
|
||||
cy.get(publish.iconWidgetBtn).should("have.css", "border-radius", "24px");
|
||||
cy.get(".t--widget-button1 button").should(
|
||||
"have.css",
|
||||
"border-radius",
|
||||
"24px",
|
||||
"0px",
|
||||
);
|
||||
|
||||
//Verify Box shadow
|
||||
|
|
@ -786,7 +504,6 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
"box-shadow",
|
||||
"rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px",
|
||||
);
|
||||
cy.get(publish.iconWidgetBtn).should("have.css", "box-shadow", "none");
|
||||
cy.get(".t--widget-button1 button").should(
|
||||
"have.css",
|
||||
"box-shadow",
|
||||
|
|
@ -805,7 +522,7 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
cy.get(".t--widget-button2 button").should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(219, 234, 254)",
|
||||
"rgb(100, 116, 139)",
|
||||
); //verify widget reverted to theme color
|
||||
cy.get(".t--property-control-borderradius .reset-button").then(($elem) => {
|
||||
$elem[0].removeAttribute("display: none");
|
||||
|
|
@ -814,24 +531,28 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
cy.get(".t--widget-button2 button").should(
|
||||
"have.css",
|
||||
"border-radius",
|
||||
"24px",
|
||||
"0px",
|
||||
);
|
||||
|
||||
//the new widget with reverted styles also conforming to theme
|
||||
deployMode.DeployApp();
|
||||
|
||||
cy.wait(4000); //for theme to settle
|
||||
cy.get("body").should("have.css", "font-family", "Inter, sans-serif"); //Font
|
||||
cy.get("body").should(
|
||||
"have.css",
|
||||
"font-family",
|
||||
`"Nunito Sans", sans-serif`,
|
||||
); //Font
|
||||
|
||||
cy.xpath("//div[@id='root']//section/parent::div").should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(29, 78, 216)",
|
||||
"rgb(248, 250, 252)",
|
||||
); //Background Color
|
||||
cy.get(".t--widget-button1 button").should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(219, 234, 254)",
|
||||
"rgb(100, 116, 139)",
|
||||
); //Widget Color
|
||||
cy.get("body").then(($ele) => {
|
||||
if ($ele.find(widgetsPage.widgetBtn).length <= 1) {
|
||||
|
|
@ -842,25 +563,19 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
cy.get(".t--widget-button2 button").should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(219, 234, 254)",
|
||||
); //Widget Color
|
||||
cy.get(publish.iconWidgetBtn).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(219, 234, 254)",
|
||||
"rgb(100, 116, 139)",
|
||||
); //Widget Color
|
||||
|
||||
cy.get(".t--widget-button1 button").should(
|
||||
"have.css",
|
||||
"border-radius",
|
||||
"24px",
|
||||
"0px",
|
||||
); //Border Radius
|
||||
cy.get(".t--widget-button2 button").should(
|
||||
"have.css",
|
||||
"border-radius",
|
||||
"24px",
|
||||
"0px",
|
||||
); //Border Radius
|
||||
cy.get(publish.iconWidgetBtn).should("have.css", "border-radius", "24px"); //Border Radius
|
||||
|
||||
cy.get(".t--widget-button1 button").should(
|
||||
"have.css",
|
||||
|
|
@ -872,12 +587,10 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
"box-shadow",
|
||||
"rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px",
|
||||
); //Since Shadow revert option does not exixts
|
||||
cy.get(publish.iconWidgetBtn).should("have.css", "box-shadow", "none"); //Shadow
|
||||
|
||||
deployMode.NavigateBacktoEditor();
|
||||
});
|
||||
|
||||
it("10. Verify Chainging theme should not affect Individual widgets with changed Color, Border radius, Shadow & can revert to newly selected theme", () => {
|
||||
it("7. Verify Chainging theme should not affect Individual widgets with changed Color, Border radius, Shadow & can revert to newly selected theme", () => {
|
||||
cy.get("canvas").first(0).trigger("click", { force: true });
|
||||
|
||||
appSettings.OpenAppSettings();
|
||||
|
|
@ -911,11 +624,6 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
"background-color",
|
||||
"rgb(239, 68, 68)",
|
||||
); //old widgets still conforming to theme color
|
||||
cy.get(widgetsPage.iconWidgetBtn).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(239, 68, 68)",
|
||||
);
|
||||
});
|
||||
|
||||
//Change Border & verify
|
||||
|
|
@ -930,11 +638,7 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
"border-radius",
|
||||
borderRadius, //6px
|
||||
);
|
||||
cy.get(widgetsPage.iconWidgetBtn).should(
|
||||
"have.css",
|
||||
"border-radius",
|
||||
"24px",
|
||||
);
|
||||
|
||||
cy.get(".t--widget-button2 button").should(
|
||||
"have.css",
|
||||
"border-radius",
|
||||
|
|
@ -944,7 +648,6 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
|
||||
//Change Shadow & verify
|
||||
cy.contains(".ads-v2-segmented-control-value-0", "Small").click();
|
||||
cy.get(widgetsPage.iconWidgetBtn).should("have.css", "box-shadow", "none");
|
||||
cy.get(".t--widget-button2 button").should(
|
||||
"have.css",
|
||||
"box-shadow",
|
||||
|
|
@ -971,11 +674,6 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
"background-color",
|
||||
"rgb(239, 68, 68)",
|
||||
);
|
||||
cy.get(publish.iconWidgetBtn).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(239, 68, 68)",
|
||||
);
|
||||
|
||||
//Verify Border radius
|
||||
cy.get(".t--widget-button1 button").should(
|
||||
|
|
@ -983,7 +681,6 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
"border-radius",
|
||||
"6px",
|
||||
);
|
||||
cy.get(publish.iconWidgetBtn).should("have.css", "border-radius", "24px");
|
||||
cy.get(".t--widget-button2 button").should(
|
||||
"have.css",
|
||||
"border-radius",
|
||||
|
|
@ -996,7 +693,6 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
"box-shadow",
|
||||
"rgba(0, 0, 0, 0.1) 0px 1px 3px 0px, rgba(0, 0, 0, 0.06) 0px 1px 2px 0px",
|
||||
);
|
||||
cy.get(publish.iconWidgetBtn).should("have.css", "box-shadow", "none");
|
||||
cy.get(".t--widget-button2 button").should(
|
||||
"have.css",
|
||||
"box-shadow",
|
||||
|
|
@ -1056,11 +752,6 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
"background-color",
|
||||
"rgb(239, 68, 68)",
|
||||
); //Widget Color
|
||||
cy.get(publish.iconWidgetBtn).should(
|
||||
"have.css",
|
||||
"background-color",
|
||||
"rgb(239, 68, 68)",
|
||||
); //Widget Color
|
||||
|
||||
cy.get(".t--widget-button1 button").should(
|
||||
"have.css",
|
||||
|
|
@ -1072,7 +763,6 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
"border-radius",
|
||||
"24px",
|
||||
); //Border Radius
|
||||
cy.get(publish.iconWidgetBtn).should("have.css", "border-radius", "24px"); //Border Radius
|
||||
|
||||
cy.get(".t--widget-button1 button").should(
|
||||
"have.css",
|
||||
|
|
@ -1084,7 +774,6 @@ describe("App Theming funtionality", { tags: ["@tag.Theme"] }, function () {
|
|||
"box-shadow",
|
||||
"rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px",
|
||||
); //Since Shadow revert option does not exixts
|
||||
cy.get(publish.iconWidgetBtn).should("have.css", "box-shadow", "none"); //Shadow
|
||||
|
||||
deployMode.NavigateBacktoEditor();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import {
|
|||
locators,
|
||||
propPane,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
import Canvas from "../../../../support/Pages/Canvas";
|
||||
import EditorNavigation, {
|
||||
EntityType,
|
||||
PageLeftPane,
|
||||
|
|
@ -94,12 +93,9 @@ describe(
|
|||
);
|
||||
deployMode.NavigateBacktoEditor();
|
||||
|
||||
// Verify multiple widgets selected groups into single container
|
||||
Canvas.selectMultipleWidgets(["Input1", "Select1", "Text3"]);
|
||||
agHelper.GetElement("body").type(`{${agHelper._modifierKey}}{g}`);
|
||||
agHelper.Sleep(1000);
|
||||
PageLeftPane.assertPresence("Container3");
|
||||
entityExplorer.DeleteWidgetFromEntityExplorer("Container3");
|
||||
entityExplorer.DeleteWidgetFromEntityExplorer("Input1");
|
||||
entityExplorer.DeleteWidgetFromEntityExplorer("Select1");
|
||||
entityExplorer.DeleteWidgetFromEntityExplorer("Text3");
|
||||
});
|
||||
|
||||
it("4. Validate visible toggle", () => {
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ describe(
|
|||
//Should check that widget input is not showing any errors on input
|
||||
cy.get(widgetInput).type("123456789");
|
||||
cy.focused().then(() => {
|
||||
expect(Cypress.$(themelocators.popover)).not.to.exist;
|
||||
cy.get(".error-tooltip .bp3-popover-content").should("not.exist");
|
||||
});
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import PageList from "../../../../../support/Pages/PageList";
|
||||
const { ObjectsRegistry } = require("../../../../../support/Objects/Registry");
|
||||
import EditorNavigation, {
|
||||
EntityType,
|
||||
|
|
@ -31,13 +32,14 @@ describe(
|
|||
it("2.Check the OnSrcDocChange event call on first render", () => {
|
||||
agHelper.RefreshPage();
|
||||
cy.wait(2000);
|
||||
cy.get(`.t--entity .page`).first().should("have.class", "activePage");
|
||||
PageList.ShowList();
|
||||
PageList.VerifyIsCurrentPage("Page1");
|
||||
cy.openPropertyPane("iframewidget");
|
||||
cy.testJsontext("srcdoc", "<h1>Hello World!</h1>");
|
||||
cy.wait(2000);
|
||||
cy.get(`.t--entity .page`).last().should("have.class", "activePage");
|
||||
PageList.VerifyIsCurrentPage("Page2");
|
||||
EditorNavigation.SelectEntityByName(page1, EntityType.Page);
|
||||
cy.get(`.t--entity .page`).first().should("have.class", "activePage");
|
||||
PageList.VerifyIsCurrentPage("Page1");
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ describe(
|
|||
it("5. Verify Theme change", () => {
|
||||
agHelper.PressEscape();
|
||||
appSettings.OpenPaneAndChangeTheme("Pacific");
|
||||
agHelper.WaitUntilToastDisappear("Theme Pacific applied");
|
||||
[0, 1, 2].forEach((index) => {
|
||||
agHelper.AssertAttribute(
|
||||
locators._listText,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ const containerWidgetSelector = `[type="CONTAINER_WIDGET"]`;
|
|||
function dragAndDropToWidget(widgetType, destinationWidget, { x, y }) {
|
||||
const selector = `.t--widget-card-draggable-${widgetType}`;
|
||||
cy.wait(800);
|
||||
PageLeftPane.switchToAddNew();
|
||||
cy.get(selector)
|
||||
.first()
|
||||
.scrollIntoView()
|
||||
|
|
@ -34,9 +35,9 @@ function deleteAllWidgetsInContainer() {
|
|||
force: true,
|
||||
});
|
||||
cy.get("body").type(`{${modifierKey}}{a}`);
|
||||
cy.get("body").type("{del}");
|
||||
|
||||
cy.wait(200);
|
||||
cy.get("body").type("{del}");
|
||||
cy.get(commonlocators.layoutControls).should("be.visible");
|
||||
}
|
||||
|
||||
function checkSelectedRadioValue(selector, value) {
|
||||
|
|
@ -63,12 +64,13 @@ describe(
|
|||
x: 250,
|
||||
y: 50,
|
||||
});
|
||||
cy.assertPageSave();
|
||||
|
||||
// Verify drop
|
||||
cy.get(publishLocators.inputWidget).should("exist");
|
||||
|
||||
// Type value
|
||||
cy.get(publishLocators.inputWidget).find("input").type("abcd");
|
||||
cy.get(publishLocators.inputWidget).find("input").first().type("abcd");
|
||||
|
||||
// Verify if the value got typed
|
||||
cy.get(publishLocators.inputWidget)
|
||||
|
|
@ -78,7 +80,6 @@ describe(
|
|||
deleteAllWidgetsInContainer();
|
||||
|
||||
// Drop Select widget
|
||||
PageLeftPane.switchToAddNew();
|
||||
dragAndDropToWidget("selectwidget", "containerwidget", {
|
||||
x: 250,
|
||||
y: 50,
|
||||
|
|
@ -115,7 +116,6 @@ describe(
|
|||
deleteAllWidgetsInContainer();
|
||||
|
||||
// Drop Checkbox widget
|
||||
PageLeftPane.switchToAddNew();
|
||||
dragAndDropToWidget("checkboxgroupwidget", "containerwidget", {
|
||||
x: 250,
|
||||
y: 50,
|
||||
|
|
@ -158,7 +158,6 @@ describe(
|
|||
deleteAllWidgetsInContainer();
|
||||
|
||||
// Drop Switch widget
|
||||
PageLeftPane.switchToAddNew();
|
||||
dragAndDropToWidget("switchwidget", "containerwidget", {
|
||||
x: 250,
|
||||
y: 50,
|
||||
|
|
@ -201,9 +200,8 @@ describe(
|
|||
|
||||
_.deployMode.NavigateBacktoEditor();
|
||||
deleteAllWidgetsInContainer();
|
||||
|
||||
cy.wait(800);
|
||||
// Drop Radio widget
|
||||
PageLeftPane.switchToAddNew();
|
||||
dragAndDropToWidget("radiogroupwidget", "containerwidget", {
|
||||
x: 250,
|
||||
y: 50,
|
||||
|
|
|
|||
|
|
@ -68,7 +68,8 @@ describe(
|
|||
entityExplorer.DragDropWidgetNVerify(widget);
|
||||
//cy.dragAndDropToWidget(widget, "listwidgetv2", { x: 350, y: 50 });
|
||||
agHelper.GetNClick(propPane._deleteWidget);
|
||||
cy.wait("@updateLayout");
|
||||
cy.assertPageSave();
|
||||
cy.wait(800);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
@ -88,7 +89,8 @@ describe(
|
|||
cy.assertPageSave();
|
||||
cy.get(`.t--draggable-${widget}`).should("exist");
|
||||
cy.get(widgetsPage.removeWidget).click({ force: true });
|
||||
cy.wait("@updateLayout");
|
||||
cy.assertPageSave();
|
||||
cy.wait(800);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ describe(
|
|||
//cy.createModal("Modal", this.dataSet.ModalName);
|
||||
cy.createModal("Modal", "onRowSelected");
|
||||
cy.isSelectRow(1);
|
||||
cy.get(".bp3-overlay-backdrop").click({ force: true });
|
||||
cy.get(".bp3-overlay-backdrop").last().click({ force: true });
|
||||
cy.isSelectRow(2);
|
||||
cy.get(".bp3-overlay-backdrop").click({ force: true });
|
||||
cy.get(".bp3-overlay-backdrop").last().click({ force: true });
|
||||
});
|
||||
|
||||
it("2. Table widget V2 with button colour change validation", function () {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import {
|
|||
table,
|
||||
} from "../../../../support/Objects/ObjectsCore";
|
||||
import PageList from "../../../../support/Pages/PageList";
|
||||
import { PageLeftPane } from "../../../../support/Pages/EditorNavigation";
|
||||
|
||||
describe(
|
||||
"Validate Mongo CRUD with JSON Form",
|
||||
|
|
@ -78,7 +77,7 @@ describe(
|
|||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad(1, 0, "v2");
|
||||
//Delete the test data
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "CoffeeCafe",
|
||||
action: "Delete",
|
||||
|
|
|
|||
|
|
@ -14,9 +14,7 @@ import EditorNavigation, {
|
|||
AppSidebar,
|
||||
AppSidebarButton,
|
||||
EntityType,
|
||||
PageLeftPane,
|
||||
} from "../../../../support/Pages/EditorNavigation";
|
||||
import { featureFlagIntercept } from "../../../../support/Objects/FeatureFlags";
|
||||
import PageList from "../../../../support/Pages/PageList";
|
||||
|
||||
let dsName: any;
|
||||
|
|
@ -55,7 +53,7 @@ describe(
|
|||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
//Delete the test data
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "Page2",
|
||||
action: "Delete",
|
||||
|
|
@ -123,7 +121,7 @@ describe(
|
|||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
//Delete the test data
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "Employees",
|
||||
action: "Delete",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import EditorNavigation, {
|
|||
AppSidebar,
|
||||
AppSidebarButton,
|
||||
EntityType,
|
||||
PageLeftPane,
|
||||
} from "../../../../support/Pages/EditorNavigation";
|
||||
import PageList from "../../../../support/Pages/PageList";
|
||||
|
||||
|
|
@ -50,7 +49,7 @@ describe(
|
|||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
//Delete the test data
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "Page2",
|
||||
action: "Delete",
|
||||
|
|
@ -116,7 +115,7 @@ describe(
|
|||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
//Delete the test data
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "Public.orders",
|
||||
action: "Delete",
|
||||
|
|
|
|||
|
|
@ -142,20 +142,10 @@ describe(
|
|||
// });
|
||||
|
||||
//Create Dummy Page2 :
|
||||
cy.CreatePage();
|
||||
cy.wait("@createPage").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
201,
|
||||
);
|
||||
PageList.AddNewPage();
|
||||
|
||||
//Creating CRUD Page3
|
||||
cy.CreatePage();
|
||||
cy.wait("@createPage").should(
|
||||
"have.nested.property",
|
||||
"response.body.responseMeta.status",
|
||||
201,
|
||||
);
|
||||
PageList.AddNewPage();
|
||||
|
||||
cy.get("@dSName").then((dbName) => {
|
||||
PageList.AddNewPage("Generate page with data");
|
||||
|
|
@ -227,7 +217,7 @@ describe(
|
|||
});
|
||||
|
||||
it("4. Generate CRUD page from the page menu", function () {
|
||||
cy.GenerateCRUD();
|
||||
PageList.AddNewPage("Generate page with data");
|
||||
cy.NavigateToDSGeneratePage(datasourceName);
|
||||
// fetch bucket
|
||||
cy.wait("@getDatasourceStructure").should(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import {
|
|||
} from "../../../../support/Objects/ObjectsCore";
|
||||
import EditorNavigation, {
|
||||
EntityType,
|
||||
PageLeftPane,
|
||||
} from "../../../../support/Pages/EditorNavigation";
|
||||
import PageList from "../../../../support/Pages/PageList";
|
||||
|
||||
|
|
@ -728,7 +727,7 @@ describe(
|
|||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad(0, 0, "v2");
|
||||
//Delete the test data
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "AuthorNAwards",
|
||||
action: "Delete",
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import oneClickBindingLocator from "../../../locators/OneClickBindingLocator";
|
|||
import { OneClickBinding } from "../../Regression/ClientSide/OneClickBinding/spec_utility";
|
||||
import EditorNavigation, {
|
||||
EntityType,
|
||||
PageLeftPane,
|
||||
} from "../../../support/Pages/EditorNavigation";
|
||||
import PageList from "../../../support/Pages/PageList";
|
||||
|
||||
|
|
@ -308,7 +307,7 @@ describe(
|
|||
deployMode.NavigateBacktoEditor();
|
||||
table.WaitUntilTableLoad();
|
||||
//Delete the test data
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
entityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: "Page2",
|
||||
action: "Delete",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"formWidgets": ".t--page-sidebar-FormWidgets",
|
||||
"viewWidgets": ".t--page-sidebar-ViewWidgets",
|
||||
"widgetsEditor": ".t--nav-link-widgets-editor",
|
||||
"AddPage": ".pages .t--entity-add-btn",
|
||||
"Menuaction": ".bp3-overlay-open>.bp3-transition-container",
|
||||
"Delete": ":nth-child(2) > .bp3-menu-item",
|
||||
"apiEditorIcon": ".t--nav-link-api-editor",
|
||||
|
|
|
|||
|
|
@ -81,7 +81,6 @@
|
|||
"evaluatedCurrentValue": "div:last-of-type .t--CodeEditor-evaluatedValue > div:last-of-type pre",
|
||||
"entityExplorersearch": "#entity-explorer-search",
|
||||
"saveStatusContainer": ".t--save-status-container",
|
||||
"saveStatusIsSaving": "t--save-status-is-saving",
|
||||
"statusSaving": ".t--save-status-is-saving",
|
||||
"saveStatusError": ".t--save-status-error",
|
||||
"selectWidgetVirtualList": ".menu-virtual-list div",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
"NoApiMsg": "p:contains('No APIs yet.')",
|
||||
"NoQueryMsg": "p:contains('No DB Queries yet.')",
|
||||
"NoWidgetsMsg": "p:contains('icon above to add widgets')",
|
||||
"AddPage": ".pages .t--entity-add-btn",
|
||||
"createQueryMenu": ".file-ops",
|
||||
"entityExplorer": ".t--entity-explorer",
|
||||
"popover": "//div[contains(@class,'t--entity page')]//*[local-name()='g' and @id='Icon/Outline/more-vertical']",
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { ObjectsRegistry as _ } from "../Objects/Registry";
|
|||
import ClickOptions = Cypress.ClickOptions;
|
||||
import { Sidebar } from "./IDE/Sidebar";
|
||||
import { LeftPane } from "./IDE/LeftPane";
|
||||
import PageList from "./PageList";
|
||||
|
||||
export enum AppSidebarButton {
|
||||
Data = "Data",
|
||||
|
|
@ -79,7 +80,7 @@ class EditorNavigation {
|
|||
|
||||
NavigateToPage(name: string, networkCallAlias = false) {
|
||||
AppSidebar.navigate(AppSidebarButton.Editor);
|
||||
PageLeftPane.expandCollapseItem("Pages");
|
||||
PageList.ShowList();
|
||||
PageLeftPane.selectItem(name, { multiple: true, force: true });
|
||||
_.AggregateHelper.Sleep(); //for selection to settle
|
||||
networkCallAlias && _.AssertHelper.AssertNetworkStatus("pageSnap");
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import EditorNavigation, {
|
|||
PageLeftPane,
|
||||
PagePaneSegment,
|
||||
} from "./EditorNavigation";
|
||||
import PageList from "./PageList";
|
||||
|
||||
type templateActions =
|
||||
| "Find"
|
||||
|
|
@ -255,6 +256,7 @@ export class EntityExplorer {
|
|||
viaMenu = false,
|
||||
) {
|
||||
AppSidebar.navigate(AppSidebarButton.Editor);
|
||||
PageList.ShowList();
|
||||
if (viaMenu)
|
||||
this.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: entityName,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class PageList {
|
|||
`.t--entity.page:contains('${pageName}')`,
|
||||
newButton: ".pages .t--entity-add-btn",
|
||||
newPageOption: (option: string) => `//span[text()='${option}']/parent::div`,
|
||||
switcher: `.t--pages-switcher`,
|
||||
};
|
||||
|
||||
public AddNewPage(
|
||||
|
|
@ -20,12 +21,14 @@ class PageList {
|
|||
| "Add page from template" = "New blank page",
|
||||
) {
|
||||
AppSidebar.navigate(AppSidebarButton.Editor);
|
||||
this.ShowList();
|
||||
ObjectsRegistry.AggregateHelper.GetNClick(this.locators.newButton);
|
||||
ObjectsRegistry.AggregateHelper.GetNClick(
|
||||
this.locators.newPageOption(option),
|
||||
);
|
||||
if (option === "New blank page") {
|
||||
ObjectsRegistry.AssertHelper.AssertNetworkStatus("@createPage", 201);
|
||||
|
||||
return cy
|
||||
.get("@createPage")
|
||||
.then(($pageName: any) => $pageName.response?.body.data.name);
|
||||
|
|
@ -33,6 +36,7 @@ class PageList {
|
|||
}
|
||||
|
||||
public VerifyIsCurrentPage(pageName: string) {
|
||||
this.ShowList();
|
||||
ObjectsRegistry.AggregateHelper.GetElement(
|
||||
this.locators.pageListItem(pageName),
|
||||
).should("have.class", "activePage");
|
||||
|
|
@ -44,6 +48,7 @@ class PageList {
|
|||
|
||||
public ClonePage(pageName = "Page1") {
|
||||
AppSidebar.navigate(AppSidebarButton.Editor);
|
||||
this.ShowList();
|
||||
EditorNavigation.SelectEntityByName(pageName, EntityType.Page);
|
||||
ObjectsRegistry.EntityExplorer.ActionContextMenuByEntityName({
|
||||
entityNameinLeftSidebar: pageName,
|
||||
|
|
@ -52,17 +57,41 @@ class PageList {
|
|||
ObjectsRegistry.AssertHelper.AssertNetworkStatus("@clonePage", 201);
|
||||
}
|
||||
|
||||
public ShowList() {
|
||||
cy.get(this.locators.switcher).then(($switcher) => {
|
||||
const isActive: string | undefined = $switcher.attr("data-active");
|
||||
if (isActive === "false") {
|
||||
cy.get(this.locators.switcher).click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
assertPresence(pageName: string) {
|
||||
this.ShowList();
|
||||
ObjectsRegistry.AggregateHelper.AssertElementVisibility(
|
||||
this.locators.pageListItem(pageName),
|
||||
);
|
||||
}
|
||||
|
||||
assertAbsence(pageName: string) {
|
||||
this.ShowList();
|
||||
ObjectsRegistry.AggregateHelper.AssertElementAbsence(
|
||||
this.locators.pageListItem(pageName),
|
||||
);
|
||||
}
|
||||
|
||||
DeletePage(name: string) {
|
||||
this.ShowList();
|
||||
cy.get(this.locators.pageListItem(name)).within(() => {
|
||||
cy.get(".t--context-menu").click({ force: true });
|
||||
});
|
||||
cy.wait(2000);
|
||||
cy.selectAction("Delete");
|
||||
cy.selectAction("Are you sure?");
|
||||
cy.wait("@deletePage")
|
||||
.its("response.body.responseMeta.status")
|
||||
.should("eq", 200);
|
||||
}
|
||||
}
|
||||
|
||||
export default new PageList();
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { ANVIL_EDITOR_TEST } from "./Constants.js";
|
|||
|
||||
import EditorNavigation, {
|
||||
EntityType,
|
||||
AppSidebarButton,
|
||||
AppSidebar,
|
||||
PageLeftPane,
|
||||
PagePaneSegment,
|
||||
|
|
@ -24,7 +23,6 @@ const loginPage = require("../locators/LoginPage.json");
|
|||
const signupPage = require("../locators/SignupPage.json");
|
||||
import homePage from "../locators/HomePage";
|
||||
|
||||
const pages = require("../locators/Pages.json");
|
||||
const commonlocators = require("../locators/commonlocators.json");
|
||||
const widgetsPage = require("../locators/Widgets.json");
|
||||
import ApiEditor from "../locators/ApiEditor";
|
||||
|
|
@ -390,14 +388,6 @@ Cypress.Commands.add("DeleteApp", (appName) => {
|
|||
cy.get(homePage.deleteApp).contains("Are you sure?").click({ force: true });
|
||||
});
|
||||
|
||||
Cypress.Commands.add("DeletepageFromSideBar", () => {
|
||||
cy.xpath(pages.popover).last().click({ force: true });
|
||||
cy.get(pages.deletePage).first().click({ force: true });
|
||||
cy.get(pages.deletePageConfirm).first().click({ force: true });
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(2000);
|
||||
});
|
||||
|
||||
Cypress.Commands.add("LogOut", (toCheckgetPluginForm = true) => {
|
||||
agHelper.WaitUntilAllToastsDisappear();
|
||||
//Since these are coming in every self-hosted 1st time login, commenting for CI runs
|
||||
|
|
@ -1952,22 +1942,6 @@ Cypress.Commands.add(
|
|||
},
|
||||
);
|
||||
|
||||
Cypress.Commands.add("CreatePage", () => {
|
||||
AppSidebar.navigate(AppSidebarButton.Editor);
|
||||
cy.get(pages.AddPage).first().click();
|
||||
cy.xpath("//span[text()='New blank page']/parent::div").click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add("GenerateCRUD", () => {
|
||||
cy.get(pages.AddPage).first().click();
|
||||
cy.xpath("//span[text()='Generate page with data']/parent::div").click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add("AddPageFromTemplate", () => {
|
||||
cy.get(pages.AddPage).first().click();
|
||||
cy.xpath("//span[text()='Add page from template']/parent::div").click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add(`verifyCallCount`, (alias, expectedNumberOfCalls) => {
|
||||
cy.wait(alias);
|
||||
cy.get(`${alias}.all`).should("have.length", expectedNumberOfCalls);
|
||||
|
|
|
|||
179
app/client/cypress/support/index.d.ts
vendored
Normal file
179
app/client/cypress/support/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
/// <reference types="cypress" />
|
||||
|
||||
declare namespace Cypress {
|
||||
interface Chainable<Subject> {
|
||||
SignupFromAPI(uname: string, password: string);
|
||||
dragTo(subject: any, targetEl: any);
|
||||
downloadData(filetype: string);
|
||||
validateDownload(fileName: string);
|
||||
AddFilterWithOperator(
|
||||
operator: string,
|
||||
option: string,
|
||||
condition: string,
|
||||
value: string,
|
||||
);
|
||||
stubPostHeaderReq();
|
||||
addOAuth2ClientCredentialsDetails(
|
||||
accessTokenUrl: string,
|
||||
clientId: string,
|
||||
clientSecret: string,
|
||||
scope: string,
|
||||
);
|
||||
addOAuth2AuthorizationCodeDetails(
|
||||
accessTokenUrl: string,
|
||||
clientId: string,
|
||||
clientSecret: string,
|
||||
authURL: string,
|
||||
);
|
||||
testSelfSignedCertificateSettingsInREST(isOAuth2: boolean);
|
||||
addBasicProfileDetails(username: string, password: string);
|
||||
DeleteApp(appName: string);
|
||||
GetUrlQueryParams();
|
||||
LogOutUser();
|
||||
LoginUser(uname: string, pword: string, goToLoginPage?: boolean);
|
||||
LogintoApp(uname: string, pword: string);
|
||||
LogintoAppTestUser(uname: string, pword: string);
|
||||
Signup(uname: string, pword: string);
|
||||
LoginFromAPI(uname: string, pword: string);
|
||||
DeletepageFromSideBar();
|
||||
LogOut(toCheckgetPluginForm?: boolean);
|
||||
SearchApp(appname: string);
|
||||
WaitAutoSave();
|
||||
SelectAction(action: string);
|
||||
ClearSearch();
|
||||
paste($element: any, text: string);
|
||||
clickTest(testbutton: string);
|
||||
EvaluateCurrentValue(
|
||||
currentValue: string,
|
||||
isValueToBeEvaluatedDynamic?: boolean,
|
||||
);
|
||||
tabPopertyUpdate(tabId: string, newTabName: string);
|
||||
generateUUID();
|
||||
addDsl(dsl: any);
|
||||
DeleteAppByApi();
|
||||
DeleteWorkspaceByApi();
|
||||
togglebar(value: string);
|
||||
radiovalue(value: string, value2: string);
|
||||
optionValue(value: string, value2: string);
|
||||
typeIntoDraftEditor(selector: string, text: string);
|
||||
getPluginFormsAndCreateDatasource();
|
||||
NavigateToJSEditor();
|
||||
importCurl();
|
||||
selectAction(option: string);
|
||||
deleteActionAndConfirm();
|
||||
deleteJSObject();
|
||||
deleteDataSource();
|
||||
dragAndDropToCanvas(widgetType: string, { x: number, y: number });
|
||||
dragAndDropToWidget(
|
||||
widgetType: string,
|
||||
destinationWidget: string,
|
||||
{ x: number, y: number },
|
||||
);
|
||||
dragAndDropToWidgetBySelector(
|
||||
widgetType: string,
|
||||
destinationSelector: string,
|
||||
{ x: number, y: number },
|
||||
);
|
||||
changeButtonColor(buttonColor: string);
|
||||
closePropertyPane();
|
||||
onClickActions(
|
||||
forSuccess: string,
|
||||
forFailure: string,
|
||||
actionType: string,
|
||||
actionValue: string,
|
||||
idx?: number,
|
||||
);
|
||||
isSelectRow(index: number);
|
||||
getDate(date: number, dateFormate: string);
|
||||
setDate(date: number, dateFormate: string);
|
||||
pageNo();
|
||||
pageNoValidate(index: number);
|
||||
validateDisableWidget(widgetCss: string, disableCss: string);
|
||||
validateToolbarVisible(widgetCss: string, toolbarCss: string);
|
||||
validateToolbarHidden(widgetCss: string, toolbarCss: string);
|
||||
validateEnableWidget(widgetCss: string, disableCss: string);
|
||||
validateHTMLText(widgetCss: string, htmlTag: string, value: string);
|
||||
setTinyMceContent(tinyMceId: string, content: string);
|
||||
startRoutesForDatasource();
|
||||
startServerAndRoutes();
|
||||
startErrorRoutes();
|
||||
NavigateToPaginationTab();
|
||||
ValidateTableData(value: string);
|
||||
ValidateTableV2Data(value: string);
|
||||
ValidatePublishTableData(value: string);
|
||||
ValidatePublishTableV2Data(value: string);
|
||||
ValidatePaginateResponseUrlData(runTestCss: string);
|
||||
ValidatePaginateResponseUrlDataV2(runTestCss: string);
|
||||
ValidatePaginationInputData(valueToTest: string);
|
||||
ValidatePaginationInputDataV2(valueToTest: string);
|
||||
CheckForPageSaveError();
|
||||
assertPageSave(validateSavedState?: boolean);
|
||||
validateCodeEditorContent(selector: string, contentToValidate: string);
|
||||
updateMapType(mapType: string);
|
||||
createJSObject(JSCode: string);
|
||||
createSuperUser();
|
||||
SignupFromAPI(uname: string, pword: string);
|
||||
startInterceptRoutesForMySQL();
|
||||
startInterceptRoutesForMongo();
|
||||
startInterceptRoutesForS3();
|
||||
replaceApplicationIdForInterceptPages(fixtureFile: string);
|
||||
paste(selector: string, pastePayload: string);
|
||||
typeValueNValidate(
|
||||
valueToType: string,
|
||||
fieldName?: string,
|
||||
isDynamic?: boolean,
|
||||
);
|
||||
checkCodeInputValue(selector: string);
|
||||
clickButton(btnVisibleText: string, toForceClick?: boolean);
|
||||
actionContextMenuByEntityName(
|
||||
entityNameinLeftSidebar: string,
|
||||
action?: string,
|
||||
subActions: string,
|
||||
);
|
||||
selectEntityByName(entityNameinLeftSidebar: string);
|
||||
EvaluatFieldValue(fieldName?: string, currentValue?: string);
|
||||
renameWithInPane(renameVal: string);
|
||||
getEntityName();
|
||||
VerifyErrorMsgAbsence(errorMsgToVerifyAbsence: string);
|
||||
VerifyErrorMsgPresence(errorMsgToVerifyAbsence: string);
|
||||
setQueryTimeout(timeout: string);
|
||||
VerifyNoDataDisplayAbsence();
|
||||
isNotInViewport(element: string);
|
||||
isInViewport(element: string);
|
||||
CheckAndUnfoldEntityItem(item: string);
|
||||
DeleteEntityStateLocalStorage();
|
||||
checkLabelForWidget(options: string);
|
||||
saveLocalStorageCache();
|
||||
restoreLocalStorageCache();
|
||||
StopContainer(path: string, containerName: string);
|
||||
StopAllContainer(path: string);
|
||||
StartContainer(path: string, containerName: string);
|
||||
StartNewContainer(
|
||||
url: string,
|
||||
path: string,
|
||||
version: string,
|
||||
containerName: string,
|
||||
);
|
||||
GetPath(path: string, containerName: string);
|
||||
GetCWD(path: string);
|
||||
GetAndVerifyLogs(path: string, containerName: string);
|
||||
typeTab();
|
||||
CreatePage();
|
||||
GenerateCRUD();
|
||||
AddPageFromTemplate();
|
||||
verifyCallCount(alias: string, expectedNumberOfCalls: number);
|
||||
RenameWidgetFromPropertyPane(
|
||||
widgetType: string,
|
||||
oldName: string,
|
||||
newName: string,
|
||||
);
|
||||
forceVisit(url: string);
|
||||
SelectDropDown(dropdownOption: string);
|
||||
RemoveMultiSelectItems(dropdownOptions: string[]);
|
||||
RemoveAllSelections();
|
||||
SelectFromMultiSelect(options: string);
|
||||
skipSignposting();
|
||||
stubPricingPage();
|
||||
validateEvaluatedValue(value: string);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
/* eslint-disable cypress/no-unnecessary-waiting */
|
||||
/* eslint-disable cypress/no-assigning-return-values */
|
||||
|
||||
import PageList from "./Pages/PageList";
|
||||
|
||||
require("cy-verify-downloads").addCustomCommand();
|
||||
require("cypress-file-upload");
|
||||
const commonlocators = require("../locators/commonlocators.json");
|
||||
|
|
@ -929,31 +931,17 @@ Cypress.Commands.add("DeleteModal", () => {
|
|||
});
|
||||
|
||||
Cypress.Commands.add("Createpage", (pageName, navigateToCanvasPage = true) => {
|
||||
cy.CreatePage();
|
||||
cy.wait("@createPage").then((xhr) => {
|
||||
expect(xhr.response.body.responseMeta.status).to.equal(201);
|
||||
PageList.AddNewPage().then((oldPageName) => {
|
||||
if (pageName) {
|
||||
const pageId = xhr.response.body.data.id;
|
||||
const oldPageName = xhr.response.body.data.name;
|
||||
cy.wait(2000);
|
||||
ee.RenameEntityFromExplorer(oldPageName, pageName, true);
|
||||
cy.wrap(pageId).as("currentPageId");
|
||||
}
|
||||
cy.get("#loading").should("not.exist");
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add("Deletepage", (Pagename) => {
|
||||
cy.CheckAndUnfoldEntityItem("Pages");
|
||||
cy.get(`.t--entity-item:contains(${Pagename})`).within(() => {
|
||||
cy.get(".t--context-menu").click({ force: true });
|
||||
cy.get("@createPage").then((xhr) => {
|
||||
const pageId = xhr.response.body.data.id;
|
||||
cy.wrap(pageId).as("currentPageId");
|
||||
});
|
||||
cy.wait(2000);
|
||||
cy.selectAction("Delete");
|
||||
cy.selectAction("Are you sure?");
|
||||
cy.wait("@deletePage")
|
||||
.its("response.body.responseMeta.status")
|
||||
.should("eq", 200);
|
||||
});
|
||||
|
||||
Cypress.Commands.add("dropdownDynamic", (text) => {
|
||||
|
|
|
|||
|
|
@ -110,8 +110,8 @@
|
|||
"d3-geo": "^3.1.0",
|
||||
"dayjs": "^1.10.6",
|
||||
"deep-diff": "^1.0.2",
|
||||
"design-system": "npm:@appsmithorg/design-system@2.1.35",
|
||||
"design-system-old": "npm:@appsmithorg/design-system-old@1.1.15",
|
||||
"design-system": "npm:@appsmithorg/design-system@2.1.36",
|
||||
"design-system-old": "npm:@appsmithorg/design-system-old@1.1.16",
|
||||
"downloadjs": "^1.4.7",
|
||||
"echarts": "^5.4.2",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import type {
|
|||
EvaluationReduxAction,
|
||||
AnyReduxAction,
|
||||
ReduxAction,
|
||||
ReduxActionWithoutPayload,
|
||||
} from "@appsmith/constants/ReduxActionConstants";
|
||||
import type { JSUpdate } from "utils/JSPaneUtils";
|
||||
import {
|
||||
|
|
@ -11,6 +10,7 @@ import {
|
|||
ReduxActionTypes,
|
||||
} from "@appsmith/constants/ReduxActionConstants";
|
||||
import type { Action, ActionViewMode } from "entities/Action";
|
||||
import { ActionExecutionContext } from "entities/Action";
|
||||
import { batchAction } from "actions/batchActions";
|
||||
import type { ExecuteErrorPayload } from "constants/AppsmithActionConstants/ActionConstants";
|
||||
import type { ModalInfo } from "reducers/uiReducers/modalActionReducer";
|
||||
|
|
@ -107,6 +107,8 @@ export const runAction = (
|
|||
id: string,
|
||||
paginationField?: PaginationField,
|
||||
skipOpeningDebugger = false,
|
||||
action = undefined,
|
||||
actionExecutionContext = ActionExecutionContext.SELF,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.RUN_ACTION_REQUEST,
|
||||
|
|
@ -114,6 +116,8 @@ export const runAction = (
|
|||
id,
|
||||
paginationField,
|
||||
skipOpeningDebugger,
|
||||
action,
|
||||
actionExecutionContext,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -314,9 +318,16 @@ export const updateActionProperty = (
|
|||
});
|
||||
};
|
||||
|
||||
export const executePageLoadActions = (): ReduxActionWithoutPayload => ({
|
||||
type: ReduxActionTypes.EXECUTE_PAGE_LOAD_ACTIONS,
|
||||
});
|
||||
export const executePageLoadActions = (
|
||||
actionExecutionContext?: ActionExecutionContext,
|
||||
) => {
|
||||
return {
|
||||
type: ReduxActionTypes.EXECUTE_PAGE_LOAD_ACTIONS,
|
||||
payload: {
|
||||
actionExecutionContext,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const executeJSUpdates = (
|
||||
payload: Record<string, JSUpdate>,
|
||||
|
|
|
|||
|
|
@ -47,9 +47,15 @@ export const createModalAction = (
|
|||
|
||||
export const focusWidget = (
|
||||
widgetId?: string,
|
||||
): ReduxAction<{ widgetId?: string }> => ({
|
||||
alt?: boolean,
|
||||
): ReduxAction<{ widgetId?: string; alt?: boolean }> => ({
|
||||
type: ReduxActionTypes.FOCUS_WIDGET,
|
||||
payload: { widgetId },
|
||||
payload: { widgetId, alt },
|
||||
});
|
||||
|
||||
export const altFocusWidget = (alt: boolean) => ({
|
||||
type: ReduxActionTypes.ALT_FOCUS_WIDGET,
|
||||
payload: alt,
|
||||
});
|
||||
|
||||
export const showModal = (id: string, shouldSelectModal = true) => {
|
||||
|
|
@ -144,3 +150,10 @@ export const partialExportWidgets = (params: PartialExportParams) => {
|
|||
payload: params,
|
||||
};
|
||||
};
|
||||
|
||||
export const setWidgetSelectionBlock = (payload: boolean) => {
|
||||
return {
|
||||
type: ReduxActionTypes.SET_WIDGET_SELECTION_BLOCK,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -68,23 +68,6 @@ class AppThemingApi extends API {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* fires api for saving current theme
|
||||
*
|
||||
* @param applicationId
|
||||
* @param theme
|
||||
* @returns
|
||||
*/
|
||||
static async saveTheme(
|
||||
applicationId: string,
|
||||
payload: { name: string },
|
||||
): Promise<AxiosPromise<ApiResponse<AppTheme[]>>> {
|
||||
return API.patch(
|
||||
`${AppThemingApi.baseUrl}/themes/applications/${applicationId}`,
|
||||
payload,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* fires api for deleting theme
|
||||
*
|
||||
|
|
|
|||
|
|
@ -129,3 +129,7 @@ export const fetchEntitiesOfWorkspace = (payload: { workspaceId?: string }) => {
|
|||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
export const resetImportData = () => ({
|
||||
type: ReduxActionTypes.RESET_IMPORT_DATA,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import type { PluginType } from "entities/Action";
|
||||
|
||||
type ID = string;
|
||||
|
||||
export enum MODULE_TYPE {
|
||||
|
|
@ -15,9 +17,17 @@ export interface ModuleInputSection {
|
|||
children?: ModuleInput[];
|
||||
}
|
||||
|
||||
export interface Module {
|
||||
export interface Module extends ModuleMetadata {
|
||||
id: ID;
|
||||
name: string;
|
||||
packageId: ID;
|
||||
inputsForm: ModuleInputSection[];
|
||||
type: MODULE_TYPE;
|
||||
}
|
||||
|
||||
export interface ModuleMetadata {
|
||||
moduleId: string;
|
||||
datasourceId?: string;
|
||||
pluginId: string;
|
||||
pluginType: PluginType;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ export interface ModuleInstance {
|
|||
inputs: {
|
||||
[key: string]: string;
|
||||
};
|
||||
sourceModuleId: ModuleId;
|
||||
}
|
||||
|
||||
export interface ModuleInstanceData {
|
||||
|
|
|
|||
|
|
@ -546,6 +546,7 @@ const ActionTypes = {
|
|||
IMPORT_APPLICATION_FROM_GIT_INIT: "IMPORT_APPLICATION_FROM_GIT_INIT",
|
||||
IMPORT_APPLICATION_SUCCESS: "IMPORT_APPLICATION_SUCCESS",
|
||||
SET_WIDGET_LOADING: "SET_WIDGET_LOADING",
|
||||
RESET_IMPORT_DATA: "RESET_IMPORT_DATA",
|
||||
SET_GLOBAL_SEARCH_QUERY: "SET_GLOBAL_SEARCH_QUERY",
|
||||
SET_GLOBAL_SEARCH_CATEGORY: "SET_GLOBAL_SEARCH_CATEGORY",
|
||||
TOGGLE_SHOW_GLOBAL_SEARCH_MODAL: "TOGGLE_SHOW_GLOBAL_SEARCH_MODAL",
|
||||
|
|
@ -687,7 +688,6 @@ const ActionTypes = {
|
|||
CHANGE_SELECTED_APP_THEME_SUCCESS: "CHANGE_SELECTED_APP_THEME_SUCCESS",
|
||||
SET_PREVIEW_APP_THEME: "SET_PREVIEW_APP_THEME",
|
||||
SAVE_APP_THEME_INIT: "SAVE_APP_THEME_INIT",
|
||||
SAVE_APP_THEME_SUCCESS: "SAVE_APP_THEME_SUCCESS",
|
||||
DELETE_APP_THEME_INIT: "DELETE_APP_THEME_INIT",
|
||||
DELETE_APP_THEME_SUCCESS: "DELETE_APP_THEME_SUCCESS",
|
||||
RESET_APP_THEME_INIT: "RESET_APP_THEME_INIT",
|
||||
|
|
@ -917,6 +917,8 @@ const ActionTypes = {
|
|||
SET_API_PANE_DEBUGGER_STATE: "SET_API_PANE_DEBUGGER_STATE",
|
||||
SET_JS_PANE_DEBUGGER_STATE: "SET_JS_PANE_DEBUGGER_STATE",
|
||||
SET_CANVAS_DEBUGGER_STATE: "SET_CANVAS_DEBUGGER_STATE",
|
||||
SET_WIDGET_SELECTION_BLOCK: "SET_WIDGET_SELECTION_BLOCK",
|
||||
ALT_FOCUS_WIDGET: "ALT_FOCUS_WIDGET",
|
||||
};
|
||||
|
||||
export const ReduxActionTypes = {
|
||||
|
|
@ -1078,7 +1080,6 @@ export const ReduxActionErrorTypes = {
|
|||
UPDATE_JS_FUNCTION_PROPERTY_ERROR: "UPDATE_JS_FUNCTION_PROPERTY_ERROR",
|
||||
DELETE_WORKSPACE_ERROR: "DELETE_WORKSPACE_ERROR",
|
||||
REFLOW_BETA_FLAGS_INIT_ERROR: "REFLOW_BETA_FLAGS_INIT_ERROR",
|
||||
SAVE_APP_THEME_ERROR: "SAVE_APP_THEME_ERROR",
|
||||
DELETE_APP_THEME_ERROR: "DELETE_APP_THEME_ERROR",
|
||||
GET_ALL_TEMPLATES_ERROR: "GET_ALL_TEMPLATES_ERROR",
|
||||
GET_SIMILAR_TEMPLATES_ERROR: "GET_SIMILAR_TEMPLATES_ERROR",
|
||||
|
|
|
|||
|
|
@ -2459,3 +2459,8 @@ export const CREATE_A_NEW_ITEM = (item: string) => `Create a new ${item}`;
|
|||
export const MAXIMIZE_BUTTON_TOOLTIP = () =>
|
||||
`Expand code editor to full-screen`;
|
||||
export const MINIMIZE_BUTTON_TOOLTIP = () => `Open code editor next to the UI`;
|
||||
export const SPLITPANE_ANNOUNCEMENT = {
|
||||
TITLE: () => "Code and UI, side-by-side",
|
||||
DESCRIPTION: () =>
|
||||
"Write queries and JS functions while you refer to the UI on the side! This is a beta version that we will continue to improve with your feedback.",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ interface ResourcesLoaderProps {
|
|||
|
||||
const DEFAULT_BACKGROUND_COLOR = "#9747FF1A";
|
||||
const DEFAULT_ICON = "book";
|
||||
const DEAFULT_RESOURCES = [{ name: "Default Resource" }];
|
||||
const DEAFULT_RESOURCES = [{ id: "default", name: "Default Resource" }];
|
||||
|
||||
function ResourceListLoader({ isMobile, resources }: ResourcesLoaderProps) {
|
||||
const resourcesToUse = resources?.length ? resources : DEAFULT_RESOURCES;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import {
|
|||
createMessage,
|
||||
INVITE_USERS_PLACEHOLDER,
|
||||
NO_APPS_FOUND,
|
||||
NO_WORKSPACE_DESCRIPTION,
|
||||
NO_WORKSPACE_HEADING,
|
||||
WORKSPACES_HEADING,
|
||||
} from "@appsmith/constants/messages";
|
||||
|
|
@ -370,7 +369,6 @@ export function WorkspaceMenuItem({
|
|||
isFetchingWorkspaces ? 100 : 22
|
||||
} /* this is to avoid showing tooltip for loaders */
|
||||
icon="group-2-line"
|
||||
key={workspace?.id}
|
||||
onSelect={handleWorkspaceClick}
|
||||
selected={selected}
|
||||
text={workspace?.name}
|
||||
|
|
@ -387,8 +385,8 @@ export const submitCreateWorkspaceForm = async (data: any, dispatch: any) => {
|
|||
export interface LeftPaneProps {
|
||||
isBannerVisible?: boolean;
|
||||
isFetchingWorkspaces: boolean;
|
||||
workspaces: any;
|
||||
activeWorkspaceId: string | undefined;
|
||||
workspaces: Workspace[];
|
||||
activeWorkspaceId?: string;
|
||||
}
|
||||
|
||||
export function LeftPane(props: LeftPaneProps) {
|
||||
|
|
@ -396,7 +394,7 @@ export function LeftPane(props: LeftPaneProps) {
|
|||
activeWorkspaceId,
|
||||
isBannerVisible = false,
|
||||
isFetchingWorkspaces,
|
||||
workspaces,
|
||||
workspaces = [],
|
||||
} = props;
|
||||
const isMobile = useIsMobileDevice();
|
||||
|
||||
|
|
@ -409,18 +407,14 @@ export function LeftPane(props: LeftPaneProps) {
|
|||
isFetchingWorkspaces={isFetchingWorkspaces}
|
||||
>
|
||||
<WorkpsacesNavigator data-testid="t--left-panel">
|
||||
{workspaces &&
|
||||
workspaces.map(
|
||||
(workspace: any) =>
|
||||
workspace && (
|
||||
<WorkspaceMenuItem
|
||||
isFetchingWorkspaces={isFetchingWorkspaces}
|
||||
key={workspace?.id}
|
||||
selected={workspace?.id === activeWorkspaceId}
|
||||
workspace={workspace}
|
||||
/>
|
||||
),
|
||||
)}
|
||||
{workspaces.map((workspace) => (
|
||||
<WorkspaceMenuItem
|
||||
isFetchingWorkspaces={isFetchingWorkspaces}
|
||||
key={workspace.id}
|
||||
selected={workspace.id === activeWorkspaceId}
|
||||
workspace={workspace}
|
||||
/>
|
||||
))}
|
||||
</WorkpsacesNavigator>
|
||||
</LeftPaneSection>
|
||||
</LeftPaneWrapper>
|
||||
|
|
@ -565,11 +559,14 @@ export function ApplicationsSection(props: any) {
|
|||
setSelectedWorkspaceIdForImportApplication,
|
||||
]);
|
||||
|
||||
const leaveWS = (workspaceId: string) => {
|
||||
setWarnLeavingWorkspace(false);
|
||||
setWorkspaceToOpenMenu(null);
|
||||
dispatch(leaveWorkspace(workspaceId));
|
||||
};
|
||||
const leaveWS = useCallback(
|
||||
(workspaceId: string) => {
|
||||
setWarnLeavingWorkspace(false);
|
||||
setWorkspaceToOpenMenu(null);
|
||||
dispatch(leaveWorkspace(workspaceId));
|
||||
},
|
||||
[dispatch],
|
||||
);
|
||||
|
||||
const handleDeleteWorkspace = useCallback(
|
||||
(workspaceId: string) => {
|
||||
|
|
@ -657,9 +654,6 @@ export function ApplicationsSection(props: any) {
|
|||
<NewText className="!mb-3 !font-semibold" kind="heading-s">
|
||||
{createMessage(NO_WORKSPACE_HEADING)}
|
||||
</NewText>
|
||||
<NewText className="w-[328px]" kind="heading-xs">
|
||||
{createMessage(NO_WORKSPACE_DESCRIPTION)}
|
||||
</NewText>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -896,7 +890,9 @@ export const ApplictionsMainPage = (props: any) => {
|
|||
if (!isFetchingWorkspaces) {
|
||||
workspaces = fetchedWorkspaces;
|
||||
} else {
|
||||
workspaces = loadingUserWorkspaces as any;
|
||||
workspaces = loadingUserWorkspaces.map(
|
||||
(loadingWorkspaces) => loadingWorkspaces.workspace,
|
||||
) as any;
|
||||
}
|
||||
|
||||
const [activeWorkspaceId, setActiveWorkspaceId] = useState<
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ export const useQueryAdd = () => {
|
|||
|
||||
return addButtonClickHandler;
|
||||
};
|
||||
//history.push(location.pathname.replace(`${ADD_PATH}`, ""));
|
||||
|
||||
export type GroupedAddOperations = Array<{
|
||||
title?: string;
|
||||
|
|
@ -214,7 +213,7 @@ export const useAddQueryListItems = () => {
|
|||
fileOperation.entityExplorerTitle ||
|
||||
fileOperation.dsName ||
|
||||
fileOperation.title,
|
||||
description: "",
|
||||
description: !!fileOperation.isBeta ? "Beta" : "",
|
||||
descriptionType: "inline",
|
||||
onClick: onCreateItemClick.bind(null, fileOperation),
|
||||
} as ListItemProps;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
import { builderURL } from "@appsmith/RouteBuilder";
|
||||
import {
|
||||
RECONNECT_MISSING_DATASOURCE_CREDENTIALS_DESCRIPTION,
|
||||
SKIP_TO_APPLICATION,
|
||||
createMessage,
|
||||
} from "@appsmith/constants/messages";
|
||||
import { EditorNames } from "@appsmith/hooks";
|
||||
|
||||
interface UseReconnectModalDataProps {
|
||||
pageId: string | null;
|
||||
appId: string | null;
|
||||
}
|
||||
|
||||
function useReconnectModalData({ appId, pageId }: UseReconnectModalDataProps) {
|
||||
const editorURL =
|
||||
pageId &&
|
||||
builderURL({
|
||||
pageId,
|
||||
});
|
||||
|
||||
return {
|
||||
skipMessage: createMessage(SKIP_TO_APPLICATION),
|
||||
missingDsCredentialsDescription: createMessage(
|
||||
RECONNECT_MISSING_DATASOURCE_CREDENTIALS_DESCRIPTION,
|
||||
),
|
||||
editorURL,
|
||||
editorId: appId,
|
||||
parentEntityId: pageId,
|
||||
editorType: EditorNames.APPLICATION,
|
||||
};
|
||||
}
|
||||
|
||||
export default useReconnectModalData;
|
||||
|
|
@ -18,22 +18,13 @@ import {
|
|||
} from "constants/routes";
|
||||
import Navigation from "pages/AppViewer/Navigation";
|
||||
import type { RouteComponentProps } from "react-router";
|
||||
import AppEditorHeader from "pages/Editor/EditorHeader";
|
||||
import { Header } from "pages/Editor/IDE/Header";
|
||||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||
import { Header as AppIDEHeader } from "pages/Editor/IDE/Header";
|
||||
|
||||
export type Props = RouteComponentProps;
|
||||
|
||||
export const headerRoot = document.getElementById("header-root");
|
||||
|
||||
export const Routes = () => {
|
||||
const isSideBySideFlagEnabled = useFeatureFlag(
|
||||
FEATURE_FLAG.release_side_by_side_ide_enabled,
|
||||
);
|
||||
|
||||
const HeaderComponent = isSideBySideFlagEnabled ? Header : AppEditorHeader;
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Route component={PageHeader} path={ADMIN_SETTINGS_CATEGORY_PATH} />
|
||||
|
|
@ -46,10 +37,10 @@ export const Routes = () => {
|
|||
exact
|
||||
path={CUSTOM_WIDGETS_EDITOR_ID_PATH_CUSTOM}
|
||||
/>
|
||||
<Route component={HeaderComponent} path={BUILDER_PATH_DEPRECATED} />
|
||||
<Route component={AppIDEHeader} path={BUILDER_PATH_DEPRECATED} />
|
||||
<Route component={Navigation} path={VIEWER_PATH_DEPRECATED} />
|
||||
<Route component={HeaderComponent} path={BUILDER_PATH} />
|
||||
<Route component={HeaderComponent} path={BUILDER_CUSTOM_PATH} />
|
||||
<Route component={AppIDEHeader} path={BUILDER_PATH} />
|
||||
<Route component={AppIDEHeader} path={BUILDER_CUSTOM_PATH} />
|
||||
<Route component={Navigation} path={VIEWER_PATH} />
|
||||
<Route component={Navigation} path={VIEWER_CUSTOM_PATH} />
|
||||
<Route component={PageHeader} path={BASE_URL} />
|
||||
|
|
|
|||
|
|
@ -247,6 +247,12 @@ export const handlers = {
|
|||
importingApplication: false,
|
||||
};
|
||||
},
|
||||
[ReduxActionTypes.RESET_IMPORT_DATA]: (state: ApplicationsReduxState) => {
|
||||
return {
|
||||
...state,
|
||||
importedApplication: null,
|
||||
};
|
||||
},
|
||||
[ReduxActionTypes.PARTIAL_IMPORT_INIT]: (state: ApplicationsReduxState) => ({
|
||||
...state,
|
||||
partialImportExport: {
|
||||
|
|
|
|||
|
|
@ -20,8 +20,10 @@ import { flushErrors } from "actions/errorActions";
|
|||
import type { NavigationMethod } from "utils/history";
|
||||
import UsagePulse from "usagePulse";
|
||||
import { getIDETypeByUrl } from "@appsmith/entities/IDE/utils";
|
||||
import type { EditorViewMode } from "@appsmith/entities/IDE/constants";
|
||||
import { IDE_TYPE } from "@appsmith/entities/IDE/constants";
|
||||
import { updateIDETabsOnRouteChangeSaga } from "sagas/IDESaga";
|
||||
import { getIDEViewMode } from "selectors/ideSelectors";
|
||||
|
||||
let previousPath: string;
|
||||
|
||||
|
|
@ -110,6 +112,7 @@ function* logNavigationAnalytics(payload: RouteChangeActionPayload) {
|
|||
const isRecent = recentEntityIds.some(
|
||||
(entityId) => entityId === currentEntity.id,
|
||||
);
|
||||
const ideViewMode: EditorViewMode = yield select(getIDEViewMode);
|
||||
const { height, width } = window.screen;
|
||||
AnalyticsUtil.logEvent("ROUTE_CHANGE", {
|
||||
toPath: pathname,
|
||||
|
|
@ -121,6 +124,7 @@ function* logNavigationAnalytics(payload: RouteChangeActionPayload) {
|
|||
fromType: previousEntity.entity,
|
||||
screenHeight: height,
|
||||
screenWidth: width,
|
||||
editorMode: ideViewMode,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ import type { DSLWidget } from "WidgetProvider/constants";
|
|||
import type { FeatureFlags } from "@appsmith/entities/FeatureFlag";
|
||||
import { getIsServerDSLMigrationsEnabled } from "selectors/pageSelectors";
|
||||
import { getCurrentWorkspaceId } from "@appsmith/selectors/selectedWorkspaceSelectors";
|
||||
import { ActionExecutionContext } from "entities/Action";
|
||||
|
||||
export const checkIfMigrationIsNeeded = (
|
||||
fetchPageResponse?: FetchPageResponse,
|
||||
|
|
@ -977,7 +978,11 @@ export function* clonePageSaga(
|
|||
}
|
||||
|
||||
yield put(selectWidgetInitAction(SelectionRequestType.Empty));
|
||||
yield put(fetchAllPageEntityCompletion([executePageLoadActions()]));
|
||||
yield put(
|
||||
fetchAllPageEntityCompletion([
|
||||
executePageLoadActions(ActionExecutionContext.CLONE_PAGE),
|
||||
]),
|
||||
);
|
||||
|
||||
// TODO: Update URL params here.
|
||||
|
||||
|
|
@ -1374,7 +1379,11 @@ export function* generateTemplatePageSaga(
|
|||
if (!afterActionsFetch) {
|
||||
throw new Error("Failed generating template");
|
||||
}
|
||||
yield put(fetchAllPageEntityCompletion([executePageLoadActions()]));
|
||||
yield put(
|
||||
fetchAllPageEntityCompletion([
|
||||
executePageLoadActions(ActionExecutionContext.GENERATE_CRUD_PAGE),
|
||||
]),
|
||||
);
|
||||
|
||||
history.replace(
|
||||
builderURL({
|
||||
|
|
|
|||
|
|
@ -602,6 +602,7 @@ export function* leaveWorkspaceSaga(
|
|||
toast.show(`You have successfully left the workspace`, {
|
||||
kind: "success",
|
||||
});
|
||||
history.push("/applications");
|
||||
}
|
||||
} catch (error) {
|
||||
// do nothing as it's already handled globally
|
||||
|
|
|
|||
7
app/client/src/ce/selectors/modulesSelector.ts
Normal file
7
app/client/src/ce/selectors/modulesSelector.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import type { AppState } from "@appsmith/reducers";
|
||||
import type { Module } from "@appsmith/constants/ModuleConstants";
|
||||
|
||||
export const getAllModules = (
|
||||
state: AppState,
|
||||
): Record<string, Module> | any => {};
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import type { Action } from "entities/Action";
|
||||
import { ActionExecutionContext } from "entities/Action";
|
||||
import type { JSAction, JSCollection } from "entities/JSCollection";
|
||||
import type { ApplicationPayload } from "@appsmith/constants/ReduxActionConstants";
|
||||
import store from "store";
|
||||
|
|
@ -65,6 +66,7 @@ export function getActionExecutionAnalytics(
|
|||
isMock: !!datasource?.isMock,
|
||||
actionId: action?.id,
|
||||
inputParams: Object.keys(params).length,
|
||||
source: ActionExecutionContext.EVALUATION_ACTION_TRIGGER, // Used in analytic events to understand who triggered action execution
|
||||
};
|
||||
|
||||
if (!!currentApp) {
|
||||
|
|
|
|||
|
|
@ -354,7 +354,8 @@ export type EventName =
|
|||
| CUSTOM_WIDGET_EVENTS
|
||||
| "MULTI_FILE_PICKER_EXCEEDS_LIMIT"
|
||||
| "TEMPLATE_ADD_PAGE_FROM_TEMPLATE_FLOW"
|
||||
| HOMEPAGE_CREATE_APP_FROM_TEMPLATE_EVENTS;
|
||||
| HOMEPAGE_CREATE_APP_FROM_TEMPLATE_EVENTS
|
||||
| "EDITOR_MODE_CHANGE";
|
||||
|
||||
type HOMEPAGE_CREATE_APP_FROM_TEMPLATE_EVENTS =
|
||||
| "TEMPLATE_DROPDOWN_CLICK"
|
||||
|
|
@ -384,7 +385,8 @@ export type ONBOARDING_FLOW_EVENTS =
|
|||
| "ONBOARDING_FLOW_CLICK_SKIP_BUTTON_START_FROM_DATA_PAGE"
|
||||
| "ONBOARDING_FLOW_CLICK_SKIP_BUTTON_DATASOURCE_FORM_PAGE"
|
||||
| "ONBOARDING_FLOW_CLICK_SKIP_BUTTON_START_FROM_TEMPLATE_PAGE"
|
||||
| "ONBOARDING_FLOW_CLICK_SKIP_BUTTON_TEMPLATE_DETAILS_PAGE";
|
||||
| "ONBOARDING_FLOW_CLICK_SKIP_BUTTON_TEMPLATE_DETAILS_PAGE"
|
||||
| "CODE_MODE_WIDGET_SELECTION";
|
||||
|
||||
export type DATASOURCE_SCHEMA_EVENTS =
|
||||
| "DATASOURCE_SCHEMA_SEARCH"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import type { ReactNode } from "react";
|
||||
import React from "react";
|
||||
import {
|
||||
getFunctionNameFromJsObjectExpression,
|
||||
|
|
@ -20,7 +19,7 @@ import { PluginType } from "entities/Action";
|
|||
import type { JSAction, Variable } from "entities/JSCollection";
|
||||
import keyBy from "lodash/keyBy";
|
||||
import { getActionConfig } from "pages/Editor/Explorer/Actions/helpers";
|
||||
import { EntityIcon, JsFileIconV2 } from "pages/Editor/Explorer/ExplorerIcons";
|
||||
import { JsFileIconV2 } from "pages/Editor/Explorer/ExplorerIcons";
|
||||
import { useMemo } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import type {
|
||||
|
|
@ -66,11 +65,13 @@ import { selectEvaluationVersion } from "@appsmith/selectors/applicationSelector
|
|||
import { isJSAction } from "@appsmith/workers/Evaluation/evaluationUtils";
|
||||
import type { DataTreeEntity } from "entities/DataTree/dataTreeTypes";
|
||||
import type { ModuleInstanceDataState } from "@appsmith/constants/ModuleInstanceConstants";
|
||||
import { MODULE_TYPE } from "@appsmith/constants/ModuleConstants";
|
||||
import { setShowCreateNewModal } from "actions/propertyPaneActions";
|
||||
import { setIdeEditorViewMode } from "actions/ideActions";
|
||||
import { EditorViewMode } from "@appsmith/entities/IDE/constants";
|
||||
import { getIsSideBySideEnabled } from "selectors/ideSelectors";
|
||||
import { resolveIcon } from "pages/Editor/utils";
|
||||
import { getAllModules } from "@appsmith/selectors/modulesSelector";
|
||||
import type { Module } from "@appsmith/constants/ModuleConstants";
|
||||
|
||||
const actionList: {
|
||||
label: string;
|
||||
|
|
@ -393,16 +394,6 @@ export function useModalDropdownList(handleClose: () => void) {
|
|||
return finalList;
|
||||
}
|
||||
|
||||
export const getModuleInstanceIcon = (type: MODULE_TYPE): ReactNode => {
|
||||
if (type === MODULE_TYPE.QUERY || type === MODULE_TYPE.JS) {
|
||||
return (
|
||||
<EntityIcon>
|
||||
<Icon name="module" />
|
||||
</EntityIcon>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export function getApiQueriesAndJSActionOptionsWithChildren(
|
||||
pageId: string,
|
||||
plugins: any,
|
||||
|
|
@ -412,6 +403,7 @@ export function getApiQueriesAndJSActionOptionsWithChildren(
|
|||
handleClose: () => void,
|
||||
queryModuleInstances: ModuleInstanceDataState,
|
||||
jsModuleInstances: ReturnType<typeof getJSModuleInstancesData>,
|
||||
modules: Record<string, Module>,
|
||||
) {
|
||||
// this function gets a list of all the queries/apis and attaches it to actionList
|
||||
getApiAndQueryOptions(
|
||||
|
|
@ -420,6 +412,7 @@ export function getApiQueriesAndJSActionOptionsWithChildren(
|
|||
dispatch,
|
||||
handleClose,
|
||||
queryModuleInstances,
|
||||
modules,
|
||||
);
|
||||
|
||||
// this function gets a list of all the JS Objects and attaches it to actionList
|
||||
|
|
@ -434,6 +427,7 @@ function getApiAndQueryOptions(
|
|||
dispatch: any,
|
||||
handleClose: () => void,
|
||||
queryModuleInstances: ModuleInstanceDataState,
|
||||
modules: Record<string, Module>,
|
||||
) {
|
||||
const state = store.getState();
|
||||
const isSideBySideEnabled = getIsSideBySideEnabled(state);
|
||||
|
|
@ -499,12 +493,17 @@ function getApiAndQueryOptions(
|
|||
} as TreeDropdownOption);
|
||||
});
|
||||
queryModuleInstances.forEach((instance) => {
|
||||
const module = modules[instance.config.sourceModuleId];
|
||||
(queryOptions.children as TreeDropdownOption[]).push({
|
||||
label: instance.config.name,
|
||||
id: instance.config.id,
|
||||
value: instance.config.name,
|
||||
type: queryOptions.value,
|
||||
icon: getModuleInstanceIcon(instance.config.type),
|
||||
icon: resolveIcon({
|
||||
iconLocation: plugins[module.pluginId]?.iconLocation || "",
|
||||
pluginType: module.pluginType,
|
||||
moduleType: module.type,
|
||||
}),
|
||||
} as TreeDropdownOption);
|
||||
});
|
||||
}
|
||||
|
|
@ -587,7 +586,7 @@ export function getJSOptions(
|
|||
id: jsModuleInstance.config.id,
|
||||
value: jsModuleInstance.name,
|
||||
type: jsOption.value,
|
||||
icon: getModuleInstanceIcon(MODULE_TYPE.JS),
|
||||
icon: JsFileIconV2(),
|
||||
} as unknown as TreeDropdownOption;
|
||||
|
||||
(jsOption.children as unknown as TreeDropdownOption[]).push(jsObject);
|
||||
|
|
@ -637,6 +636,7 @@ export function useApisQueriesAndJsActionOptions(handleClose: () => void) {
|
|||
getQueryModuleInstances,
|
||||
) as unknown as ModuleInstanceDataState;
|
||||
const jsModuleInstancesData = useSelector(getJSModuleInstancesData);
|
||||
const modules = useSelector(getAllModules);
|
||||
|
||||
// this function gets all the Queries/API's/JS Objects and attaches it to actionList
|
||||
return getApiQueriesAndJSActionOptionsWithChildren(
|
||||
|
|
@ -648,5 +648,6 @@ export function useApisQueriesAndJsActionOptions(handleClose: () => void) {
|
|||
handleClose,
|
||||
queryModuleInstances,
|
||||
jsModuleInstancesData,
|
||||
modules,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,17 @@ const SideBar = styled.div`
|
|||
}
|
||||
`;
|
||||
|
||||
const Wrapper = styled.div`
|
||||
border-left: 1px solid var(--ads-v2-color-border);
|
||||
padding: 0 var(--ads-v2-spaces-7) var(--ads-v2-spaces-4);
|
||||
overflow: hidden;
|
||||
border-bottom: 0;
|
||||
display: flex;
|
||||
width: ${(props) => props.theme.actionSidePane.width}px;
|
||||
margin-top: 10px;
|
||||
/* margin-left: var(--ads-v2-spaces-7); */
|
||||
`;
|
||||
|
||||
export function useEntityDependencies(actionName: string) {
|
||||
const deps = useSelector((state: AppState) => state.evaluations.dependencies);
|
||||
const entityDependencies = useMemo(
|
||||
|
|
@ -90,16 +101,18 @@ function ActionSidebar({
|
|||
}
|
||||
|
||||
return (
|
||||
<SideBar>
|
||||
{actionRightPaneBackLink}
|
||||
<CollapsibleGroupContainer>
|
||||
{additionalSections && (
|
||||
<CollapsibleGroup maxHeight={"50%"}>
|
||||
{additionalSections}
|
||||
</CollapsibleGroup>
|
||||
)}
|
||||
</CollapsibleGroupContainer>
|
||||
</SideBar>
|
||||
<Wrapper>
|
||||
<SideBar>
|
||||
{actionRightPaneBackLink}
|
||||
<CollapsibleGroupContainer>
|
||||
{additionalSections && (
|
||||
<CollapsibleGroup maxHeight={"50%"}>
|
||||
{additionalSections}
|
||||
</CollapsibleGroup>
|
||||
)}
|
||||
</CollapsibleGroupContainer>
|
||||
</SideBar>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -269,6 +269,7 @@ export interface ActionOperation {
|
|||
focusEntityType?: FocusEntity;
|
||||
dsName?: string;
|
||||
entityExplorerTitle?: string;
|
||||
isBeta?: boolean;
|
||||
}
|
||||
|
||||
export const actionOperations: ActionOperation[] = [
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@ import type {
|
|||
ActionData,
|
||||
ActionDataState,
|
||||
} from "@appsmith/reducers/entityReducers/actionsReducer";
|
||||
import { EntityIcon } from "pages/Editor/Explorer/ExplorerIcons";
|
||||
import { Icon } from "design-system";
|
||||
import type {
|
||||
ModuleInstanceData,
|
||||
ModuleInstanceDataState,
|
||||
|
|
@ -27,6 +25,11 @@ import type {
|
|||
import { selectFeatureFlagCheck } from "@appsmith/selectors/featureFlagsSelectors";
|
||||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||
import type { AppState } from "@appsmith/reducers";
|
||||
import type { Module } from "@appsmith/constants/ModuleConstants";
|
||||
import { getAllModules } from "@appsmith/selectors/modulesSelector";
|
||||
import { resolveIcon } from "pages/Editor/utils";
|
||||
import { Icon } from "design-system";
|
||||
import { EntityIcon } from "pages/Editor/Explorer/ExplorerIcons";
|
||||
|
||||
enum SortingWeights {
|
||||
alphabetical = 1,
|
||||
|
|
@ -97,8 +100,25 @@ interface ConnectToOptionsProps {
|
|||
export const getQueryIcon = (
|
||||
query: ActionData | ModuleInstanceData,
|
||||
pluginImages: Record<string, string>,
|
||||
modules: Record<string, Module>,
|
||||
) => {
|
||||
if (!query.config.hasOwnProperty("sourceModuleId")) {
|
||||
if (query.config.hasOwnProperty("type")) {
|
||||
const q = query as ModuleInstanceData;
|
||||
const module = modules[q.config.sourceModuleId];
|
||||
const icon = resolveIcon({
|
||||
iconLocation: pluginImages[module.pluginId] || "",
|
||||
pluginType: module.pluginType,
|
||||
moduleType: module.type,
|
||||
});
|
||||
|
||||
return (
|
||||
icon || (
|
||||
<EntityIcon>
|
||||
<Icon name="module" />
|
||||
</EntityIcon>
|
||||
)
|
||||
);
|
||||
} else {
|
||||
const action = query as ActionData;
|
||||
return (
|
||||
<ImageWrapper>
|
||||
|
|
@ -109,12 +129,6 @@ export const getQueryIcon = (
|
|||
/>
|
||||
</ImageWrapper>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<EntityIcon>
|
||||
<Icon name="module" />
|
||||
</EntityIcon>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -172,6 +186,7 @@ function useConnectToOptions(props: ConnectToOptionsProps) {
|
|||
const { pluginImages, widget } = props;
|
||||
|
||||
const queryModuleInstances = useSelector(getQueryModuleInstances);
|
||||
const modules = useSelector(getAllModules);
|
||||
let filteredQueries: ActionData[] | ModuleInstanceData[] = queries;
|
||||
|
||||
/* Exclude Gsheets from query options till this gets resolved https://github.com/appsmithorg/appsmith/issues/27102*/
|
||||
|
|
@ -193,7 +208,7 @@ function useConnectToOptions(props: ConnectToOptionsProps) {
|
|||
id: query.config.id,
|
||||
label: query.config.name,
|
||||
value: getBindingValue(widget, query),
|
||||
icon: getQueryIcon(query, pluginImages),
|
||||
icon: getQueryIcon(query, pluginImages, modules),
|
||||
onSelect: function (value?: string, valueOption?: DropdownOptionType) {
|
||||
addBinding(
|
||||
valueOption?.value,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import type {
|
|||
} from "@appsmith/constants/ModuleInstanceConstants";
|
||||
import { MODULE_TYPE } from "@appsmith/constants/ModuleConstants";
|
||||
import type { JSAction } from "entities/JSCollection";
|
||||
import { getAllModules } from "@appsmith/selectors/modulesSelector";
|
||||
|
||||
class ActionSelectorControl extends BaseControl<ControlProps> {
|
||||
componentRef = React.createRef<HTMLDivElement>();
|
||||
|
|
@ -108,6 +109,7 @@ class ActionSelectorControl extends BaseControl<ControlProps> {
|
|||
const moduleInstances = getModuleInstances(state);
|
||||
const queryModuleInstances = [] as ModuleInstanceDataState;
|
||||
const jsModuleInstances = getJSModuleInstancesData(state);
|
||||
const modules = getAllModules(state);
|
||||
|
||||
if (!!moduleInstances) {
|
||||
for (const moduleInstance of Object.values(moduleInstances)) {
|
||||
|
|
@ -166,6 +168,7 @@ class ActionSelectorControl extends BaseControl<ControlProps> {
|
|||
},
|
||||
queryModuleInstances,
|
||||
jsModuleInstances,
|
||||
modules,
|
||||
);
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export const NameWrapper = styled.div<{ enableFontStyling?: boolean }>`
|
|||
}`
|
||||
: null}
|
||||
|
||||
& .t--action-name-edit-field, & .t--js-action-name-edit-field {
|
||||
& .t--action-name-edit-field, & .t--js-action-name-edit-field, & .t--module-instance-name-edit-field {
|
||||
width: 100%;
|
||||
|
||||
& > span {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ export const DOCS_BRANCH_PROTECTION_URL =
|
|||
"https://docs.appsmith.com/advanced-concepts/version-control-with-git/working-with-branches#branch-protection";
|
||||
export const DOCS_DEFAULT_BRANCH_URL =
|
||||
"https://docs.appsmith.com/advanced-concepts/version-control-with-git/working-with-branches#default-branch";
|
||||
export const PACKAGES_OVERVIEW_DOC =
|
||||
"https://docs.appsmith.com/packages/overview";
|
||||
|
||||
export const PRICING_PAGE_URL = (
|
||||
URL: string,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
export * from "ce/pages/Editor/gitSync/useReconnectModalData";
|
||||
import { default as useCEReconnectModalData } from "ce/pages/Editor/gitSync/useReconnectModalData";
|
||||
export default useCEReconnectModalData;
|
||||
1
app/client/src/ee/selectors/modulesSelector.ts
Normal file
1
app/client/src/ee/selectors/modulesSelector.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from "ce/selectors/modulesSelector";
|
||||
|
|
@ -75,6 +75,18 @@ export enum ActionCreationSourceTypeEnum {
|
|||
COPY_ACTION = "COPY_ACTION",
|
||||
}
|
||||
|
||||
// Used for analytic events
|
||||
export enum ActionExecutionContext {
|
||||
SELF = "SELF",
|
||||
ONE_CLICK_BINDING = "ONE_CLICK_BINDING",
|
||||
GENERATE_CRUD_PAGE = "GENERATE_CRUD_PAGE",
|
||||
CLONE_PAGE = "CLONE_PAGE",
|
||||
FORK_TEMPLATE_PAGE = "FORK_TEMPLATE_PAGE",
|
||||
PAGE_LOAD = "PAGE_LOAD",
|
||||
EVALUATION_ACTION_TRIGGER = "EVALUATION_ACTION_TRIGGER",
|
||||
REFRESH_ACTIONS_ON_ENV_CHANGE = "REFRESH_ACTIONS_ON_ENV_CHANGE",
|
||||
}
|
||||
|
||||
export interface KeyValuePair {
|
||||
key?: string;
|
||||
value?: unknown;
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@ import { getShouldAllowDrag } from "selectors/widgetDragSelectors";
|
|||
import { combinedPreviewModeSelector } from "selectors/editorSelectors";
|
||||
import { getAnvilSpaceDistributionStatus } from "layoutSystems/anvil/integrations/selectors";
|
||||
|
||||
const DraggableWrapper = styled.div`
|
||||
const DraggableWrapper = styled.div<{ draggable: boolean }>`
|
||||
display: block;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
user-select: none;
|
||||
cursor: grab;
|
||||
cursor: ${(props) => (props.draggable ? "grab" : "unset")};
|
||||
`;
|
||||
|
||||
export interface DraggableComponentProps {
|
||||
|
|
@ -37,7 +37,7 @@ export interface DraggableComponentProps {
|
|||
type: string;
|
||||
children: ReactNode;
|
||||
generateDragState: (
|
||||
e: React.DragEvent<Element>,
|
||||
e: React.DragEvent,
|
||||
draggableRef: HTMLElement,
|
||||
) => SetDraggingStateActionPayload;
|
||||
dragDisabled: boolean;
|
||||
|
|
@ -53,7 +53,6 @@ const WidgetBoundaries = styled.div`
|
|||
${(props) => getColorWithOpacity(props.theme.colors.textAnchor, 0.5)};
|
||||
pointer-events: none;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
`;
|
||||
|
||||
|
|
@ -100,14 +99,14 @@ function DraggableComponent(props: DraggableComponentProps) {
|
|||
!props.isFlexChild && (isCurrentWidgetDragging || isDraggingSibling);
|
||||
|
||||
// When mouse is over this draggable
|
||||
const handleMouseOver = (e: any) => {
|
||||
const handleMouseOver = (e: React.MouseEvent) => {
|
||||
focusWidget &&
|
||||
!isResizingOrDragging &&
|
||||
!isFocused &&
|
||||
!isDistributingSpace &&
|
||||
!props.resizeDisabled &&
|
||||
!isPreviewMode &&
|
||||
focusWidget(props.widgetId);
|
||||
focusWidget(props.widgetId, e.metaKey);
|
||||
e.stopPropagation();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import { useCurrentAppState } from "pages/Editor/IDE/hooks";
|
|||
import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
|
||||
import { getLayoutSystemType } from "selectors/layoutSystemSelectors";
|
||||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||
import { getWidgetSelectionBlock } from "selectors/ui";
|
||||
import {
|
||||
isAutoHeightEnabledForWidget,
|
||||
isAutoHeightEnabledForWidgetWithLimits,
|
||||
|
|
@ -259,6 +260,7 @@ export function DropTargetComponent(props: DropTargetComponentProps) {
|
|||
);
|
||||
// Are we changing the auto height limits by dragging the signifiers?
|
||||
const { isAutoHeightWithLimitsChanging } = useAutoHeightUIState();
|
||||
const isWidgetSelectionBlocked = useSelector(getWidgetSelectionBlock);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
|
|
@ -327,7 +329,12 @@ export function DropTargetComponent(props: DropTargetComponentProps) {
|
|||
(e.target as HTMLDivElement).dataset.testid === selectionDiv ||
|
||||
(e.target as HTMLDivElement).dataset.testid === mainCanvasId;
|
||||
|
||||
if (!isResizing && !isDragging && !isAutoHeightWithLimitsChanging) {
|
||||
if (
|
||||
!isResizing &&
|
||||
!isDragging &&
|
||||
!isAutoHeightWithLimitsChanging &&
|
||||
!isWidgetSelectionBlocked
|
||||
) {
|
||||
// Check if Target is the MainCanvas
|
||||
if (isTargetMainCanvas) {
|
||||
goToWidgetAdd();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import {
|
|||
combinedPreviewModeSelector,
|
||||
snipingModeSelector,
|
||||
} from "selectors/editorSelectors";
|
||||
import { getWidgetSelectionBlock } from "../../../selectors/ui";
|
||||
const minSize = 100;
|
||||
|
||||
/**
|
||||
|
|
@ -101,7 +102,9 @@ export const ModalResizableLayer = ({
|
|||
};
|
||||
const isPreviewMode = useSelector(combinedPreviewModeSelector);
|
||||
const isSnipingMode = useSelector(snipingModeSelector);
|
||||
const enableResizing = !isSnipingMode && !isPreviewMode;
|
||||
const isWidgetSelectionBlocked = useSelector(getWidgetSelectionBlock);
|
||||
const enableResizing =
|
||||
!isSnipingMode && !isPreviewMode && !isWidgetSelectionBlocked;
|
||||
return (
|
||||
<ModalResizable
|
||||
allowResize
|
||||
|
|
|
|||
|
|
@ -65,6 +65,10 @@ import {
|
|||
computeFinalRowCols,
|
||||
computeFinalAutoLayoutRowCols,
|
||||
} from "layoutSystems/common/resizer/ResizableUtils";
|
||||
import {
|
||||
getAltBlockWidgetSelection,
|
||||
getWidgetSelectionBlock,
|
||||
} from "selectors/ui";
|
||||
|
||||
export type ResizableComponentProps = WidgetProps & {
|
||||
paddingOffset: number;
|
||||
|
|
@ -80,6 +84,8 @@ export const ResizableComponent = memo(function ResizableComponent(
|
|||
const Resizable = isAutoLayout ? AutoLayoutResizable : FixedLayoutResizable;
|
||||
const isSnipingMode = useSelector(snipingModeSelector);
|
||||
const isPreviewMode = useSelector(combinedPreviewModeSelector);
|
||||
const isWidgetSelectionBlock = useSelector(getWidgetSelectionBlock);
|
||||
const isAltWidgetSelectionBlock = useSelector(getAltBlockWidgetSelection);
|
||||
const isAppSettingsPaneWithNavigationTabOpen = useSelector(
|
||||
getIsAppSettingsPaneWithNavigationTabOpen,
|
||||
);
|
||||
|
|
@ -325,6 +331,7 @@ export const ResizableComponent = memo(function ResizableComponent(
|
|||
!props.resizeDisabled &&
|
||||
!isSnipingMode &&
|
||||
!isPreviewMode &&
|
||||
!isWidgetSelectionBlock &&
|
||||
!isAppSettingsPaneWithNavigationTabOpen;
|
||||
const { updateDropTargetRows } = useContext(DropTargetContext);
|
||||
|
||||
|
|
@ -387,6 +394,7 @@ export const ResizableComponent = memo(function ResizableComponent(
|
|||
!isPreviewMode &&
|
||||
!isAppSettingsPaneWithNavigationTabOpen &&
|
||||
!isDragging &&
|
||||
!isAltWidgetSelectionBlock &&
|
||||
(isHovered || isSelected);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { Classes, Tooltip } from "@blueprintjs/core";
|
||||
import { Colors } from "constants/Colors";
|
||||
import type { CSSProperties } from "react";
|
||||
import React from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { snipingModeSelector } from "selectors/editorSelectors";
|
||||
import styled from "styled-components";
|
||||
import { Icon } from "design-system";
|
||||
import { Icon, Text, Tooltip } from "design-system";
|
||||
|
||||
// I honestly can't think of a better name for this enum
|
||||
export enum Activities {
|
||||
HOVERING,
|
||||
|
|
@ -13,13 +13,7 @@ export enum Activities {
|
|||
ACTIVE,
|
||||
NONE,
|
||||
}
|
||||
const StyledTooltip = styled(Tooltip)<{
|
||||
children?: React.ReactNode;
|
||||
}>`
|
||||
.${Classes.POPOVER_TARGET} {
|
||||
height: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
const WidgetNameBoundary = 1;
|
||||
const BORDER_RADIUS = 4;
|
||||
const SettingsWrapper = styled.div<{ widgetWidth: number; inverted: boolean }>`
|
||||
|
|
@ -60,10 +54,6 @@ const WidgetName = styled.span`
|
|||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
const StyledErrorIcon = styled(Icon)`
|
||||
margin-right: ${(props) => props.theme.spaces[1]}px;
|
||||
`;
|
||||
|
||||
interface SettingsControlProps {
|
||||
toggleSettings: (e: any) => void;
|
||||
activity: Activities;
|
||||
|
|
@ -111,17 +101,17 @@ const getStyles = (
|
|||
|
||||
export function SettingsControl(props: SettingsControlProps) {
|
||||
const isSnipingMode = useSelector(snipingModeSelector);
|
||||
const errorIcon = <StyledErrorIcon name="warning" size="sm" />;
|
||||
const errorIcon = <Icon name="warning" size="sm" />;
|
||||
|
||||
return (
|
||||
<StyledTooltip
|
||||
<Tooltip
|
||||
content={
|
||||
isSnipingMode
|
||||
? `Bind to widget ${props.name}`
|
||||
: "Edit widget properties"
|
||||
<Text color="var(--ads-v2-color-white)">
|
||||
{isSnipingMode ? `Bind to widget ${props.name}` : `Edit widget`}
|
||||
</Text>
|
||||
}
|
||||
hoverOpenDelay={500}
|
||||
position="top-right"
|
||||
mouseEnterDelay={0}
|
||||
placement="topRight"
|
||||
>
|
||||
<SettingsWrapper
|
||||
className="t--widget-propertypane-toggle"
|
||||
|
|
@ -143,7 +133,7 @@ export function SettingsControl(props: SettingsControlProps) {
|
|||
{isSnipingMode ? `Bind to ${props.name}` : props.name}
|
||||
</WidgetName>
|
||||
</SettingsWrapper>
|
||||
</StyledTooltip>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import { getAbsolutePixels } from "utils/helpers";
|
|||
import type { XYCord } from "layoutSystems/common/canvasArenas/ArenaTypes";
|
||||
import { useCanvasDragToScroll } from "layoutSystems/common/canvasArenas/useCanvasDragToScroll";
|
||||
import { StickyCanvasArena } from "layoutSystems/common/canvasArenas/StickyCanvasArena";
|
||||
import { getWidgetSelectionBlock } from "../../../../selectors/ui";
|
||||
|
||||
export interface SelectedArenaDimensions {
|
||||
top: number;
|
||||
|
|
@ -71,6 +72,7 @@ export function CanvasSelectionArena({
|
|||
);
|
||||
const appMode = useSelector(getAppMode);
|
||||
const isPreviewMode = useSelector(combinedPreviewModeSelector);
|
||||
const isWidgetSelectionBlocked = useSelector(getWidgetSelectionBlock);
|
||||
const isAppSettingsPaneWithNavigationTabOpen = useSelector(
|
||||
getIsAppSettingsPaneWithNavigationTabOpen,
|
||||
);
|
||||
|
|
@ -501,6 +503,7 @@ export function CanvasSelectionArena({
|
|||
!(
|
||||
isDragging ||
|
||||
isPreviewMode ||
|
||||
isWidgetSelectionBlocked ||
|
||||
isAppSettingsPaneWithNavigationTabOpen ||
|
||||
dropDisabled
|
||||
);
|
||||
|
|
|
|||
|
|
@ -644,102 +644,107 @@ function CommonEditorForm(props: CommonFormPropsWithExtraParams) {
|
|||
</HelpSection>
|
||||
)}
|
||||
<Wrapper>
|
||||
<SecondaryWrapper>
|
||||
<TabbedViewContainer>
|
||||
<Tabs
|
||||
className="h-full"
|
||||
defaultValue={
|
||||
isGraphql ? API_EDITOR_TABS.BODY : API_EDITOR_TABS.HEADERS
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
//@ts-ignore
|
||||
onValueChange={setSelectedIndex}
|
||||
value={selectedValue}
|
||||
>
|
||||
<TabsListWrapper>
|
||||
<TabsList>
|
||||
{Object.values(API_EDITOR_TABS).map((tab) => (
|
||||
<Tab
|
||||
data-testid={`t--api-editor-${tab}`}
|
||||
key={tab}
|
||||
notificationCount={
|
||||
tab == "HEADERS"
|
||||
? headersCount
|
||||
: tab == "PARAMS"
|
||||
? paramsCount
|
||||
: undefined
|
||||
}
|
||||
value={tab}
|
||||
>
|
||||
{createMessage(API_EDITOR_TAB_TITLES[tab])}
|
||||
</Tab>
|
||||
))}
|
||||
</TabsList>
|
||||
</TabsListWrapper>
|
||||
<StyledTabPanel value={API_EDITOR_TABS.HEADERS}>
|
||||
<ImportedDatas
|
||||
attributeName="header"
|
||||
autogeneratedHeaders={autoGeneratedActionConfigHeaders}
|
||||
data={props.datasourceHeaders}
|
||||
/>
|
||||
<KeyValueFieldArray
|
||||
actionConfig={actionConfigurationHeaders}
|
||||
dataTreePath={`${actionName}.config.headers`}
|
||||
hideHeader
|
||||
label="Headers"
|
||||
name="actionConfiguration.headers"
|
||||
placeholder="Value"
|
||||
pushFields={isChangePermitted}
|
||||
theme={theme}
|
||||
/>
|
||||
</StyledTabPanel>
|
||||
<StyledTabPanel value={API_EDITOR_TABS.PARAMS}>
|
||||
<ImportedDatas
|
||||
attributeName={"param"}
|
||||
data={props.datasourceParams}
|
||||
/>
|
||||
<KeyValueFieldArray
|
||||
actionConfig={actionConfigurationParams}
|
||||
dataTreePath={`${actionName}.config.queryParameters`}
|
||||
hideHeader
|
||||
label="Params"
|
||||
name="actionConfiguration.queryParameters"
|
||||
pushFields={isChangePermitted}
|
||||
theme={theme}
|
||||
/>
|
||||
</StyledTabPanel>
|
||||
<StyledTabPanel className="h-full" value={API_EDITOR_TABS.BODY}>
|
||||
{props.bodyUIComponent}
|
||||
</StyledTabPanel>
|
||||
<StyledTabPanel value={API_EDITOR_TABS.PAGINATION}>
|
||||
{props.paginationUIComponent}
|
||||
</StyledTabPanel>
|
||||
<StyledTabPanel value={API_EDITOR_TABS.AUTHENTICATION}>
|
||||
<ApiAuthentication formName={formName} />
|
||||
</StyledTabPanel>
|
||||
<StyledTabPanel value={API_EDITOR_TABS.SETTINGS}>
|
||||
<SettingsWrapper>
|
||||
<ActionSettings
|
||||
actionSettingsConfig={settingsConfig}
|
||||
formName={formName}
|
||||
<div className="flex flex-1">
|
||||
<SecondaryWrapper>
|
||||
<TabbedViewContainer>
|
||||
<Tabs
|
||||
className="h-full"
|
||||
defaultValue={
|
||||
isGraphql ? API_EDITOR_TABS.BODY : API_EDITOR_TABS.HEADERS
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
//@ts-ignore
|
||||
onValueChange={setSelectedIndex}
|
||||
value={selectedValue}
|
||||
>
|
||||
<TabsListWrapper>
|
||||
<TabsList>
|
||||
{Object.values(API_EDITOR_TABS).map((tab) => (
|
||||
<Tab
|
||||
data-testid={`t--api-editor-${tab}`}
|
||||
key={tab}
|
||||
notificationCount={
|
||||
tab == "HEADERS"
|
||||
? headersCount
|
||||
: tab == "PARAMS"
|
||||
? paramsCount
|
||||
: undefined
|
||||
}
|
||||
value={tab}
|
||||
>
|
||||
{createMessage(API_EDITOR_TAB_TITLES[tab])}
|
||||
</Tab>
|
||||
))}
|
||||
</TabsList>
|
||||
</TabsListWrapper>
|
||||
<StyledTabPanel value={API_EDITOR_TABS.HEADERS}>
|
||||
<ImportedDatas
|
||||
attributeName="header"
|
||||
autogeneratedHeaders={autoGeneratedActionConfigHeaders}
|
||||
data={props.datasourceHeaders}
|
||||
/>
|
||||
<KeyValueFieldArray
|
||||
actionConfig={actionConfigurationHeaders}
|
||||
dataTreePath={`${actionName}.config.headers`}
|
||||
hideHeader
|
||||
label="Headers"
|
||||
name="actionConfiguration.headers"
|
||||
placeholder="Value"
|
||||
pushFields={isChangePermitted}
|
||||
theme={theme}
|
||||
/>
|
||||
</SettingsWrapper>
|
||||
</StyledTabPanel>
|
||||
</Tabs>
|
||||
</TabbedViewContainer>
|
||||
<ApiResponseView
|
||||
actionResponse={actionResponse}
|
||||
apiName={actionName}
|
||||
currentActionConfig={currentActionConfig}
|
||||
disabled={!isExecutePermitted}
|
||||
isRunning={isRunning}
|
||||
onRunClick={onRunClick}
|
||||
responseDataTypes={responseDataTypes}
|
||||
responseDisplayFormat={responseDisplayFormat}
|
||||
theme={theme}
|
||||
/>
|
||||
</SecondaryWrapper>
|
||||
</StyledTabPanel>
|
||||
<StyledTabPanel value={API_EDITOR_TABS.PARAMS}>
|
||||
<ImportedDatas
|
||||
attributeName={"param"}
|
||||
data={props.datasourceParams}
|
||||
/>
|
||||
<KeyValueFieldArray
|
||||
actionConfig={actionConfigurationParams}
|
||||
dataTreePath={`${actionName}.config.queryParameters`}
|
||||
hideHeader
|
||||
label="Params"
|
||||
name="actionConfiguration.queryParameters"
|
||||
pushFields={isChangePermitted}
|
||||
theme={theme}
|
||||
/>
|
||||
</StyledTabPanel>
|
||||
<StyledTabPanel
|
||||
className="h-full"
|
||||
value={API_EDITOR_TABS.BODY}
|
||||
>
|
||||
{props.bodyUIComponent}
|
||||
</StyledTabPanel>
|
||||
<StyledTabPanel value={API_EDITOR_TABS.PAGINATION}>
|
||||
{props.paginationUIComponent}
|
||||
</StyledTabPanel>
|
||||
<StyledTabPanel value={API_EDITOR_TABS.AUTHENTICATION}>
|
||||
<ApiAuthentication formName={formName} />
|
||||
</StyledTabPanel>
|
||||
<StyledTabPanel value={API_EDITOR_TABS.SETTINGS}>
|
||||
<SettingsWrapper>
|
||||
<ActionSettings
|
||||
actionSettingsConfig={settingsConfig}
|
||||
formName={formName}
|
||||
theme={theme}
|
||||
/>
|
||||
</SettingsWrapper>
|
||||
</StyledTabPanel>
|
||||
</Tabs>
|
||||
</TabbedViewContainer>
|
||||
<ApiResponseView
|
||||
actionResponse={actionResponse}
|
||||
apiName={actionName}
|
||||
currentActionConfig={currentActionConfig}
|
||||
disabled={!isExecutePermitted}
|
||||
isRunning={isRunning}
|
||||
onRunClick={onRunClick}
|
||||
responseDataTypes={responseDataTypes}
|
||||
responseDisplayFormat={responseDisplayFormat}
|
||||
theme={theme}
|
||||
/>
|
||||
</SecondaryWrapper>
|
||||
</div>
|
||||
<ActionRightPane
|
||||
actionRightPaneBackLink={actionRightPaneBackLink}
|
||||
additionalSections={actionRightPaneAdditionSections}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
|||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||
import { ApiEditorContextProvider } from "./ApiEditorContext";
|
||||
import type { PaginationField } from "api/ActionAPI";
|
||||
import { get } from "lodash";
|
||||
import { get, keyBy } from "lodash";
|
||||
import PerformanceTracker, {
|
||||
PerformanceTransactionName,
|
||||
} from "utils/PerformanceTracker";
|
||||
|
|
@ -38,6 +38,8 @@ import { MODULE_TYPE } from "@appsmith/constants/ModuleConstants";
|
|||
import Disabler from "pages/common/Disabler";
|
||||
import ConvertEntityNotification from "@appsmith/pages/common/ConvertEntityNotification";
|
||||
import { useIsEditorPaneSegmentsEnabled } from "../IDE/hooks";
|
||||
import { Icon } from "design-system";
|
||||
import { resolveIcon } from "../utils";
|
||||
|
||||
type ApiEditorWrapperProps = RouteComponentProps<APIEditorRouteParams>;
|
||||
|
||||
|
|
@ -65,6 +67,12 @@ function ApiEditorWrapper(props: ApiEditorWrapperProps) {
|
|||
const isConverting = useSelector((state) =>
|
||||
getIsActionConverting(state, action?.id || ""),
|
||||
);
|
||||
const pluginGroups = useMemo(() => keyBy(plugins, "id"), [plugins]);
|
||||
const icon = resolveIcon({
|
||||
iconLocation: pluginGroups[pluginId]?.iconLocation || "",
|
||||
pluginType: action?.pluginType || "",
|
||||
moduleType: action?.actionConfiguration?.body?.moduleType,
|
||||
}) || <Icon name="module" />;
|
||||
|
||||
const isChangePermitted = getHasManageActionPermission(
|
||||
isFeatureEnabled,
|
||||
|
|
@ -150,7 +158,7 @@ function ApiEditorWrapper(props: ApiEditorWrapperProps) {
|
|||
const notification = useMemo(() => {
|
||||
if (!isConverting) return null;
|
||||
|
||||
return <ConvertEntityNotification name={action?.name || ""} />;
|
||||
return <ConvertEntityNotification icon={icon} name={action?.name || ""} />;
|
||||
}, [action?.name, isConverting]);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import { CANVAS_ART_BOARD } from "constants/componentClassNameConstants";
|
|||
import { renderAppsmithCanvas } from "layoutSystems/CanvasFactory";
|
||||
import type { WidgetProps } from "widgets/BaseWidget";
|
||||
import { getAppThemeSettings } from "@appsmith/selectors/applicationSelectors";
|
||||
import CodeModeTooltip from "pages/Editor/WidgetsEditor/CodeModeTooltip";
|
||||
|
||||
interface CanvasProps {
|
||||
widgetsStructure: CanvasWidgetStructure;
|
||||
|
|
@ -83,20 +84,22 @@ const Canvas = (props: CanvasProps) => {
|
|||
|
||||
const renderChildren = () => {
|
||||
return (
|
||||
<Wrapper
|
||||
$enableMainCanvasResizer={!!props.enableMainCanvasResizer}
|
||||
background={isWDSEnabled ? "" : backgroundForCanvas}
|
||||
className={`relative t--canvas-artboard ${paddingBottomClass} transition-all duration-400 ${marginHorizontalClass} ${getViewportClassName(
|
||||
canvasWidth,
|
||||
)}`}
|
||||
data-testid={"t--canvas-artboard"}
|
||||
id={CANVAS_ART_BOARD}
|
||||
ref={isWDSEnabled ? undefined : focusRef}
|
||||
width={canvasWidth}
|
||||
>
|
||||
{props.widgetsStructure.widgetId &&
|
||||
renderAppsmithCanvas(props.widgetsStructure as WidgetProps)}
|
||||
</Wrapper>
|
||||
<CodeModeTooltip>
|
||||
<Wrapper
|
||||
$enableMainCanvasResizer={!!props.enableMainCanvasResizer}
|
||||
background={isWDSEnabled ? "" : backgroundForCanvas}
|
||||
className={`relative t--canvas-artboard ${paddingBottomClass} transition-all duration-400 ${marginHorizontalClass} ${getViewportClassName(
|
||||
canvasWidth,
|
||||
)}`}
|
||||
data-testid={"t--canvas-artboard"}
|
||||
id={CANVAS_ART_BOARD}
|
||||
ref={isWDSEnabled ? undefined : focusRef}
|
||||
width={canvasWidth}
|
||||
>
|
||||
{props.widgetsStructure.widgetId &&
|
||||
renderAppsmithCanvas(props.widgetsStructure as WidgetProps)}
|
||||
</Wrapper>
|
||||
</CodeModeTooltip>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -337,21 +337,3 @@ export function AppsmithAIIcon() {
|
|||
export function ActionUrlIcon(url: string) {
|
||||
return <img src={url} />;
|
||||
}
|
||||
|
||||
export function ModuleIcon(
|
||||
height = 18,
|
||||
width = 18,
|
||||
noBackground = false,
|
||||
noBorder = false,
|
||||
) {
|
||||
return (
|
||||
<EntityIcon
|
||||
height={height + "px"}
|
||||
noBackground={noBackground}
|
||||
noBorder={noBorder}
|
||||
width={width + "px"}
|
||||
>
|
||||
<Icon name="module" size="md" />
|
||||
</EntityIcon>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ const PagesSection = () => {
|
|||
style={springs}
|
||||
>
|
||||
<PaneHeader
|
||||
className="pages"
|
||||
rightIcon={
|
||||
canCreatePages ? (
|
||||
<AddPageContextMenu
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
import React, { useState } from "react";
|
||||
import { AnnouncementModal, Button } from "design-system";
|
||||
import localStorage, { LOCAL_STORAGE_KEYS } from "utils/localStorage";
|
||||
import {
|
||||
SPLITPANE_ANNOUNCEMENT,
|
||||
createMessage,
|
||||
} from "@appsmith/constants/messages";
|
||||
import { getAssetUrl } from "@appsmith/utils/airgapHelpers";
|
||||
import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants";
|
||||
|
||||
const Announcement = () => {
|
||||
const localStorageFlag =
|
||||
localStorage.getItem(LOCAL_STORAGE_KEYS.SPLITPANE_ANNOUNCEMENT) || "true";
|
||||
const [show, setShow] = useState(JSON.parse(localStorageFlag));
|
||||
|
||||
const tryClickHandler = () => {
|
||||
setShow(false);
|
||||
localStorage.setItem(LOCAL_STORAGE_KEYS.SPLITPANE_ANNOUNCEMENT, "false");
|
||||
};
|
||||
|
||||
const learnClickHandler = () => {
|
||||
window.open(
|
||||
"https://community.appsmith.com/content/blog/discover-ide-20-building-more-efficient-ide",
|
||||
"_blank",
|
||||
);
|
||||
};
|
||||
|
||||
const modalFooter = () => (
|
||||
<>
|
||||
<Button kind="primary" onClick={tryClickHandler} size="md">
|
||||
Try it out
|
||||
</Button>
|
||||
<Button kind="tertiary" onClick={learnClickHandler} size="md">
|
||||
Learn more
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<AnnouncementModal
|
||||
banner={getAssetUrl(`${ASSETS_CDN_URL}/splitpane-banner.svg`)}
|
||||
description={createMessage(SPLITPANE_ANNOUNCEMENT.DESCRIPTION)}
|
||||
footer={modalFooter()}
|
||||
isBeta
|
||||
isOpen={show}
|
||||
title={createMessage(SPLITPANE_ANNOUNCEMENT.TITLE)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export { Announcement };
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
import React from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { default as OldPages } from "pages/Editor/Explorer/Pages";
|
||||
import { PagesSection } from "../PagesSection";
|
||||
import { getIsSideBySideEnabled } from "selectors/ideSelectors";
|
||||
|
||||
const Pages = () => {
|
||||
const isSideBySideEnabled = useSelector(getIsSideBySideEnabled);
|
||||
|
||||
if (!isSideBySideEnabled) {
|
||||
return <OldPages />;
|
||||
} else {
|
||||
return <PagesSection />;
|
||||
}
|
||||
};
|
||||
|
||||
export { Pages };
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import React from "react";
|
||||
import React, { useCallback } from "react";
|
||||
import { Button, Flex, SegmentedControl, Tooltip } from "design-system";
|
||||
import {
|
||||
createMessage,
|
||||
|
|
@ -19,6 +19,7 @@ import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
|||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||
import { getIDEViewMode, getIsSideBySideEnabled } from "selectors/ideSelectors";
|
||||
import { setIdeEditorViewMode } from "actions/ideActions";
|
||||
import AnalyticsUtil from "../../../../../utils/AnalyticsUtil";
|
||||
|
||||
const Container = styled(Flex)`
|
||||
#editor-pane-segment-control {
|
||||
|
|
@ -44,6 +45,12 @@ const SegmentedHeader = () => {
|
|||
};
|
||||
const { segment } = useCurrentEditorState();
|
||||
const { onSegmentChange } = useSegmentNavigation();
|
||||
const handleMaximizeButtonClick = useCallback(() => {
|
||||
AnalyticsUtil.logEvent("EDITOR_MODE_CHANGE", {
|
||||
to: EditorViewMode.FullScreen,
|
||||
});
|
||||
dispatch(setIdeEditorViewMode(EditorViewMode.FullScreen));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Container
|
||||
|
|
@ -91,9 +98,7 @@ const SegmentedHeader = () => {
|
|||
id="editor-mode-maximize"
|
||||
isIconButton
|
||||
kind="tertiary"
|
||||
onClick={() =>
|
||||
dispatch(setIdeEditorViewMode(EditorViewMode.FullScreen))
|
||||
}
|
||||
onClick={handleMaximizeButtonClick}
|
||||
startIcon="maximize-v3"
|
||||
/>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import EditorPaneSegments from "./EditorPaneSegments";
|
|||
import GlobalAdd from "./GlobalAdd";
|
||||
import { useEditorPaneWidth } from "../hooks";
|
||||
import EntityProperties from "pages/Editor/Explorer/Entity/EntityProperties";
|
||||
import { Pages } from "./components/Pages";
|
||||
import { PagesSection } from "./PagesSection";
|
||||
|
||||
const EditorPane = ({ match: { path } }: RouteComponentProps) => {
|
||||
const width = useEditorPaneWidth();
|
||||
|
|
@ -26,7 +26,7 @@ const EditorPane = ({ match: { path } }: RouteComponentProps) => {
|
|||
{/** Entity Properties component is needed to render
|
||||
the Bindings popover in the context menu. Will be removed eventually **/}
|
||||
<EntityProperties />
|
||||
<Pages />
|
||||
<PagesSection />
|
||||
|
||||
<Switch>
|
||||
<SentryRoute component={GlobalAdd} exact path={`${path}${ADD_PATH}`} />
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import {
|
|||
MINIMIZE_BUTTON_TOOLTIP,
|
||||
createMessage,
|
||||
} from "@appsmith/constants/messages";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
|
||||
const FullScreenTabs = () => {
|
||||
const dispatch = useDispatch();
|
||||
|
|
@ -26,6 +27,9 @@ const FullScreenTabs = () => {
|
|||
const { segment } = useCurrentEditorState();
|
||||
const setSplitScreenMode = useCallback(() => {
|
||||
dispatch(setIdeEditorViewMode(EditorViewMode.SplitScreen));
|
||||
AnalyticsUtil.logEvent("EDITOR_MODE_CHANGE", {
|
||||
to: EditorViewMode.SplitScreen,
|
||||
});
|
||||
}, []);
|
||||
const tabsConfig = TabSelectors[segment];
|
||||
const pageId = useSelector(getCurrentPageId);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import { getCurrentPageId } from "@appsmith/selectors/entitiesSelector";
|
|||
import history, { NavigationMethod } from "utils/history";
|
||||
import { includes } from "lodash";
|
||||
import ListButton from "./ListButton";
|
||||
import { Announcement } from "../EditorPane/components/Announcement";
|
||||
|
||||
const SplitScreenTabs = () => {
|
||||
const isSideBySideEnabled = useSelector(getIsSideBySideEnabled);
|
||||
|
|
@ -53,18 +54,23 @@ const SplitScreenTabs = () => {
|
|||
if (!isSideBySideEnabled) return null;
|
||||
if (ideViewMode === EditorViewMode.FullScreen) return null;
|
||||
if (segment === EditorEntityTab.UI) return null;
|
||||
return files.length > 0 ? (
|
||||
<Container>
|
||||
<ToggleButton
|
||||
icon="add-line"
|
||||
isSelected={segmentMode === EditorEntityTabState.Add}
|
||||
onClick={onAddClick}
|
||||
size="md"
|
||||
/>
|
||||
<FileTabs navigateToTab={onClick} tabs={files} />
|
||||
<ListButton items={overflowList} navigateToTab={onClick} />
|
||||
</Container>
|
||||
) : null;
|
||||
return (
|
||||
<>
|
||||
{files.length > 0 ? (
|
||||
<Container>
|
||||
<ToggleButton
|
||||
icon="add-line"
|
||||
isSelected={segmentMode === EditorEntityTabState.Add}
|
||||
onClick={onAddClick}
|
||||
size="md"
|
||||
/>
|
||||
<FileTabs navigateToTab={onClick} tabs={files} />
|
||||
<ListButton items={overflowList} navigateToTab={onClick} />
|
||||
</Container>
|
||||
) : null}
|
||||
<Announcement />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SplitScreenTabs;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ const EditorTitle = ({ title }: { title: string }) => {
|
|||
<Flex
|
||||
alignItems={"center"}
|
||||
className={"t--pages-switcher"}
|
||||
data-active={active}
|
||||
gap={"spaces-1"}
|
||||
height={"100%"}
|
||||
justifyContent={"center"}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ import {
|
|||
DEPLOY_MENU_OPTION,
|
||||
IN_APP_EMBED_SETTING,
|
||||
INVITE_TAB,
|
||||
RENAME_APPLICATION_TOOLTIP,
|
||||
HEADER_TITLES,
|
||||
} from "@appsmith/constants/messages";
|
||||
import EditorName from "pages/Editor/EditorName";
|
||||
|
|
@ -35,8 +34,10 @@ import { GetNavigationMenuData } from "pages/Editor/EditorName/NavigationMenuDat
|
|||
import {
|
||||
getCurrentApplicationId,
|
||||
getCurrentPageId,
|
||||
getIsPageSaving,
|
||||
getIsPublishingApplication,
|
||||
getPageById,
|
||||
getPageSavingError,
|
||||
} from "selectors/editorSelectors";
|
||||
import {
|
||||
getApplicationList,
|
||||
|
|
@ -74,6 +75,7 @@ import { EditorTitle } from "./EditorTitle";
|
|||
import { useCurrentAppState } from "pages/Editor/IDE/hooks";
|
||||
import { DefaultTitle } from "./DeaultTitle";
|
||||
import { EditorState } from "@appsmith/entities/IDE/constants";
|
||||
import { EditorSaveIndicator } from "../../EditorSaveIndicator";
|
||||
|
||||
const StyledDivider = styled(Divider)`
|
||||
height: 50%;
|
||||
|
|
@ -99,6 +101,8 @@ const Header = () => {
|
|||
const pageId = useSelector(getCurrentPageId) as string;
|
||||
const currentPage = useSelector(getPageById(pageId));
|
||||
const appState = useCurrentAppState();
|
||||
const isSaving = useSelector(getIsPageSaving);
|
||||
const pageSaveError = useSelector(getPageSavingError);
|
||||
|
||||
// states
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false);
|
||||
|
|
@ -202,7 +206,6 @@ const Header = () => {
|
|||
className={"t--editor-header"}
|
||||
height={"40px"}
|
||||
overflow={"hidden"}
|
||||
px={"spaces-4"}
|
||||
width={"100%"}
|
||||
>
|
||||
<Flex
|
||||
|
|
@ -212,10 +215,12 @@ const Header = () => {
|
|||
gap={"spaces-4"}
|
||||
height={"100%"}
|
||||
justifyContent={"left"}
|
||||
pl={"spaces-4"}
|
||||
>
|
||||
<AppsmithLink />
|
||||
<Divider orientation="vertical" />
|
||||
<TitleComponent />
|
||||
<EditorSaveIndicator isSaving={isSaving} saveError={pageSaveError} />
|
||||
</Flex>
|
||||
<Flex
|
||||
alignItems={"center"}
|
||||
|
|
@ -224,49 +229,43 @@ const Header = () => {
|
|||
height={"100%"}
|
||||
justifyContent={"center"}
|
||||
>
|
||||
<Tooltip
|
||||
content={createMessage(RENAME_APPLICATION_TOOLTIP)}
|
||||
isDisabled={isPopoverOpen}
|
||||
placement="bottom"
|
||||
>
|
||||
<Flex alignItems={"center"}>
|
||||
{currentWorkspace.name && (
|
||||
<>
|
||||
<Text
|
||||
color={"var(--ads-v2-colors-content-label-inactive-fg)"}
|
||||
kind="body-m"
|
||||
>
|
||||
{currentWorkspace.name + " / "}
|
||||
</Text>
|
||||
<EditorName
|
||||
applicationId={applicationId}
|
||||
className="t--application-name editable-application-name max-w-48"
|
||||
defaultSavingState={
|
||||
isSavingName ? SavingState.STARTED : SavingState.NOT_STARTED
|
||||
}
|
||||
defaultValue={currentApplication?.name || ""}
|
||||
editInteractionKind={EditInteractionKind.SINGLE}
|
||||
editorName="Application"
|
||||
fill
|
||||
getNavigationMenu={GetNavigationMenuData}
|
||||
isError={isErroredSavingName}
|
||||
isNewEditor={
|
||||
applicationList.filter((el) => el.id === applicationId)
|
||||
.length > 0
|
||||
}
|
||||
isPopoverOpen={isPopoverOpen}
|
||||
onBlur={(value: string) =>
|
||||
updateApplicationDispatch(applicationId || "", {
|
||||
name: value,
|
||||
currentApp: true,
|
||||
})
|
||||
}
|
||||
setIsPopoverOpen={setIsPopoverOpen}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
</Tooltip>
|
||||
<Flex alignItems={"center"}>
|
||||
{currentWorkspace.name && (
|
||||
<>
|
||||
<Text
|
||||
color={"var(--ads-v2-colors-content-label-inactive-fg)"}
|
||||
kind="body-m"
|
||||
>
|
||||
{currentWorkspace.name + " / "}
|
||||
</Text>
|
||||
<EditorName
|
||||
applicationId={applicationId}
|
||||
className="t--application-name editable-application-name max-w-48"
|
||||
defaultSavingState={
|
||||
isSavingName ? SavingState.STARTED : SavingState.NOT_STARTED
|
||||
}
|
||||
defaultValue={currentApplication?.name || ""}
|
||||
editInteractionKind={EditInteractionKind.SINGLE}
|
||||
editorName="Application"
|
||||
fill
|
||||
getNavigationMenu={GetNavigationMenuData}
|
||||
isError={isErroredSavingName}
|
||||
isNewEditor={
|
||||
applicationList.filter((el) => el.id === applicationId)
|
||||
.length > 0
|
||||
}
|
||||
isPopoverOpen={isPopoverOpen}
|
||||
onBlur={(value: string) =>
|
||||
updateApplicationDispatch(applicationId || "", {
|
||||
name: value,
|
||||
currentApp: true,
|
||||
})
|
||||
}
|
||||
setIsPopoverOpen={setIsPopoverOpen}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex
|
||||
alignItems={"center"}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { Text } from "design-system";
|
|||
interface Props {
|
||||
title: string;
|
||||
rightIcon?: React.ReactNode;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
|
|
@ -22,7 +23,7 @@ const Container = styled.div`
|
|||
|
||||
function PaneHeader(props: Props) {
|
||||
return (
|
||||
<Container>
|
||||
<Container className={props.className}>
|
||||
<Text kind="heading-xs">{props.title}</Text>
|
||||
{props.rightIcon ? props.rightIcon : null}
|
||||
</Container>
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@ import { Route, Switch, useRouteMatch } from "react-router";
|
|||
import * as Sentry from "@sentry/react";
|
||||
import useRoutes from "@appsmith/pages/Editor/IDE/MainPane/useRoutes";
|
||||
import EditorTabs from "pages/Editor/IDE/EditorTabs/FullScreenTabs";
|
||||
import { useWidgetSelectionBlockListener } from "pages/Editor/IDE/hooks";
|
||||
|
||||
const SentryRoute = Sentry.withSentryRouting(Route);
|
||||
export const MainPane = (props: { id: string }) => {
|
||||
const { path } = useRouteMatch();
|
||||
const routes = useRoutes(path);
|
||||
useWidgetSelectionBlockListener();
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
} from "@appsmith/entities/IDE/constants";
|
||||
import { useLocation } from "react-router";
|
||||
import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { getIDEViewMode, getIsSideBySideEnabled } from "selectors/ideSelectors";
|
||||
import { getPropertyPaneWidth } from "selectors/propertyPaneSelectors";
|
||||
import { getCurrentPageId } from "@appsmith/selectors/entitiesSelector";
|
||||
|
|
@ -28,6 +28,8 @@ import {
|
|||
} from "constants/AppConstants";
|
||||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||
import { getIsAltFocusWidget, getWidgetSelectionBlock } from "selectors/ui";
|
||||
import { altFocusWidget, setWidgetSelectionBlock } from "actions/widgetActions";
|
||||
|
||||
export const useCurrentAppState = () => {
|
||||
const [appState, setAppState] = useState(EditorState.EDITOR);
|
||||
|
|
@ -215,3 +217,41 @@ export const useIsEditorPaneSegmentsEnabled = () => {
|
|||
|
||||
return isEditorSegmentsReleaseEnabled || isEditorSegmentsRolloutEnabled;
|
||||
};
|
||||
|
||||
export function useWidgetSelectionBlockListener() {
|
||||
const { pathname } = useLocation();
|
||||
const dispatch = useDispatch();
|
||||
const currentFocus = identifyEntityFromPath(pathname);
|
||||
const isAltFocused = useSelector(getIsAltFocusWidget);
|
||||
const widgetSelectionIsBlocked = useSelector(getWidgetSelectionBlock);
|
||||
|
||||
useEffect(() => {
|
||||
const inUIMode = [
|
||||
FocusEntity.CANVAS,
|
||||
FocusEntity.PROPERTY_PANE,
|
||||
FocusEntity.WIDGET_LIST,
|
||||
].includes(currentFocus.entity);
|
||||
dispatch(setWidgetSelectionBlock(!inUIMode));
|
||||
}, [currentFocus]);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("keydown", handleKeyDown);
|
||||
window.addEventListener("keyup", handleKeyUp);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleKeyDown);
|
||||
window.removeEventListener("keyup", handleKeyUp);
|
||||
};
|
||||
}, [isAltFocused, widgetSelectionIsBlocked]);
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (!isAltFocused && widgetSelectionIsBlocked && e.metaKey) {
|
||||
dispatch(altFocusWidget(e.metaKey));
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyUp = (e: KeyboardEvent) => {
|
||||
if (!e.metaKey && widgetSelectionIsBlocked) {
|
||||
dispatch(altFocusWidget(e.metaKey));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,7 @@ import React, { useCallback } from "react";
|
|||
import type { InjectedFormProps } from "redux-form";
|
||||
import { noop } from "lodash";
|
||||
import type { Datasource } from "entities/Datasource";
|
||||
import { getPluginNameFromId } from "@appsmith/selectors/entitiesSelector";
|
||||
import {
|
||||
PluginName,
|
||||
type Action,
|
||||
type QueryAction,
|
||||
type SaaSAction,
|
||||
} from "entities/Action";
|
||||
import type { Action, QueryAction, SaaSAction } from "entities/Action";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import ActionSettings from "pages/Editor/ActionSettings";
|
||||
import { Button, Tab, TabPanel, Tabs, TabsList, Tooltip } from "design-system";
|
||||
|
|
@ -23,9 +17,7 @@ import {
|
|||
import { useParams } from "react-router";
|
||||
import type { AppState } from "@appsmith/reducers";
|
||||
import { thinScrollbar } from "constants/DefaultTheme";
|
||||
import ActionRightPane, {
|
||||
useEntityDependencies,
|
||||
} from "components/editorComponents/ActionRightPane";
|
||||
import ActionRightPane from "components/editorComponents/ActionRightPane";
|
||||
import type { ActionResponse } from "api/ActionAPI";
|
||||
import type { Plugin } from "api/PluginApi";
|
||||
import type { UIComponentTypes } from "api/PluginApi";
|
||||
|
|
@ -134,17 +126,6 @@ const DocumentationButton = styled(Button)`
|
|||
z-index: 6;
|
||||
`;
|
||||
|
||||
const SidebarWrapper = styled.div<{ show: boolean }>`
|
||||
border-left: 1px solid var(--ads-v2-color-border);
|
||||
padding: 0 var(--ads-v2-spaces-7) var(--ads-v2-spaces-4);
|
||||
overflow: hidden;
|
||||
border-bottom: 0;
|
||||
display: ${(props) => (props.show ? "flex" : "none")};
|
||||
width: ${(props) => props.theme.actionSidePane.width}px;
|
||||
margin-top: 10px;
|
||||
/* margin-left: var(--ads-v2-spaces-7); */
|
||||
`;
|
||||
|
||||
export const SegmentedControlContainer = styled.div`
|
||||
padding: 0 var(--ads-v2-spaces-7);
|
||||
padding-top: var(--ads-v2-spaces-4);
|
||||
|
|
@ -234,13 +215,6 @@ export function EditorJSONtoForm(props: Props) {
|
|||
FEATURE_FLAG.release_actions_redesign_enabled,
|
||||
);
|
||||
|
||||
const showRightPane = Boolean(actionRightPaneAdditionSections);
|
||||
|
||||
// get the current action's plugin name
|
||||
const currentActionPluginName = useSelector((state: AppState) =>
|
||||
getPluginNameFromId(state, currentActionConfig?.pluginId || ""),
|
||||
);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleDocumentationClick = () => {
|
||||
|
|
@ -254,21 +228,12 @@ export function EditorJSONtoForm(props: Props) {
|
|||
id: currentActionConfig ? currentActionConfig.id : "",
|
||||
};
|
||||
|
||||
const { hasDependencies } = useEntityDependencies(props.actionName);
|
||||
|
||||
const selectedConfigTab = useSelector(getQueryPaneConfigSelectedTabIndex);
|
||||
|
||||
const setSelectedConfigTab = useCallback((selectedIndex: string) => {
|
||||
dispatch(setQueryPaneConfigSelectedTabIndex(selectedIndex));
|
||||
}, []);
|
||||
|
||||
// here we check for normal conditions for opening action pane
|
||||
// or if any of the flags are true, We should open the actionpane by default.
|
||||
const shouldOpenActionPaneByDefault =
|
||||
hasDependencies ||
|
||||
!!actionResponse ||
|
||||
currentActionPluginName !== PluginName.SMTP;
|
||||
|
||||
// when switching between different redux forms, make sure this redux form has been initialized before rendering anything.
|
||||
// the initialized prop below comes from redux-form.
|
||||
if (!props.initialized) {
|
||||
|
|
@ -419,14 +384,10 @@ export function EditorJSONtoForm(props: Props) {
|
|||
/>
|
||||
</SecondaryWrapper>
|
||||
</div>
|
||||
{showRightPane && (
|
||||
<SidebarWrapper show={shouldOpenActionPaneByDefault}>
|
||||
<ActionRightPane
|
||||
actionRightPaneBackLink={actionRightPaneBackLink}
|
||||
additionalSections={actionRightPaneAdditionSections}
|
||||
/>
|
||||
</SidebarWrapper>
|
||||
)}
|
||||
<ActionRightPane
|
||||
actionRightPaneBackLink={actionRightPaneBackLink}
|
||||
additionalSections={actionRightPaneAdditionSections}
|
||||
/>
|
||||
</Wrapper>
|
||||
</QueryFormContainer>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import { DatasourceCreateEntryPoints } from "constants/Datasource";
|
|||
import {
|
||||
getAction,
|
||||
getIsActionConverting,
|
||||
getPluginImages,
|
||||
getPluginSettingConfigs,
|
||||
} from "@appsmith/selectors/entitiesSelector";
|
||||
import { integrationEditorURL } from "@appsmith/RouteBuilder";
|
||||
|
|
@ -38,6 +39,8 @@ import { MODULE_TYPE } from "@appsmith/constants/ModuleConstants";
|
|||
import ConvertEntityNotification from "@appsmith/pages/common/ConvertEntityNotification";
|
||||
import { PluginType } from "entities/Action";
|
||||
import { useIsEditorPaneSegmentsEnabled } from "../IDE/hooks";
|
||||
import { Icon } from "design-system";
|
||||
import { resolveIcon } from "../utils";
|
||||
|
||||
type QueryEditorProps = RouteComponentProps<QueryEditorRouteParams>;
|
||||
|
||||
|
|
@ -58,6 +61,12 @@ function QueryEditor(props: QueryEditorProps) {
|
|||
const isConverting = useSelector((state) =>
|
||||
getIsActionConverting(state, actionId || ""),
|
||||
);
|
||||
const pluginImages = useSelector(getPluginImages);
|
||||
const icon = resolveIcon({
|
||||
iconLocation: pluginImages[pluginId] || "",
|
||||
pluginType: action?.pluginType || "",
|
||||
moduleType: action?.actionConfiguration?.body?.moduleType,
|
||||
}) || <Icon name="module" />;
|
||||
|
||||
const isDeletePermitted = getHasDeleteActionPermission(
|
||||
isFeatureEnabled,
|
||||
|
|
@ -156,7 +165,13 @@ function QueryEditor(props: QueryEditorProps) {
|
|||
const notification = useMemo(() => {
|
||||
if (!isConverting) return null;
|
||||
|
||||
return <ConvertEntityNotification name={action?.name || ""} withPadding />;
|
||||
return (
|
||||
<ConvertEntityNotification
|
||||
icon={icon}
|
||||
name={action?.name || ""}
|
||||
withPadding
|
||||
/>
|
||||
);
|
||||
}, [action?.name, isConverting]);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,178 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
import { saveSelectedThemeAction } from "actions/appThemingActions";
|
||||
import { getCurrentApplicationId } from "selectors/editorSelectors";
|
||||
import { getAppThemes } from "selectors/appThemingSelectors";
|
||||
import {
|
||||
createMessage,
|
||||
ERROR_MESSAGE_NAME_EMPTY,
|
||||
APLHANUMERIC_HYPHEN_SLASH_SPACE_ERROR,
|
||||
UNIQUE_NAME_ERROR,
|
||||
} from "@appsmith/constants/messages";
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Text,
|
||||
Modal,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalFooter,
|
||||
ModalBody,
|
||||
} from "design-system";
|
||||
|
||||
interface SaveThemeModalProps {
|
||||
isOpen: boolean;
|
||||
onClose(): void;
|
||||
}
|
||||
|
||||
function SaveThemeModal(props: SaveThemeModalProps) {
|
||||
const { isOpen } = props;
|
||||
const dispatch = useDispatch();
|
||||
const [name, setName] = useState("");
|
||||
const [inputValidator, setInputValidator] = useState({
|
||||
isValid: false,
|
||||
message: "",
|
||||
isDirty: false,
|
||||
});
|
||||
const applicationId = useSelector(getCurrentApplicationId);
|
||||
const themes = useSelector(getAppThemes);
|
||||
|
||||
/**
|
||||
* dispatches action to save selected theme
|
||||
*
|
||||
*/
|
||||
const onSubmit = (event: any) => {
|
||||
event.preventDefault();
|
||||
|
||||
// if input validations fails, don't do anything
|
||||
if (!inputValidator.isValid || inputValidator.isDirty === false) return;
|
||||
|
||||
AnalyticsUtil.logEvent("APP_THEMING_SAVE_THEME_SUCCESS", {
|
||||
themeName: name,
|
||||
});
|
||||
|
||||
dispatch(saveSelectedThemeAction({ applicationId, name }));
|
||||
|
||||
// close the modal after submit
|
||||
onClose();
|
||||
};
|
||||
|
||||
/**
|
||||
* theme creation validator
|
||||
*
|
||||
* @param value
|
||||
* @returns
|
||||
*/
|
||||
const createThemeValidator = (value: string) => {
|
||||
let isValid = !!value;
|
||||
|
||||
let errorMessage = !isValid ? createMessage(ERROR_MESSAGE_NAME_EMPTY) : "";
|
||||
|
||||
if (
|
||||
isValid &&
|
||||
themes.find((theme) => value.toLowerCase() === theme.name.toLowerCase())
|
||||
) {
|
||||
isValid = false;
|
||||
errorMessage = createMessage(UNIQUE_NAME_ERROR);
|
||||
}
|
||||
|
||||
if (/[^a-zA-Z0-9\-\/\ ]/.test(value)) {
|
||||
isValid = false;
|
||||
errorMessage = createMessage(APLHANUMERIC_HYPHEN_SLASH_SPACE_ERROR);
|
||||
}
|
||||
|
||||
return {
|
||||
isValid: isValid,
|
||||
message: errorMessage,
|
||||
isDirty: true,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* on input change
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
const onChangeName = (value: string) => {
|
||||
const validator = createThemeValidator(value);
|
||||
|
||||
setInputValidator(validator);
|
||||
setName(value);
|
||||
};
|
||||
|
||||
/**
|
||||
* on close modal
|
||||
*/
|
||||
const onClose = () => {
|
||||
// reset validations
|
||||
setInputValidator({
|
||||
isValid: false,
|
||||
message: "",
|
||||
isDirty: false,
|
||||
});
|
||||
|
||||
props.onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
onOpenChange={(isOpen) => {
|
||||
if (!isOpen) {
|
||||
onClose();
|
||||
}
|
||||
}}
|
||||
open={isOpen}
|
||||
>
|
||||
<ModalContent
|
||||
id="save-theme-modal"
|
||||
onInteractOutside={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
style={{ width: "640px" }}
|
||||
>
|
||||
<ModalHeader>Save theme</ModalHeader>
|
||||
<ModalBody>
|
||||
<div className="flex flex-col gap-2">
|
||||
<Text kind="action-l">
|
||||
You can save your custom themes to use across applications and use
|
||||
them when you need.
|
||||
</Text>
|
||||
<form data-testid="save-theme-form" noValidate onSubmit={onSubmit}>
|
||||
<Input
|
||||
autoFocus
|
||||
errorMessage={
|
||||
!inputValidator.isValid ? inputValidator.message : undefined
|
||||
}
|
||||
isRequired
|
||||
label="Your theme name"
|
||||
name="name"
|
||||
onChange={onChangeName}
|
||||
placeholder="My theme"
|
||||
size="md"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<div className="flex gap-3">
|
||||
<Button kind="secondary" onClick={onClose} size="md">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
isDisabled={!name}
|
||||
onClick={onSubmit}
|
||||
size="md"
|
||||
type="submit"
|
||||
>
|
||||
Save theme
|
||||
</Button>
|
||||
</div>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export default SaveThemeModal;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import styled, { createGlobalStyle } from "styled-components";
|
||||
import { get, startCase } from "lodash";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import React, { useCallback, useState } from "react";
|
||||
import React, { useCallback } from "react";
|
||||
|
||||
import ThemeCard from "./ThemeCard";
|
||||
import {
|
||||
|
|
@ -15,7 +15,6 @@ import {
|
|||
updateSelectedAppThemeAction,
|
||||
} from "actions/appThemingActions";
|
||||
import SettingSection from "./SettingSection";
|
||||
import SaveThemeModal from "./SaveThemeModal";
|
||||
import type { AppTheme } from "entities/AppTheming";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
import ThemeFontControl from "./controls/ThemeFontControl";
|
||||
|
|
@ -64,7 +63,6 @@ function ThemeEditor() {
|
|||
const applicationId = useSelector(getCurrentApplicationId);
|
||||
const selectedTheme = useSelector(getSelectedAppTheme);
|
||||
const themingStack = useSelector(getAppThemingStack);
|
||||
const [isSaveModalOpen, setSaveModalOpen] = useState(false);
|
||||
|
||||
/**
|
||||
* customizes the current theme
|
||||
|
|
@ -95,22 +93,6 @@ function ThemeEditor() {
|
|||
);
|
||||
}, [setAppThemingModeStackAction]);
|
||||
|
||||
/**
|
||||
* open the save modal
|
||||
*/
|
||||
const onOpenSaveModal = useCallback(() => {
|
||||
AnalyticsUtil.logEvent("APP_THEMING_SAVE_THEME_START");
|
||||
|
||||
setSaveModalOpen(true);
|
||||
}, [setSaveModalOpen]);
|
||||
|
||||
/**
|
||||
* on close save modal
|
||||
*/
|
||||
const onCloseSaveModal = useCallback(() => {
|
||||
setSaveModalOpen(false);
|
||||
}, [setSaveModalOpen]);
|
||||
|
||||
/**
|
||||
* resets theme
|
||||
*/
|
||||
|
|
@ -136,9 +118,6 @@ function ThemeEditor() {
|
|||
/>
|
||||
</MenuTrigger>
|
||||
<MenuContent align="end" className="t--save-theme-menu">
|
||||
<MenuItem onClick={onOpenSaveModal} startIcon="save">
|
||||
Save theme
|
||||
</MenuItem>
|
||||
<MenuItem onClick={onResetTheme} startIcon="arrow-go-back">
|
||||
Reset widget styles
|
||||
</MenuItem>
|
||||
|
|
@ -270,7 +249,6 @@ function ThemeEditor() {
|
|||
)}
|
||||
</SettingSection>
|
||||
</main>
|
||||
<SaveThemeModal isOpen={isSaveModalOpen} onClose={onCloseSaveModal} />
|
||||
<PopoverStyles />
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
import { Tooltip } from "design-system";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { modText } from "utils/helpers";
|
||||
import { useSelector } from "react-redux";
|
||||
import { getWidgetSelectionBlock } from "selectors/ui";
|
||||
import { retrieveCodeWidgetNavigationUsed } from "utils/storage";
|
||||
|
||||
const CodeModeTooltip = (props: { children: React.ReactElement }) => {
|
||||
const isWidgetSelectionBlock = useSelector(getWidgetSelectionBlock);
|
||||
const [shouldShow, setShouldShow] = useState<boolean>(false);
|
||||
useEffect(() => {
|
||||
retrieveCodeWidgetNavigationUsed()
|
||||
.then((timesUsed) => {
|
||||
if (timesUsed < 2) {
|
||||
setShouldShow(true);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
setShouldShow(true);
|
||||
});
|
||||
}, [isWidgetSelectionBlock]);
|
||||
if (!isWidgetSelectionBlock) return props.children;
|
||||
return (
|
||||
<Tooltip
|
||||
content={`💡 ${modText()} click a widget to navigate to UI mode.`}
|
||||
isDisabled={!shouldShow}
|
||||
placement={"bottom"}
|
||||
showArrow={false}
|
||||
trigger={"hover"}
|
||||
>
|
||||
{props.children}
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export default CodeModeTooltip;
|
||||
|
|
@ -27,8 +27,17 @@ const StyledModalContent = styled(ModalContent)`
|
|||
width: 640px;
|
||||
`;
|
||||
|
||||
function ImportedApplicationSuccessModal() {
|
||||
const importedAppSuccess = localStorage.getItem("importApplicationSuccess");
|
||||
interface ImportSuccessModalProps {
|
||||
title?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
function ImportSuccessModal(props: ImportSuccessModalProps) {
|
||||
const {
|
||||
description = createMessage(APPLICATION_IMPORT_SUCCESS_DESCRIPTION),
|
||||
title = createMessage(APPLICATION_IMPORT_SUCCESS),
|
||||
} = props;
|
||||
const importedAppSuccess = localStorage.getItem("importSuccess");
|
||||
// const isOpen = importedAppSuccess === "true";
|
||||
const [isOpen, setIsOpen] = useState(importedAppSuccess === "true");
|
||||
|
||||
|
|
@ -40,7 +49,7 @@ function ImportedApplicationSuccessModal() {
|
|||
|
||||
const close = () => {
|
||||
setIsOpen(false);
|
||||
localStorage.setItem("importApplicationSuccess", "false");
|
||||
localStorage.setItem("importSuccess", "false");
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -54,10 +63,8 @@ function ImportedApplicationSuccessModal() {
|
|||
name="success"
|
||||
size={"lg"}
|
||||
/>
|
||||
<Text kind="heading-m">
|
||||
{createMessage(APPLICATION_IMPORT_SUCCESS)}
|
||||
</Text>
|
||||
<Text>{createMessage(APPLICATION_IMPORT_SUCCESS_DESCRIPTION)}</Text>
|
||||
<Text kind="heading-m">{title}</Text>
|
||||
<Text>{description}</Text>
|
||||
</BodyContainer>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
|
|
@ -76,4 +83,4 @@ function ImportedApplicationSuccessModal() {
|
|||
);
|
||||
}
|
||||
|
||||
export default ImportedApplicationSuccessModal;
|
||||
export default ImportSuccessModal;
|
||||
|
|
@ -19,9 +19,7 @@ import {
|
|||
RECONNECT_DATASOURCE_SUCCESS_MESSAGE1,
|
||||
RECONNECT_DATASOURCE_SUCCESS_MESSAGE2,
|
||||
RECONNECT_MISSING_DATASOURCE_CREDENTIALS,
|
||||
RECONNECT_MISSING_DATASOURCE_CREDENTIALS_DESCRIPTION,
|
||||
SKIP_CONFIGURATION,
|
||||
SKIP_TO_APPLICATION,
|
||||
SKIP_TO_APPLICATION_TOOLTIP_DESCRIPTION,
|
||||
} from "@appsmith/constants/messages";
|
||||
import {
|
||||
|
|
@ -51,7 +49,6 @@ import {
|
|||
getOAuthAccessToken,
|
||||
loadFilePickerAction,
|
||||
} from "actions/datasourceActions";
|
||||
import { builderURL } from "@appsmith/RouteBuilder";
|
||||
import localStorage from "utils/localStorage";
|
||||
import {
|
||||
Modal,
|
||||
|
|
@ -76,6 +73,9 @@ import {
|
|||
import type { AppState } from "@appsmith/reducers";
|
||||
import { getFetchedWorkspaces } from "@appsmith/selectors/workspaceSelectors";
|
||||
import { getApplicationsOfWorkspace } from "@appsmith/selectors/selectedWorkspaceSelectors";
|
||||
import useReconnectModalData from "@appsmith/pages/Editor/gitSync/useReconnectModalData";
|
||||
import { resetImportData } from "@appsmith/actions/workspaceActions";
|
||||
import history from "utils/history";
|
||||
|
||||
const Section = styled.div`
|
||||
display: flex;
|
||||
|
|
@ -289,7 +289,6 @@ function ReconnectDatasourceModal() {
|
|||
>(queryDatasourceId);
|
||||
const [pageId, setPageId] = useState<string | null>(queryPageId);
|
||||
const [appId, setAppId] = useState<string | null>(queryAppId);
|
||||
const [appURL, setAppURL] = useState("");
|
||||
const [datasource, setDatasource] = useState<Datasource | null>(null);
|
||||
const [isImport, setIsImport] = useState(queryIsImport);
|
||||
const [isTesting, setIsTesting] = useState(false);
|
||||
|
|
@ -312,6 +311,21 @@ function ReconnectDatasourceModal() {
|
|||
return output;
|
||||
};
|
||||
|
||||
/**
|
||||
* The role of useReconnectModalData is to provide editorId (appId or packageId), parentEntityId (pageId or moduleId)
|
||||
* and any differentiating elements when a app vs package is imported.
|
||||
* Right now it takes the pageId and appId and returns editorId/parentEntityId to reduces the changes required to
|
||||
* refactor this for packages. Ideally the hook should calculate everything and return the necessary values.
|
||||
*/
|
||||
const {
|
||||
editorId,
|
||||
editorType,
|
||||
editorURL,
|
||||
missingDsCredentialsDescription, // pageId or moduleId
|
||||
parentEntityId, // appId or packageId from query params
|
||||
skipMessage,
|
||||
} = useReconnectModalData({ pageId, appId });
|
||||
|
||||
// when redirecting from oauth, processing the status
|
||||
if (isImport) {
|
||||
setIsImport(false);
|
||||
|
|
@ -333,6 +347,7 @@ function ReconnectDatasourceModal() {
|
|||
workspaceId: orgId,
|
||||
datasourceName: dsName,
|
||||
pluginName: plugins[datasource?.pluginId || ""]?.name,
|
||||
editorType,
|
||||
});
|
||||
} else if (queryDatasourceId) {
|
||||
dispatch(loadFilePickerAction());
|
||||
|
|
@ -348,7 +363,7 @@ function ReconnectDatasourceModal() {
|
|||
if (app) {
|
||||
dispatch(
|
||||
setWorkspaceIdForImport({
|
||||
editorId: appId || "",
|
||||
editorId: editorId || "",
|
||||
workspaceId: app.workspaceId,
|
||||
}),
|
||||
);
|
||||
|
|
@ -363,7 +378,7 @@ function ReconnectDatasourceModal() {
|
|||
dispatch({
|
||||
type: ReduxActionTypes.FETCH_UNCONFIGURED_DATASOURCE_LIST,
|
||||
payload: {
|
||||
applicationId: appId,
|
||||
applicationId: editorId,
|
||||
workspaceId: app.workspaceId,
|
||||
},
|
||||
});
|
||||
|
|
@ -428,15 +443,20 @@ function ReconnectDatasourceModal() {
|
|||
}
|
||||
};
|
||||
|
||||
const clearImportData = () => {
|
||||
dispatch(resetImportData());
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
localStorage.setItem("importedAppPendingInfo", "null");
|
||||
dispatch(setIsReconnectingDatasourcesModalOpen({ isOpen: false }));
|
||||
dispatch(
|
||||
setWorkspaceIdForImport({ editorId: appId || "", workspaceId: "" }),
|
||||
setWorkspaceIdForImport({ editorId: editorId || "", workspaceId: "" }),
|
||||
);
|
||||
dispatch(setPageIdForImport(""));
|
||||
dispatch(resetDatasourceConfigForImportFetchedFlag());
|
||||
setSelectedDatasourceId("");
|
||||
clearImportData();
|
||||
};
|
||||
|
||||
const onSelectDatasource = useCallback((ds: Datasource) => {
|
||||
|
|
@ -478,17 +498,6 @@ function ReconnectDatasourceModal() {
|
|||
}
|
||||
}, [importedApplication, queryIsImport]);
|
||||
|
||||
useEffect(() => {
|
||||
if (pageId) {
|
||||
// TODO: Update route params here
|
||||
setAppURL(
|
||||
builderURL({
|
||||
pageId: pageId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}, [pageId]);
|
||||
|
||||
// checking of full configured
|
||||
useEffect(() => {
|
||||
if (isModalOpen && !isTesting) {
|
||||
|
|
@ -524,14 +533,14 @@ function ReconnectDatasourceModal() {
|
|||
}
|
||||
// When datasources are present and pending datasources are 0,
|
||||
// then only we want to update status as success
|
||||
else if (appURL && pending.length === 0 && datasources.length > 0) {
|
||||
else if (editorURL && pending.length === 0 && datasources.length > 0) {
|
||||
// open application import successfule
|
||||
localStorage.setItem("importApplicationSuccess", "true");
|
||||
localStorage.setItem("importSuccess", "true");
|
||||
localStorage.setItem("importedAppPendingInfo", "null");
|
||||
window.open(appURL, "_self");
|
||||
window.open(editorURL, "_self");
|
||||
}
|
||||
}
|
||||
}, [datasources, appURL, isModalOpen, isTesting, queryIsImport]);
|
||||
}, [datasources, editorURL, isModalOpen, isTesting, queryIsImport]);
|
||||
|
||||
const mappedDataSources = datasources.map((ds: Datasource) => {
|
||||
return (
|
||||
|
|
@ -551,6 +560,13 @@ function ReconnectDatasourceModal() {
|
|||
const shouldShowDBForm =
|
||||
isConfigFetched && !isLoading && !checkIfDatasourceIsConfigured(datasource);
|
||||
|
||||
const onSkipBtnClick = () => {
|
||||
AnalyticsUtil.logEvent("RECONNECTING_SKIP_TO_APPLICATION_BUTTON_CLICK");
|
||||
localStorage.setItem("importedAppPendingInfo", "null");
|
||||
editorURL && history.push(editorURL);
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal open={isModalOpen}>
|
||||
<ModalContentWrapper
|
||||
|
|
@ -567,23 +583,19 @@ function ReconnectDatasourceModal() {
|
|||
{createMessage(RECONNECT_MISSING_DATASOURCE_CREDENTIALS)}
|
||||
</Title>
|
||||
|
||||
<Text>
|
||||
{createMessage(
|
||||
RECONNECT_MISSING_DATASOURCE_CREDENTIALS_DESCRIPTION,
|
||||
)}
|
||||
</Text>
|
||||
<Text>{missingDsCredentialsDescription}</Text>
|
||||
<ContentWrapper>
|
||||
<ListContainer>{mappedDataSources}</ListContainer>
|
||||
|
||||
<DBFormWrapper>
|
||||
{shouldShowDBForm && (
|
||||
<DatasourceForm
|
||||
applicationId={appId}
|
||||
applicationId={editorId}
|
||||
datasourceId={selectedDatasourceId}
|
||||
fromImporting
|
||||
// isInsideReconnectModal: indicates that the datasource form is rendering inside reconnect modal
|
||||
isInsideReconnectModal
|
||||
pageId={pageId}
|
||||
pageId={parentEntityId}
|
||||
/>
|
||||
)}
|
||||
{checkIfDatasourceIsConfigured(datasource) && SuccessMessages()}
|
||||
|
|
@ -599,18 +611,12 @@ function ReconnectDatasourceModal() {
|
|||
<Button
|
||||
UNSAFE_width={"100px"}
|
||||
className="t--skip-to-application-btn mt-5"
|
||||
href={appURL}
|
||||
kind="secondary"
|
||||
onClick={() => {
|
||||
AnalyticsUtil.logEvent(
|
||||
"RECONNECTING_SKIP_TO_APPLICATION_BUTTON_CLICK",
|
||||
);
|
||||
localStorage.setItem("importedAppPendingInfo", "null");
|
||||
}}
|
||||
onClick={onSkipBtnClick}
|
||||
renderAs="a"
|
||||
size="md"
|
||||
>
|
||||
{createMessage(SKIP_TO_APPLICATION)}
|
||||
{skipMessage}
|
||||
</Button>
|
||||
</SkipToAppWrapper>
|
||||
</ContentWrapper>
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ export enum Kind {
|
|||
JS_LIB = "JS_LIB",
|
||||
THEME = "THEME",
|
||||
SETTINGS = "SETTINGS",
|
||||
PACKAGES = "PACKAGES",
|
||||
MODULES = "MODULES",
|
||||
}
|
||||
|
||||
interface GitStatusProps {
|
||||
|
|
@ -125,6 +127,22 @@ const STATUS_MAP: GitStatusMap = {
|
|||
iconName: "package",
|
||||
hasValue: (status?.modifiedJSLibs || 0) > 0,
|
||||
}),
|
||||
[Kind.PACKAGES]: (status) => ({
|
||||
message: `${status?.modifiedPackages || 0} ${
|
||||
(status?.modifiedPackages || 0) <= 1 ? "package" : "packages"
|
||||
} modified`,
|
||||
iconName: "package",
|
||||
hasValue: (status?.modifiedPackages || 0) > 0,
|
||||
}),
|
||||
[Kind.MODULES]: (status) => ({
|
||||
message: `${status?.modifiedModules || 0} ${
|
||||
(status?.modifiedModules || 0) <= 1
|
||||
? "module configuration"
|
||||
: "module configurations"
|
||||
} modified`,
|
||||
iconName: "package",
|
||||
hasValue: (status?.modifiedModules || 0) > 0,
|
||||
}),
|
||||
};
|
||||
|
||||
function behindCommitMessage(status: Partial<GitStatusData>) {
|
||||
|
|
@ -193,6 +211,8 @@ export function gitChangeListData(
|
|||
Kind.JS_OBJECT,
|
||||
Kind.DATA_SOURCE,
|
||||
Kind.JS_LIB,
|
||||
Kind.MODULES,
|
||||
Kind.PACKAGES,
|
||||
];
|
||||
return changeKind
|
||||
.map((type: Kind) => STATUS_MAP[type](status))
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import { setupPage, updateCurrentPage } from "actions/pageActions";
|
|||
import { getCurrentPageId } from "selectors/editorSelectors";
|
||||
import { getSearchQuery } from "utils/helpers";
|
||||
import RepoLimitExceededErrorModal from "./gitSync/RepoLimitExceededErrorModal";
|
||||
import ImportedApplicationSuccessModal from "./gitSync/ImportedAppSuccessModal";
|
||||
import ImportedApplicationSuccessModal from "./gitSync/ImportSuccessModal";
|
||||
import { getIsBranchUpdated } from "../utils";
|
||||
import { APP_MODE } from "entities/App";
|
||||
import { GIT_BRANCH_QUERY_KEY } from "constants/routes";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { debounce, random } from "lodash";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useLocation } from "react-router";
|
||||
import { debounce, random } from "lodash";
|
||||
import type {
|
||||
WidgetCardsGroupedByTags,
|
||||
WidgetTags,
|
||||
|
|
@ -19,6 +20,15 @@ import { useSelector } from "react-redux";
|
|||
import { getCurrentPageId } from "selectors/editorSelectors";
|
||||
import type { WidgetCardProps } from "widgets/BaseWidget";
|
||||
import type { ActionResponse } from "api/ActionAPI";
|
||||
import { MODULE_TYPE } from "@appsmith/constants/ModuleConstants";
|
||||
import {
|
||||
ENTITY_ICON_SIZE,
|
||||
EntityIcon,
|
||||
JsFileIconV2,
|
||||
dbQueryIcon,
|
||||
} from "pages/Editor/Explorer/ExplorerIcons";
|
||||
import { PluginType } from "entities/Action";
|
||||
import { getAssetUrl } from "@appsmith/utils/airgapHelpers";
|
||||
|
||||
export const draggableElement = (
|
||||
id: string,
|
||||
|
|
@ -336,3 +346,38 @@ export const actionResponseDisplayDataFormats = (
|
|||
responseDisplayFormat,
|
||||
};
|
||||
};
|
||||
|
||||
function resolveQueryModuleIcon(
|
||||
iconLocation: string,
|
||||
pluginType: string,
|
||||
isLargeIcon: boolean,
|
||||
) {
|
||||
if (iconLocation)
|
||||
return (
|
||||
<EntityIcon
|
||||
height={`${isLargeIcon ? ENTITY_ICON_SIZE * 2 : ENTITY_ICON_SIZE}px`}
|
||||
width={`${isLargeIcon ? ENTITY_ICON_SIZE * 2 : ENTITY_ICON_SIZE}px`}
|
||||
>
|
||||
<img alt="entityIcon" src={getAssetUrl(iconLocation)} />
|
||||
</EntityIcon>
|
||||
);
|
||||
else if (pluginType === PluginType.DB) return dbQueryIcon;
|
||||
}
|
||||
|
||||
export function resolveIcon({
|
||||
iconLocation,
|
||||
isLargeIcon = false,
|
||||
moduleType,
|
||||
pluginType,
|
||||
}: {
|
||||
iconLocation: string;
|
||||
pluginType: string;
|
||||
moduleType: string;
|
||||
isLargeIcon?: boolean;
|
||||
}) {
|
||||
if (moduleType === MODULE_TYPE.JS) {
|
||||
return isLargeIcon ? JsFileIconV2(34, 34) : JsFileIconV2(16, 16);
|
||||
} else {
|
||||
return resolveQueryModuleIcon(iconLocation, pluginType, isLargeIcon);
|
||||
}
|
||||
}
|
||||
|
|
@ -111,12 +111,6 @@ const themeReducer = createImmerReducer(initialState, {
|
|||
(theme) => theme.id !== action.payload.themeId,
|
||||
);
|
||||
},
|
||||
[ReduxActionTypes.SAVE_APP_THEME_SUCCESS]: (
|
||||
state: AppThemingState,
|
||||
action: ReduxAction<AppTheme>,
|
||||
) => {
|
||||
state.themes.push(action.payload);
|
||||
},
|
||||
[ReduxActionTypes.UPDATE_BETA_CARD_SHOWN]: (
|
||||
state: AppThemingState,
|
||||
action: ReduxAction<boolean>,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ const initialState: WidgetDragResizeState = {
|
|||
isDistributingSpace: false,
|
||||
},
|
||||
isDraggingDisabled: false,
|
||||
blockSelection: false,
|
||||
altFocus: false,
|
||||
};
|
||||
|
||||
export const widgetDraggingReducer = createImmerReducer(initialState, {
|
||||
|
|
@ -100,11 +102,20 @@ export const widgetDraggingReducer = createImmerReducer(initialState, {
|
|||
},
|
||||
[ReduxActionTypes.FOCUS_WIDGET]: (
|
||||
state: WidgetDragResizeState,
|
||||
action: ReduxAction<{ widgetId?: string }>,
|
||||
action: ReduxAction<{ widgetId?: string; alt?: boolean }>,
|
||||
) => {
|
||||
if (state.focusedWidget !== action.payload.widgetId) {
|
||||
state.focusedWidget = action.payload.widgetId;
|
||||
}
|
||||
if (state.altFocus !== action.payload.alt) {
|
||||
state.altFocus = !!action.payload.alt;
|
||||
}
|
||||
},
|
||||
[ReduxActionTypes.ALT_FOCUS_WIDGET]: (
|
||||
state: WidgetDragResizeState,
|
||||
action: ReduxAction<boolean>,
|
||||
) => {
|
||||
state.altFocus = action.payload;
|
||||
},
|
||||
[ReduxActionTypes.SET_SELECTED_WIDGET_ANCESTRY]: (
|
||||
state: WidgetDragResizeState,
|
||||
|
|
@ -118,6 +129,12 @@ export const widgetDraggingReducer = createImmerReducer(initialState, {
|
|||
) => {
|
||||
state.entityExplorerAncestry = action.payload;
|
||||
},
|
||||
[ReduxActionTypes.SET_WIDGET_SELECTION_BLOCK]: (
|
||||
state: WidgetDragResizeState,
|
||||
action: ReduxAction<boolean>,
|
||||
) => {
|
||||
state.blockSelection = action.payload;
|
||||
},
|
||||
//space distribution redux
|
||||
[AnvilReduxActionTypes.ANVIL_SPACE_DISTRIBUTION_START]: (
|
||||
state: WidgetDragResizeState,
|
||||
|
|
@ -166,6 +183,8 @@ export interface WidgetDragResizeState {
|
|||
selectedWidgets: string[];
|
||||
isAutoCanvasResizing: boolean;
|
||||
isDraggingDisabled: boolean;
|
||||
blockSelection: boolean;
|
||||
altFocus: boolean;
|
||||
}
|
||||
|
||||
export default widgetDraggingReducer;
|
||||
|
|
|
|||
|
|
@ -670,6 +670,9 @@ export interface GitStatusData {
|
|||
modifiedJSLibs: number;
|
||||
discardDocUrl?: string;
|
||||
migrationMessage?: string;
|
||||
modifiedPackages?: number;
|
||||
modifiedModules?: number;
|
||||
modifiedModuleInstances?: number;
|
||||
}
|
||||
|
||||
interface GitErrorPayloadType {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user