Skip to content

Commit

Permalink
[NU-2015] Component labels (#7578)
Browse files Browse the repository at this point in the history
* Labels for provided components set and label is displayed on components palette instead of name
Label can be set in configuration

* Component label is now shown in node details modal instead of name

* Component label shown in components list

* Updated documentation and added an example in DevelopmentTest category, `providedComponent-component-v1` has slightly different label now -configured in `dev-application.conf`

* If label is not provided in definition, we will set it to `name` in Title Case by default

* Updated snapshots (#7608)

Co-authored-by: ForrestFairy <[email protected]>

* IdToTitleConverter used and added default label for previousValue

* Updated snapshots (#7613)

Co-authored-by: ForrestFairy <[email protected]>

---------

Co-authored-by: Szymon Bogusz <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Mar 5, 2025
1 parent d0a88c8 commit 2435d04
Show file tree
Hide file tree
Showing 45 changed files with 152 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ case class ComponentConfig(
// It should be probable called designerWideComponentId but we don't want to change it
// to not break the compatibility
componentId: Option[DesignerWideComponentId],
disabled: Boolean = false
disabled: Boolean = false,
label: Option[String]
)

object ComponentConfig {

val zero: ComponentConfig = ComponentConfig(None, None, None, None, None)
val zero: ComponentConfig = ComponentConfig(None, None, None, None, None, false, None)

implicit val semigroup: Semigroup[ComponentConfig] = {
implicit def takeLeftOptionSemi[T]: Semigroup[Option[T]] = Semigroup.instance[Option[T]] {
Expand Down Expand Up @@ -51,6 +52,7 @@ object ComponentConfig {
x.docsUrl |+| y.docsUrl,
x.componentGroup |+| y.componentGroup,
x.componentId |+| y.componentId,
label = x.label |+| y.label
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import net.ceedubs.ficus.readers.{ArbitraryTypeReader, ValueReader}
import org.semver4j.Semver
import pl.touk.nussknacker.engine.api.component.Component._
import pl.touk.nussknacker.engine.api.process.ProcessObjectDependencies
import pl.touk.nussknacker.engine.util.IdToTitleConverter
import pl.touk.nussknacker.engine.version.BuildInfo

/**
Expand Down Expand Up @@ -144,11 +145,30 @@ case class NussknackerVersion(value: Semver)
case class ComponentDefinition(
name: String,
component: Component,
icon: Option[String] = None,
docsUrl: Option[String] = None,
designerWideId: Option[DesignerWideComponentId] = None
icon: Option[String],
docsUrl: Option[String],
designerWideId: Option[DesignerWideComponentId],
label: String
) {

def withDesignerWideId(id: String): ComponentDefinition = copy(designerWideId = Some(DesignerWideComponentId(id)))

}

object ComponentDefinition {

def apply(
name: String,
component: Component,
icon: Option[String] = None,
docsUrl: Option[String] = None,
designerWideId: Option[DesignerWideComponentId] = None,
label: Option[String] = None
): ComponentDefinition = {
label match {
case Some(value) => ComponentDefinition(name, component, icon, docsUrl, designerWideId, value)
case None => ComponentDefinition(name, component, icon, docsUrl, designerWideId, IdToTitleConverter.toTitle(name))
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class IdToTitleConverterTest extends AnyFunSuite with Matchers {
IdToTitleConverter.toTitle("") shouldEqual ""
IdToTitleConverter.toTitle("foo") shouldEqual "Foo"
IdToTitleConverter.toTitle("foo-bar") shouldEqual "Foo Bar"
IdToTitleConverter.toTitle("barFilter") shouldEqual "Barfilter"
}

}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions designer/client/cypress/e2e/compareVersions.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe("Compare versions", () => {
cy.contains(/^fragments$/)
.should("exist")
.scrollIntoView();
cy.contains("fragment_xxx-test-process")
cy.contains("Fragment_xxx Test Process")
.last()
.should("be.visible")
.move({ x, y, position: "right", force: true })
Expand All @@ -45,7 +45,7 @@ describe("Compare versions", () => {
.trigger("mouseup", { force: true });

// Change fragment param and save changes
cy.get("[model-id^=e2e][model-id$=fragment_xxx-test-process]").should("be.visible").trigger("dblclick");
cy.get('[model-id^=E2e][model-id$="001 Fragment_xxx Test Process"]').should("be.visible").trigger("dblclick");
cy.get("[data-testid=window]").find('[title="i222"]').siblings().eq(0).find("#ace-editor").type("4");
cy.contains(/^apply/i)
.should("be.enabled")
Expand All @@ -55,7 +55,7 @@ describe("Compare versions", () => {
cy.get("[data-testid=window]").should("not.exist");

// Change fragment param again and save changes
cy.get("[model-id^=e2e][model-id$=fragment_xxx-test-process]").should("be.visible").trigger("dblclick");
cy.get('[model-id^=E2e][model-id$="001 Fragment_xxx Test Process"]').should("be.visible").trigger("dblclick");
cy.get("[data-testid=window]").find('[title="i222"]').siblings().eq(0).find("#ace-editor").type("7");
cy.contains(/^apply/i)
.should("be.enabled")
Expand Down
10 changes: 5 additions & 5 deletions designer/client/cypress/e2e/components.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe("Components list", () => {
filterByDefaultCategory();
cy.contains(/^name$/i).should("be.visible");
cy.contains(/^categories$/i).should("be.visible");
cy.contains(/^for-each$/).should("be.visible");
cy.contains(/^For Each$/).should("be.visible");
cy.get("#app-container").matchImage();
});

Expand All @@ -41,7 +41,7 @@ describe("Components list", () => {
it("should allow filtering by name", () => {
filterByDefaultCategory();
cy.get("[placeholder='Search...']").type("for", { force: true });
cy.contains(/^for-each$/i).should("be.visible");
cy.contains(/^For Each$/i).should("be.visible");
cy.get("[role=row]").should("have.lengthOf", 2);
cy.get("[placeholder='Search...']").type("-dummy");
cy.get("[role=row]").should("have.lengthOf", 1);
Expand All @@ -54,7 +54,7 @@ describe("Components list", () => {
force: true,
delay: 100,
});
cy.contains(/^for-each$/i).should("be.visible");
cy.contains(/^For Each$/i).should("be.visible");
cy.get("[role=row]").should("have.lengthOf", 2);
cy.matchQuery("?CATEGORY=Default&NAME=fo+ea");
cy.get("[role=grid]").matchImage();
Expand All @@ -79,7 +79,7 @@ describe("Components list", () => {
.click();
cy.get("[role=row]")
.should("have.lengthOf", baseGroupComponents + 1)
.contains(":not(title)", /^filter$/)
.contains(":not(title)", /^Filter$/)
.should("be.visible");
cy.get(`[data-testid="FilterListOffIcon"]`).click();
cy.get("[role=row]").should("have.length.greaterThan", 2);
Expand Down Expand Up @@ -191,7 +191,7 @@ describe("Components list", () => {
cy.visitNewProcess(`${seed}_yyy`, "testProcess2");
cy.get("#toolbox").contains("fragments").should("exist").scrollIntoView();
cy.layoutScenario();
cy.contains(`${seed}_xxx`)
cy.contains(`${seed.charAt(0).toUpperCase() + seed.slice(1)}_xxx`)
.last()
.should("be.visible")
.drag("#nk-graph-main", {
Expand Down
14 changes: 7 additions & 7 deletions designer/client/cypress/e2e/fragment.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ describe("Fragment", () => {
cy.contains(/^fragments$/)
.should("exist")
.scrollIntoView();
cy.contains("fragment-test")
cy.contains("Fragment Test")
.last()
.should("be.visible")
.drag("#nk-graph-main", {
Expand All @@ -189,7 +189,7 @@ describe("Fragment", () => {

cy.intercept("POST", "/api/nodes/*/validation").as("fragmentInputValidation");

cy.get("[model-id^=e2e][model-id$=fragment-test-process]").should("be.visible").trigger("dblclick");
cy.get('[model-id^=E2e][model-id$="001 Fragment Test Process"]').should("be.visible").trigger("dblclick");
cy.get("#nk-graph-fragment [model-id='input']").scrollIntoView().should("be.visible");

cy.wait("@fragmentInputValidation");
Expand Down Expand Up @@ -273,7 +273,7 @@ describe("Fragment", () => {
cy.contains(/^ok$/i).click();

// Verify if Frontend received correct data after save
cy.get("[model-id^=e2e][model-id$=fragment-test-process]").trigger("dblclick");
cy.get('[model-id^=E2e][model-id$="001 Fragment Test Process"]').trigger("dblclick");
cy.get('[title="any_value_with_suggestions_preset"]').siblings().eq(0).find("#ace-editor").contains("#RGB()");
cy.contains(/^apply/i)
.should("be.enabled")
Expand All @@ -297,7 +297,7 @@ describe("Fragment", () => {
cy.go(1);

// Verify existing fragment after properties change
cy.get("[model-id^=e2e][model-id$=fragment-test-process]").should("be.visible").trigger("dblclick");
cy.get('[model-id^=E2e][model-id$="001 Fragment Test Process"]').should("be.visible").trigger("dblclick");
cy.get("[data-testid=window]").get("[title='name_value_string_any_value']").siblings().eq(0).find("[id='ace-editor']").type("test");

cy.get("@window")
Expand Down Expand Up @@ -350,7 +350,7 @@ describe("Fragment", () => {
cy.layoutScenario();

cy.contains("fragments").should("exist").scrollIntoView();
cy.contains(`${seed2}-test`)
cy.contains(`${seed2.charAt(0).toUpperCase() + seed2.slice(1)} Test`)
.last()
.should("be.visible")
.drag("#nk-graph-main", {
Expand All @@ -362,7 +362,7 @@ describe("Fragment", () => {
});
cy.layoutScenario();

cy.get(`[model-id^=e2e][model-id$=-${seed2}-test-process]`).should("be.visible").trigger("dblclick");
cy.get('[model-id^=E2e][model-id$="001 Fragment2 Test Process"]').should("be.visible").trigger("dblclick");

cy.get("[title='Documentation']").should("have.attr", "href", docsUrl).parent().matchImage();

Expand All @@ -379,7 +379,7 @@ describe("Fragment", () => {

cy.contains("fragments").should("exist").scrollIntoView();
cy.getNode("enricher").as("enricher");
cy.contains(`${fragmentName}-test`)
cy.contains(`${fragmentName} Test`)
.last()
.should("be.visible")
.drag("@enricher", {
Expand Down
4 changes: 2 additions & 2 deletions designer/client/cypress/e2e/nodeWindow.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe("Node window", () => {
.should("exist")
.scrollIntoView();
cy.layoutScenario();
cy.get("[data-testid='component:event-generator']")
cy.get("[data-testid='component:Event Generator']")
.should("be.visible")
.drag("#nk-graph-main", {
target: {
Expand All @@ -29,7 +29,7 @@ describe("Node window", () => {
force: true,
});

cy.getNode("event-generator").dblclick();
cy.getNode("Event Generator").dblclick();

// TODO: fix validation display in node windows
cy.intercept("POST", "/api/nodes/*/validation").as("validation");
Expand Down
14 changes: 7 additions & 7 deletions designer/client/cypress/e2e/process.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe("Process", () => {
cy.contains(/scenario was archived/i).should("be.visible");
});

it("should open properites from tips panel", () => {
it("should open properties from tips panel", () => {
cy.viewport("macbook-15");
cy.contains(/^properties/i)
.should("be.enabled")
Expand Down Expand Up @@ -139,7 +139,7 @@ describe("Process", () => {
.should("exist")
.scrollIntoView();
cy.layoutScenario();
cy.get("[data-testid='component:customFilter']")
cy.get("[data-testid='component:Customfilter']")
.should("be.visible")
.drag("#nk-graph-main", {
target: {
Expand Down Expand Up @@ -177,19 +177,19 @@ describe("Process", () => {

it("should display some node details in modal", () => {
cy.get("[model-id=dynamicService]").should("be.visible").trigger("dblclick");
cy.get("[data-testid=window]").contains("dynamicService").should("be.visible");
cy.get("[data-testid=window]").contains("Dynamicservice").should("be.visible");
cy.get("[data-testid=window]").should("be.visible").matchImage();
cy.get("[data-testid=window]")
.contains(/^cancel$/i)
.click();
cy.get("[model-id=boundedSource]").should("be.visible").trigger("dblclick");
cy.get("[data-testid=window]").contains("boundedSource").should("be.visible");
cy.get("[data-testid=window]").contains("Boundedsource").should("be.visible");
cy.get("[data-testid=window]").should("be.visible").matchImage();
cy.get("[data-testid=window]")
.contains(/^cancel$/i)
.click();
cy.get("[model-id=sendSms]").should("be.visible").trigger("dblclick");
cy.get("[data-testid=window]").contains("sendSms").should("be.visible");
cy.get("[data-testid=window]").contains("Sendsms").should("be.visible");
cy.get("[data-testid=window]").should("be.visible").matchImage();
});
});
Expand All @@ -214,7 +214,7 @@ describe("Process", () => {
.scrollIntoView();
const x = 900;
const y = 630;
cy.get("[data-testid='component:dead-end']").should("be.visible").drag("#nk-graph-main", {
cy.get("[data-testid='component:Dead End']").should("be.visible").drag("#nk-graph-main", {
target: {
x,
y,
Expand Down Expand Up @@ -269,7 +269,7 @@ describe("Process", () => {
.scrollIntoView();
const x = 700;
const y = 600;
cy.get("[data-testid='component:dead-end']").should("be.visible").drag("#nk-graph-main", {
cy.get("[data-testid='component:Dead End']").should("be.visible").drag("#nk-graph-main", {
target: {
x,
y,
Expand Down
4 changes: 2 additions & 2 deletions designer/client/cypress/e2e/switch.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe("Process", () => {
cy.contains(/^base$/)
.should("exist")
.scrollIntoView();
cy.contains(/^choice$/)
cy.contains(/^Choice$/)
.should("be.visible")
.drag("#nk-graph-main", {
target: {
Expand All @@ -28,7 +28,7 @@ describe("Process", () => {
force: true,
});
cy.layoutScenario();
cy.get("[model-id$=choice-sendSms-true]").should("be.visible").trigger("dblclick");
cy.get("[model-id$=Choice-sendSms-true]").should("be.visible").trigger("dblclick");

cy.get("[data-testid=window]").should("be.visible");
cy.get("[data-testid=window]").find("[data-testid='fieldsRow:0']").find(".ace_editor").as("input");
Expand Down
6 changes: 3 additions & 3 deletions designer/client/cypress/e2e/undo.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe("Undo/Redo", () => {

it("should work for add and move to edge", () => {
cy.get("@graph").matchImage(screenshotOptions);
cy.get("[data-testid='component:customFilter']")
cy.get("[data-testid='component:Customfilter']")
.should("be.visible")
.drag("#nk-graph-main", {
target: {
Expand All @@ -44,7 +44,7 @@ describe("Undo/Redo", () => {
force: true,
});
cy.get("@graph").matchImage(screenshotOptions);
cy.dragNode("customFilter", { x: 560, y: 500 });
cy.dragNode("Customfilter", { x: 560, y: 500 });
cy.get("@graph").matchImage(screenshotOptions);
cy.get("@undo").should("be.enabled").click();
cy.get("@graph").matchImage(screenshotOptions);
Expand All @@ -60,7 +60,7 @@ describe("Undo/Redo", () => {
cy.get("@graph").matchImage(screenshotOptions);
cy.getNode("boundedSource-enricher").find("[event=remove]").eq(0).click();
cy.getNode("enricher-dynamicService").find("[event=remove]").eq(0).click();
cy.get("[data-testid='component:customFilter']")
cy.get("[data-testid='component:Customfilter']")
.should("be.visible")
.drag("#nk-graph-main", {
target: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,11 @@ export const NodeDetailsModalSubheader = ({ node }: { node: NodeType }): ReactEl
const docsUrl = useMemo(() => {
return ProcessUtils.extractComponentDefinition(node, components)?.docsUrl;
}, [components, node]);
const label = useMemo(() => {
return ProcessUtils.extractComponentDefinition(node, components)?.label;
}, [components, node]);

const nodeClass = findNodeClass(node);

return <NodeDocs name={nodeClass} href={docsUrl} />;
return <NodeDocs name={label} href={docsUrl} />;
};

export const NodeDetailsModalIcon = styled(WindowHeaderIconStyled.withComponent(ComponentIcon))(({ node, theme }) => ({
Expand Down
1 change: 1 addition & 0 deletions designer/client/src/http/HttpService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export type ComponentType = {
icon: string;
url: string;
}>;
label: string;
};

export type SourceWithParametersTest = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ exports[`GraphUtils prepareNewNodesWithLayout should update union output express
},
"branchParameters": undefined,
"id": "variable 1 (copy 1)",
"label": "variable",
"type": "Variable",
"value": {
"expression": "'value'",
Expand All @@ -58,6 +59,7 @@ exports[`GraphUtils prepareNewNodesWithLayout should update union output express
},
"branchParameters": undefined,
"id": "variable 2 (copy 1)",
"label": "variable",
"type": "Variable",
"value": {
"expression": "'value'",
Expand Down Expand Up @@ -100,6 +102,7 @@ exports[`GraphUtils prepareNewNodesWithLayout should update union output express
},
],
"id": "union (copy 1)",
"label": "union",
"nodeType": "union",
"outputVar": "outputVar",
"parameters": [],
Expand Down
Loading

0 comments on commit 2435d04

Please sign in to comment.