diff --git a/build.sbt b/build.sbt
index ade9dbece4f..f7b8aca6623 100644
--- a/build.sbt
+++ b/build.sbt
@@ -349,6 +349,7 @@ val monocleV = "2.1.0"
val jmxPrometheusJavaagentV = "0.18.0"
val wireMockV = "2.35.0"
val findBugsV = "3.0.2"
+val enumeratumV = "1.7.3"
// depending on scala version one of this jar lays in Flink lib dir
def flinkLibScalaDeps(scalaVersion: String, configurations: Option[String] = None) = forScalaVersion(
@@ -742,7 +743,12 @@ lazy val defaultModel = (project in (file("defaultModel")))
.settings(assemblyNoScala("defaultModel.jar"): _*)
.settings(publishAssemblySettings: _*)
.settings(
- name := "nussknacker-default-model"
+ name := "nussknacker-default-model",
+ libraryDependencies ++= {
+ Seq(
+ "org.scalatest" %% "scalatest" % scalaTestV % Test
+ )
+ }
)
.dependsOn(defaultHelpers, extensionsApi % Provided)
@@ -1095,6 +1101,10 @@ lazy val testUtils = (project in utils("test-utils"))
"io.circe" %% "circe-parser" % circeV,
"org.testcontainers" % "testcontainers" % testContainersJavaV,
"com.lihaoyi" %% "ujson" % "3.1.2",
+ "com.github.erosb" % "everit-json-schema" % everitSchemaV exclude ("commons-logging", "commons-logging"),
+ "com.softwaremill.sttp.tapir" %% "tapir-core" % tapirV,
+ "com.softwaremill.sttp.tapir" %% "tapir-apispec-docs" % tapirV,
+ "com.softwaremill.sttp.apispec" %% "openapi-circe-yaml" % "0.7.4",
) ++ forScalaVersion(
scalaVersion.value,
Seq(),
@@ -1479,6 +1489,7 @@ lazy val componentsApi = (project in file("components-api"))
Seq(
"org.apache.commons" % "commons-text" % flinkCommonsTextV,
"org.typelevel" %% "cats-core" % catsV,
+ "com.beachape" %% "enumeratum" % enumeratumV,
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingV,
"com.typesafe" % "config" % configV,
"com.vdurmont" % "semver4j" % "3.1.0",
@@ -1911,7 +1922,7 @@ lazy val designer = (project in file("designer/server"))
"org.postgresql" % "postgresql" % postgresV,
"org.flywaydb" % "flyway-core" % flywayV,
"org.apache.xmlgraphics" % "fop" % "2.8" exclude ("commons-logging", "commons-logging"),
- "com.beachape" %% "enumeratum-circe" % "1.7.3",
+ "com.beachape" %% "enumeratum-circe" % enumeratumV,
"tf.tofu" %% "derevo-circe" % "0.13.0",
"com.softwaremill.sttp.apispec" %% "openapi-circe-yaml" % "0.7.4",
"com.softwaremill.sttp.tapir" %% "tapir-akka-http-server" % tapirV,
@@ -1930,6 +1941,8 @@ lazy val designer = (project in file("designer/server"))
"io.dropwizard.metrics5" % "metrics-core" % dropWizardV,
"io.dropwizard.metrics5" % "metrics-jmx" % dropWizardV,
"fr.davit" %% "akka-http-metrics-dropwizard-v5" % "1.7.1",
+ "org.scalacheck" %% "scalacheck" % scalaCheckV % Test,
+ "com.github.erosb" % "everit-json-schema" % everitSchemaV exclude ("commons-logging", "commons-logging"),
"org.apache.flink" % "flink-metrics-dropwizard" % flinkV % Test,
"com.github.tomakehurst" % "wiremock-jre8" % wireMockV % Test,
) ++ forScalaVersion(
@@ -1951,6 +1964,7 @@ lazy val designer = (project in file("designer/server"))
listenerApi,
testUtils % Test,
flinkTestUtils % Test,
+ componentsApi % "test->test",
// All DeploymentManager dependencies are added because they are needed to run NussknackerApp* with
// dev-application.conf. Currently, we doesn't have a separate classpath for DMs like we have for components.
// schemedKafkaComponentsUtils is added because loading the provided liteEmbeddedDeploymentManager causes
diff --git a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/component/ComponentProvider.scala b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/component/ComponentProvider.scala
index 84463d91de7..987c56918c5 100644
--- a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/component/ComponentProvider.scala
+++ b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/component/ComponentProvider.scala
@@ -1,8 +1,10 @@
package pl.touk.nussknacker.engine.api.component
+import cats.data.NonEmptySet
import com.typesafe.config.{Config, ConfigFactory}
import com.vdurmont.semver4j.Semver
import net.ceedubs.ficus.readers.{ArbitraryTypeReader, ValueReader}
+import pl.touk.nussknacker.engine.api.component.Component._
import pl.touk.nussknacker.engine.api.process.ProcessObjectDependencies
import pl.touk.nussknacker.engine.version.BuildInfo
@@ -18,23 +20,54 @@ trait Component extends Serializable {
// like in Service case, but in other cases, Component class is only a factory that returns some other class
// and we don't know if this class allow given processing mode or not so the developer have to specify this
// by his/her own
- def allowedProcessingModes: Option[Set[ProcessingMode]]
+ def allowedProcessingModes: AllowedProcessingModes
+}
+
+object Component {
+ sealed trait AllowedProcessingModes
+
+ object AllowedProcessingModes {
+ case object All extends AllowedProcessingModes
+ final case class SetOf(allowedProcessingModes: NonEmptySet[ProcessingMode]) extends AllowedProcessingModes
+
+ object SetOf {
+
+ def apply(processingMode: ProcessingMode, processingModes: ProcessingMode*): SetOf = {
+ new SetOf(NonEmptySet.of(processingMode, processingModes: _*))
+ }
+
+ }
+
+ }
+
+ implicit class ToProcessingModes(val allowedProcessingModes: AllowedProcessingModes) extends AnyVal {
+
+ def toProcessingModes: Set[ProcessingMode] = allowedProcessingModes match {
+ case AllowedProcessingModes.All => ProcessingMode.values.toSet
+ case AllowedProcessingModes.SetOf(allowedProcessingModesSet) => allowedProcessingModesSet.toSortedSet
+ }
+
+ }
+
}
trait UnboundedStreamComponent { self: Component =>
- override def allowedProcessingModes: Option[Set[ProcessingMode]] = Some(Set(ProcessingMode.UnboundedStream))
+ override def allowedProcessingModes: AllowedProcessingModes =
+ AllowedProcessingModes.SetOf(ProcessingMode.UnboundedStream)
}
trait BoundedStreamComponent { self: Component =>
- override def allowedProcessingModes: Option[Set[ProcessingMode]] = Some(Set(ProcessingMode.BoundedStream))
+ override def allowedProcessingModes: AllowedProcessingModes =
+ AllowedProcessingModes.SetOf(ProcessingMode.BoundedStream)
}
trait RequestResponseComponent { self: Component =>
- override def allowedProcessingModes: Option[Set[ProcessingMode]] = Some(Set(ProcessingMode.RequestResponse))
+ override def allowedProcessingModes: AllowedProcessingModes =
+ AllowedProcessingModes.SetOf(ProcessingMode.RequestResponse)
}
trait AllProcessingModesComponent { self: Component =>
- override def allowedProcessingModes: Option[Set[ProcessingMode]] = None
+ override def allowedProcessingModes: AllowedProcessingModes = AllowedProcessingModes.All
}
object ComponentProviderConfig {
diff --git a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/component/ProcessingMode.scala b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/component/ProcessingMode.scala
index f737f2c0417..a9cc99a5281 100644
--- a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/component/ProcessingMode.scala
+++ b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/component/ProcessingMode.scala
@@ -1,35 +1,43 @@
package pl.touk.nussknacker.engine.api.component
+import cats.Order
+import enumeratum._
import io.circe.{Decoder, Encoder}
-sealed trait ProcessingMode {
- def value: String
- override def toString: String = value
-}
+import scala.collection.immutable
-case object RequestResponseProcessingMode extends ProcessingMode {
- override def value: String = "Request-Response"
-}
+sealed trait ProcessingMode extends EnumEntry
-case class StreamProcessingMode(bounded: Boolean) extends ProcessingMode {
- override def value: String = s"${if (bounded) "Bounded" else "Unbounded"}-Stream"
-}
+object ProcessingMode extends Enum[ProcessingMode] {
+ case object RequestResponse extends ProcessingMode
+ case object BoundedStream extends ProcessingMode
+ case object UnboundedStream extends ProcessingMode
-object ProcessingMode {
+ override def values: immutable.IndexedSeq[ProcessingMode] = findValues
- val RequestResponse: ProcessingMode = RequestResponseProcessingMode
- val UnboundedStream: ProcessingMode = StreamProcessingMode(bounded = false)
- val BoundedStream: ProcessingMode = StreamProcessingMode(bounded = true)
+ private val RequestResponseJsonValue = "Request-Response"
+ private val BoundedStreamJsonValue = "Bounded-Stream"
+ private val UnboundedStreamJsonValue = "Unbounded-Stream"
- val all: Set[ProcessingMode] = Set(UnboundedStream, BoundedStream, RequestResponse)
+ implicit class ProcessingModeOps(processingMode: ProcessingMode) {
+
+ def toJsonString: String = processingMode match {
+ case ProcessingMode.RequestResponse => RequestResponseJsonValue
+ case ProcessingMode.BoundedStream => BoundedStreamJsonValue
+ case ProcessingMode.UnboundedStream => UnboundedStreamJsonValue
+ }
+
+ }
- implicit val encoder: Encoder[ProcessingMode] = Encoder.encodeString.contramap(_.value)
+ implicit val processingModeEncoder: Encoder[ProcessingMode] = Encoder.encodeString.contramap(_.toJsonString)
- implicit val decoder: Decoder[ProcessingMode] = Decoder.decodeString.map {
- case str if str == RequestResponse.value => RequestResponseProcessingMode
- case str if str == UnboundedStream.value => UnboundedStream
- case str if str == BoundedStream.value => BoundedStream
- case other => throw new IllegalArgumentException(s"Not known processing mode: $other")
+ implicit val processingModeDecoder: Decoder[ProcessingMode] = Decoder.decodeString.map {
+ case RequestResponseJsonValue => ProcessingMode.RequestResponse
+ case BoundedStreamJsonValue => ProcessingMode.BoundedStream
+ case UnboundedStreamJsonValue => ProcessingMode.UnboundedStream
+ case other => throw new IllegalArgumentException(s"Unknown processing mode: $other")
}
+ implicit val processingModeOrdering: Ordering[ProcessingMode] = Ordering.by(_.toJsonString)
+ implicit val processingModeOrder: Order[ProcessingMode] = Order.fromOrdering
}
diff --git a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/process/Source.scala b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/process/Source.scala
index d6b5b81f2b2..29bbd4ee54a 100644
--- a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/process/Source.scala
+++ b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/process/Source.scala
@@ -1,5 +1,7 @@
package pl.touk.nussknacker.engine.api.process
+import cats.data.NonEmptySet
+import pl.touk.nussknacker.engine.api.component.Component._
import pl.touk.nussknacker.engine.api.component.{Component, ProcessingMode}
import pl.touk.nussknacker.engine.api.context.ContextTransformation
import pl.touk.nussknacker.engine.api.definition.{Parameter, WithExplicitTypesToExtract}
@@ -61,23 +63,39 @@ object SourceFactory {
// source is called by for making SourceFactory serialization easier
def noParamUnboundedStreamFactory(source: => Source, inputType: TypingResult): SourceFactory =
- NoParamSourceFactory(_ => source, inputType, Some(Set(ProcessingMode.UnboundedStream)))
+ NoParamSourceFactory(
+ _ => source,
+ inputType,
+ AllowedProcessingModes.SetOf(ProcessingMode.UnboundedStream)
+ )
def noParamUnboundedStreamFactory[T: TypeTag](source: => Source)(implicit ev: T =:!= Nothing): SourceFactory =
- NoParamSourceFactory(_ => source, Typed.fromDetailedType[T], Some(Set(ProcessingMode.UnboundedStream)))
+ NoParamSourceFactory(
+ _ => source,
+ Typed.fromDetailedType[T],
+ AllowedProcessingModes.SetOf(ProcessingMode.UnboundedStream)
+ )
def noParamUnboundedStreamFactory[T: TypeTag](createSource: NodeId => Source)(
implicit ev: T =:!= Nothing
): SourceFactory =
- NoParamSourceFactory(createSource, Typed.fromDetailedType[T], Some(Set(ProcessingMode.UnboundedStream)))
+ NoParamSourceFactory(
+ createSource,
+ Typed.fromDetailedType[T],
+ AllowedProcessingModes.SetOf(ProcessingMode.UnboundedStream)
+ )
def noParamUnboundedStreamFromClassTag[T: ClassTag](source: => Source)(implicit ev: T =:!= Nothing): SourceFactory =
- NoParamSourceFactory(_ => source, Typed.apply[T], Some(Set(ProcessingMode.UnboundedStream)))
+ NoParamSourceFactory(
+ _ => source,
+ Typed.apply[T],
+ AllowedProcessingModes.SetOf(ProcessingMode.UnboundedStream)
+ )
case class NoParamSourceFactory(
createSource: NodeId => Source,
inputType: TypingResult,
- override val allowedProcessingModes: Option[Set[ProcessingMode]]
+ override val allowedProcessingModes: AllowedProcessingModes
) extends SourceFactory
with WithExplicitTypesToExtract {
diff --git a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/CanBeSubclassDeterminer.scala b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/CanBeSubclassDeterminer.scala
index 9a16a22e8c4..141e310c7f7 100644
--- a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/CanBeSubclassDeterminer.scala
+++ b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/CanBeSubclassDeterminer.scala
@@ -1,7 +1,7 @@
package pl.touk.nussknacker.engine.api.typed
import cats.data.Validated._
-import cats.data.{NonEmptyList, NonEmptySet, ValidatedNel}
+import cats.data.{NonEmptyList, ValidatedNel}
import cats.implicits.{catsSyntaxValidatedId, _}
import org.apache.commons.lang3.ClassUtils
import pl.touk.nussknacker.engine.api.typed.typing._
diff --git a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/supertype/CommonSupertypeFinder.scala b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/supertype/CommonSupertypeFinder.scala
index 22121a27425..8e5e5c93732 100644
--- a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/supertype/CommonSupertypeFinder.scala
+++ b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/supertype/CommonSupertypeFinder.scala
@@ -3,7 +3,6 @@ package pl.touk.nussknacker.engine.api.typed.supertype
import cats.data.NonEmptyList
import cats.implicits.toTraverseOps
import pl.touk.nussknacker.engine.api.typed.supertype.CommonSupertypeFinder.{
- Default,
SupertypeClassResolutionStrategy,
looseFinder
}
diff --git a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/typing.scala b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/typing.scala
index 7ad523e4fc2..08917cb0332 100644
--- a/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/typing.scala
+++ b/components-api/src/main/scala/pl/touk/nussknacker/engine/api/typed/typing.scala
@@ -23,7 +23,7 @@ object typing {
implicit val encoder: Encoder[TypingResult] = TypeEncoders.typingResultEncoder
}
- // TODO: Rename to Typed
+ // TODO: Rename to Typed, maybe NuType?
sealed trait TypingResult {
// TODO: We should split this method into two or three methods:
@@ -133,7 +133,8 @@ object typing {
// Thanks to that we avoid nasty types like String | null (String type is nullable as well)
// We can avoid this case by changing this folding logic - see the comment there
case object TypedNull extends TypingResult {
- override def withoutValue: TypedNull.type = TypedNull
+
+ override val withoutValue: TypingResult = this
// this value is intentionally `Some(null)` (and not `None`), as TypedNull represents null value
override val valueOpt: Some[Null] = Some(null)
diff --git a/defaultModel/src/main/scala/pl/touk/nussknacker/defaultmodel/DefaultModelMigrations.scala b/defaultModel/src/main/scala/pl/touk/nussknacker/defaultmodel/DefaultModelMigrations.scala
index 49c484eaaa3..185724580b1 100644
--- a/defaultModel/src/main/scala/pl/touk/nussknacker/defaultmodel/DefaultModelMigrations.scala
+++ b/defaultModel/src/main/scala/pl/touk/nussknacker/defaultmodel/DefaultModelMigrations.scala
@@ -1,10 +1,6 @@
package pl.touk.nussknacker.defaultmodel
-import pl.touk.nussknacker.defaultmodel.migrations.{
- GroupByMigration,
- RequestResponseSinkValidationModeMigration,
- SinkExpressionMigration
-}
+import pl.touk.nussknacker.defaultmodel.migrations._
import pl.touk.nussknacker.engine.migration.{ProcessMigration, ProcessMigrations}
class DefaultModelMigrations extends ProcessMigrations {
@@ -13,7 +9,8 @@ class DefaultModelMigrations extends ProcessMigrations {
.listOf(
GroupByMigration,
SinkExpressionMigration,
- RequestResponseSinkValidationModeMigration
+ RequestResponseSinkValidationModeMigration,
+ DecisionTableParameterNamesMigration
)
.processMigrations
diff --git a/defaultModel/src/main/scala/pl/touk/nussknacker/defaultmodel/migrations/DecisionTableParameterNamesMigration.scala b/defaultModel/src/main/scala/pl/touk/nussknacker/defaultmodel/migrations/DecisionTableParameterNamesMigration.scala
new file mode 100644
index 00000000000..4add44d17d4
--- /dev/null
+++ b/defaultModel/src/main/scala/pl/touk/nussknacker/defaultmodel/migrations/DecisionTableParameterNamesMigration.scala
@@ -0,0 +1,30 @@
+package pl.touk.nussknacker.defaultmodel.migrations
+
+import pl.touk.nussknacker.engine.api.MetaData
+import pl.touk.nussknacker.engine.api.parameter.ParameterName
+import pl.touk.nussknacker.engine.graph.evaluatedparam.Parameter
+import pl.touk.nussknacker.engine.graph.node
+import pl.touk.nussknacker.engine.graph.node.Enricher
+import pl.touk.nussknacker.engine.graph.service.ServiceRef
+import pl.touk.nussknacker.engine.migration.NodeMigration
+
+object DecisionTableParameterNamesMigration extends NodeMigration {
+
+ override val description: String = "Change Decision Table component parameter names"
+
+ override def migrateNode(metaData: MetaData): PartialFunction[node.NodeData, node.NodeData] = {
+ case enricher @ Enricher(_, service @ ServiceRef(_, params), _, _) =>
+ enricher.copy(service = service.copy(parameters = renameParams(params)))
+ }
+
+ private def renameParams(params: List[Parameter]) = {
+ params.map { param =>
+ param.name.value match {
+ case "Basic Decision Table" => param.copy(name = ParameterName("Decision Table"))
+ case "Expression" => param.copy(name = ParameterName("Filtering expression"))
+ case _ => param
+ }
+ }
+ }
+
+}
diff --git a/defaultModel/src/test/scala/pl/touk/nussknacker/defaultModel/migrations/DecisionTableParameterNamesMigrationSpec.scala b/defaultModel/src/test/scala/pl/touk/nussknacker/defaultModel/migrations/DecisionTableParameterNamesMigrationSpec.scala
new file mode 100644
index 00000000000..81e16674b39
--- /dev/null
+++ b/defaultModel/src/test/scala/pl/touk/nussknacker/defaultModel/migrations/DecisionTableParameterNamesMigrationSpec.scala
@@ -0,0 +1,61 @@
+package pl.touk.nussknacker.defaultModel.migrations
+
+import org.scalatest.freespec.AnyFreeSpecLike
+import org.scalatest.matchers.should.Matchers
+import pl.touk.nussknacker.defaultmodel.migrations.DecisionTableParameterNamesMigration
+import pl.touk.nussknacker.engine.api.{MetaData, StreamMetaData}
+import pl.touk.nussknacker.engine.api.parameter.ParameterName
+import pl.touk.nussknacker.engine.graph.node.Enricher
+import pl.touk.nussknacker.engine.graph.service.ServiceRef
+import pl.touk.nussknacker.engine.graph.evaluatedparam.Parameter
+import pl.touk.nussknacker.engine.graph.expression.Expression
+import pl.touk.nussknacker.engine.spel.Implicits.asSpelExpression
+
+class DecisionTableParameterNamesMigrationSpec extends AnyFreeSpecLike with Matchers {
+
+ "DecisionTableParameterNamesMigration should be applied" in {
+ val metaData = MetaData("test", StreamMetaData(Some(1)))
+ val beforeMigration = Enricher(
+ id = "decision-table",
+ service = ServiceRef(
+ id = "decision-table-service",
+ parameters = List(
+ Parameter(ParameterName("Basic Decision Table"), exampleDecisionTableJson),
+ Parameter(ParameterName("Expression"), "#ROW['age'] > #input.minAge && #ROW['DoB'] != null"),
+ )
+ ),
+ output = "Output",
+ )
+ val expectedAfterMigration = Enricher(
+ id = "decision-table",
+ service = ServiceRef(
+ id = "decision-table-service",
+ parameters = List(
+ Parameter(ParameterName("Decision Table"), exampleDecisionTableJson),
+ Parameter(ParameterName("Filtering expression"), "#ROW['age'] > #input.minAge && #ROW['DoB'] != null"),
+ )
+ ),
+ output = "Output",
+ )
+
+ val migrated = DecisionTableParameterNamesMigration.migrateNode(metaData)(beforeMigration)
+
+ migrated shouldBe expectedAfterMigration
+ }
+
+ private lazy val exampleDecisionTableJson = Expression.tabularDataDefinition {
+ s"""{
+ | "columns": [
+ | { "name": "name", "type": "java.lang.String" },
+ | { "name": "age", "type": "java.lang.Integer" },
+ | { "name": "DoB", "type": "java.time.LocalDate" }
+ | ],
+ | "rows": [
+ | [ "John", "39", null ],
+ | [ "Lisa", "21", "2003-01-13" ],
+ | [ "Mark", "54", "1970-12-30" ]
+ | ]
+ |}""".stripMargin
+ }
+
+}
diff --git a/designer/client/cypress/e2e/fragment.cy.ts b/designer/client/cypress/e2e/fragment.cy.ts
index 8b92b8813ea..ca3fc3f9dc8 100644
--- a/designer/client/cypress/e2e/fragment.cy.ts
+++ b/designer/client/cypress/e2e/fragment.cy.ts
@@ -38,6 +38,7 @@ describe("Fragment", () => {
cy.get("[id$='option-1']").click({ force: true });
// Display Add list item errors when blank value
+ cy.get("[data-testid='settings:4']").contains("User defined list").click();
cy.get("[data-testid='settings:4']").find("[id='ace-editor']").type("{enter}");
cy.get("[data-testid='settings:4']").find("[data-testid='form-helper-text']").should("be.visible");
cy.get("[data-testid='settings:4']").contains("This field is mandatory and can not be empty");
@@ -78,6 +79,7 @@ describe("Fragment", () => {
toggleSettings(5);
cy.get("[data-testid='settings:5']").contains("Any value").click();
cy.get("[id$='option-0']").click({ force: true });
+ cy.get("[data-testid='settings:5']").contains("User defined list").click();
cy.get("[data-testid='settings:5']").find("[id='ace-editor']").type("#meta.processName");
cy.get("[data-testid='settings:5']").contains("Typing...").should("not.exist");
cy.get("[data-testid='settings:5']").find("[id='ace-editor']").type("{enter}");
@@ -119,6 +121,44 @@ describe("Fragment", () => {
cy.get("@window").find("[data-testid='settings:6']").matchImage();
+ // Provide String Fixed value inputMode
+ cy.get("@window").contains("+").click();
+ cy.get("[data-testid='fieldsRow:7']").find("[placeholder='Field name']").type("any_value_with_suggestions_preset");
+ toggleSettings(7);
+
+ // Select any value with suggestions Input mode
+ cy.get("[data-testid='settings:7']").contains("Any value").click();
+ cy.get("[id$='option-1']").click({ force: true });
+
+ // Activate preset mode
+ cy.get("[data-testid='settings:7']").contains("Preset").click();
+
+ // Initial value should be disabled when there is no preset selected
+ cy.get("[data-testid='settings:7']")
+ .find("label")
+ .contains(/initial value/i)
+ .siblings()
+ .find("input")
+ .should("be.disabled");
+
+ // Select available values from Preset
+ cy.get("[data-testid='settings:7']")
+ .find("label")
+ .contains(/preset selection/i)
+ .siblings()
+ .eq(0)
+ .click();
+ cy.get("[id$='option-1']").click({ force: true });
+
+ // Select Initial value
+ cy.get("[data-testid='settings:7']")
+ .find("label")
+ .contains(/initial value/i)
+ .siblings()
+ .eq(0)
+ .click();
+ cy.get("[id$='option-1']").click({ force: true });
+
cy.get("@window")
.contains(/^apply$/i)
.click();
@@ -143,7 +183,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("#nk-graph-fragment [model-id='input']").should("be.visible");
+ cy.get("#nk-graph-fragment [model-id='input']").scrollIntoView().should("be.visible");
cy.wait("@fragmentInputValidation");
cy.get("[data-testid=window]").matchImage();
@@ -153,6 +193,24 @@ describe("Fragment", () => {
cy.get('[title="name_string_fixed"]').find('[title="Hint text test"]').should("be.visible");
cy.get('[title="non_boolean_or_string"]').siblings().eq(0).contains("1");
+ // any value with suggestions preset verification
+ cy.get('[title="any_value_with_suggestions_preset"]').siblings().eq(0).as("anyValueWithSuggestionField");
+
+ cy.get("@anyValueWithSuggestionField").find("input").should("have.value", "Email Marketing 12.2019");
+ cy.get("@anyValueWithSuggestionField").clear().type("Campaign 2020");
+ cy.get("[id$='option-0']").click({ force: true });
+ cy.get("@anyValueWithSuggestionField").find("input").should("have.value", "Campaign 2020 News");
+ cy.get("@anyValueWithSuggestionField").find('[title="Switch to expression mode"]').click();
+ cy.get("@anyValueWithSuggestionField").contains('{"key":"9d6d4e3e-0ba6-43bb-8696-58432e8f6bd8","label":"Campaign ');
+ cy.get("@anyValueWithSuggestionField").find("#ace-editor").type("{selectall}t");
+ cy.get("@anyValueWithSuggestionField")
+ .find('[title="Expression must be valid JSON to switch to basic mode"]')
+ .should("be.disabled");
+ cy.get("@anyValueWithSuggestionField")
+ .find("#ace-editor")
+ .type("{selectall}{backspace}")
+ .type('{"key": "9d6d4e3e-0ba6-43bb-8696-58432e8f6bd8", "label": "Campaign 2020 News"}', { parseSpecialCharSequences: false });
+
cy.get("[data-testid=window]").find("input[value=testOutput]").type("{selectall}fragmentResult");
cy.contains(/^apply/i)
.should("be.enabled")
@@ -198,6 +256,13 @@ describe("Fragment", () => {
cy.contains(/^save\*$/i).click();
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('[title="any_value_with_suggestions_preset"]').siblings().eq(0).find("input").should("have.value", "Campaign 2020 News");
+ cy.contains(/^apply/i)
+ .should("be.enabled")
+ .click();
+
// Go back to the fragment
cy.go(-1);
@@ -205,7 +270,7 @@ describe("Fragment", () => {
cy.get("[model-id=input]").should("be.visible").trigger("dblclick");
cy.get("[data-testid=window]").should("be.visible").as("window");
cy.get("@window").contains("+").click();
- cy.get("[data-testid='fieldsRow:7']").find("[placeholder='Field name']").type("test5");
+ cy.get("[data-testid='fieldsRow:8']").find("[placeholder='Field name']").type("test5");
cy.get("@window")
.contains(/^apply$/i)
.click();
diff --git a/designer/client/src/components/graph/node-modal/editors/EditableEditor.tsx b/designer/client/src/components/graph/node-modal/editors/EditableEditor.tsx
index cdc9a0e41be..c05ec8e7e6f 100644
--- a/designer/client/src/components/graph/node-modal/editors/EditableEditor.tsx
+++ b/designer/client/src/components/graph/node-modal/editors/EditableEditor.tsx
@@ -8,7 +8,7 @@ import { ExpressionLang, ExpressionObj } from "./expression/types";
import { ParamType } from "./types";
import { FieldError, PossibleValue } from "./Validators";
import { cx } from "@emotion/css";
-import { FormControl } from "@mui/material";
+import { FormControl, FormLabel } from "@mui/material";
import ErrorBoundary from "../../../common/ErrorBoundary";
interface Props {
@@ -69,7 +69,7 @@ function EditableEditorRow({
return (
<>
- {fieldLabel && renderFieldLabel?.(fieldLabel)}
+ {fieldLabel ? renderFieldLabel?.(fieldLabel) : }
>
diff --git a/designer/client/src/components/graph/node-modal/editors/expression/DictParameterEditor/DictParameterEditor.tsx b/designer/client/src/components/graph/node-modal/editors/expression/DictParameterEditor/DictParameterEditor.tsx
index 1aef7b6ac08..b9ca3e6165f 100644
--- a/designer/client/src/components/graph/node-modal/editors/expression/DictParameterEditor/DictParameterEditor.tsx
+++ b/designer/client/src/components/graph/node-modal/editors/expression/DictParameterEditor/DictParameterEditor.tsx
@@ -4,7 +4,7 @@ import HttpService, { ProcessDefinitionDataDictOption } from "../../../../../../
import { getScenario } from "../../../../../../reducers/selectors/graph";
import { useSelector } from "react-redux";
import { debounce } from "@mui/material/utils";
-import { SimpleEditor } from "../Editor";
+import { ExtendedEditor } from "../Editor";
import { ExpressionObj } from "../types";
import { FieldError } from "../../Validators";
import { ParamType } from "../../types";
@@ -14,6 +14,7 @@ import i18next from "i18next";
import ValidationLabels from "../../../../../modals/ValidationLabels";
import { cx } from "@emotion/css";
import { isEmpty } from "lodash";
+import { tryParseOrNull } from "../../../../../../common/JsonUtils";
interface Props {
expressionObj: ExpressionObj;
@@ -24,7 +25,7 @@ interface Props {
readOnly: boolean;
}
-export const DictParameterEditor: SimpleEditor = ({
+export const DictParameterEditor: ExtendedEditor = ({
fieldErrors,
expressionObj,
param,
@@ -47,16 +48,18 @@ export const DictParameterEditor: SimpleEditor = ({
const [inputValue, setInputValue] = useState("");
const [isFetching, setIsFetching] = useState(false);
+ const dictId = param.editor.dictId || param.editor?.simpleEditor?.dictId;
+
const fetchProcessDefinitionDataDict = useCallback(
async (inputValue: string) => {
setIsFetching(true);
- const { data } = await HttpService.fetchProcessDefinitionDataDict(scenario.processingType, param.editor.dictId, inputValue);
+ const { data } = await HttpService.fetchProcessDefinitionDataDict(scenario.processingType, dictId, inputValue);
setIsFetching(false);
return data;
},
- [param.editor.dictId, scenario.processingType],
+ [dictId, scenario.processingType],
);
const debouncedUpdateOptions = useMemo(() => {
@@ -71,6 +74,7 @@ export const DictParameterEditor: SimpleEditor = ({
return (
(
= ({
options={options}
filterOptions={(x) => x}
onChange={(_, value) => {
- onValueChange(JSON.stringify(value) || "");
+ onValueChange(value ? JSON.stringify(value) : "");
setValue(value);
setOpen(false);
}}
@@ -122,3 +126,12 @@ export const DictParameterEditor: SimpleEditor = ({
);
};
+
+const isParseable = (expression: ExpressionObj): boolean => {
+ return tryParseOrNull(expression.expression);
+};
+
+DictParameterEditor.switchableToHint = () => i18next.t("editors.dictParameter.switchableToHint", "Switch to basic mode");
+DictParameterEditor.notSwitchableToHint = () =>
+ i18next.t("editors.dictParameter.notSwitchableToHint", "Expression must be valid JSON to switch to basic mode");
+DictParameterEditor.isSwitchableTo = (expressionObj: ExpressionObj) => isParseable(expressionObj) || isEmpty(expressionObj.expression);
diff --git a/designer/client/src/components/graph/node-modal/fragment-input-definition/FieldsSelect.tsx b/designer/client/src/components/graph/node-modal/fragment-input-definition/FieldsSelect.tsx
index aaeab394896..82ff4e58a4c 100644
--- a/designer/client/src/components/graph/node-modal/fragment-input-definition/FieldsSelect.tsx
+++ b/designer/client/src/components/graph/node-modal/fragment-input-definition/FieldsSelect.tsx
@@ -1,5 +1,5 @@
import React, { useCallback, useMemo } from "react";
-import { FixedValuesPresets, NodeValidationError, Parameter, VariableTypes } from "../../../../types";
+import { NodeValidationError, Parameter, VariableTypes } from "../../../../types";
import { DndItems } from "../../../common/dndItems/DndItems";
import { NodeRowFieldsProvider } from "../node-row-fields-provider";
import { Item, onChangeType, FragmentInputParameter } from "./item";
@@ -20,25 +20,11 @@ interface FieldsSelectProps {
readOnly?: boolean;
showValidation?: boolean;
variableTypes: VariableTypes;
- fixedValuesPresets: FixedValuesPresets;
errors: NodeValidationError[];
}
export function FieldsSelect(props: FieldsSelectProps): JSX.Element {
- const {
- fields,
- label,
- namespace,
- options,
- onChange,
- variableTypes,
- removeField,
- addField,
- readOnly,
- showValidation,
- fixedValuesPresets,
- errors,
- } = props;
+ const { fields, label, namespace, options, onChange, variableTypes, removeField, addField, readOnly, showValidation, errors } = props;
const ItemElement = useCallback(
({ index, item, errors }: { index: number; item: FragmentInputParameter; errors: NodeValidationError[] }) => {
@@ -52,12 +38,11 @@ export function FieldsSelect(props: FieldsSelectProps): JSX.Element {
readOnly={readOnly}
variableTypes={variableTypes}
showValidation={showValidation}
- fixedValuesPresets={fixedValuesPresets}
errors={errors}
/>
);
},
- [namespace, onChange, options, readOnly, variableTypes, showValidation, fixedValuesPresets],
+ [namespace, onChange, options, readOnly, variableTypes, showValidation],
);
const changeOrder = useCallback((value) => onChange(namespace, value), [namespace, onChange]);
diff --git a/designer/client/src/components/graph/node-modal/fragment-input-definition/FragmentInputDefinition.tsx b/designer/client/src/components/graph/node-modal/fragment-input-definition/FragmentInputDefinition.tsx
index abc8d7cfdce..35bf942f884 100644
--- a/designer/client/src/components/graph/node-modal/fragment-input-definition/FragmentInputDefinition.tsx
+++ b/designer/client/src/components/graph/node-modal/fragment-input-definition/FragmentInputDefinition.tsx
@@ -40,7 +40,6 @@ export default function FragmentInputDefinition(props: Props): JSX.Element {
const readOnly = !isEditMode;
const { orderedTypeOptions, defaultTypeOption } = useTypeOptions();
- const definitionData = useSelector(getProcessDefinitionData);
const addField = useCallback(() => {
addElement("parameters", getDefaultFields(defaultTypeOption.value));
@@ -61,7 +60,6 @@ export default function FragmentInputDefinition(props: Props): JSX.Element {
showValidation={showValidation}
readOnly={readOnly}
variableTypes={variableTypes}
- fixedValuesPresets={definitionData.fixedValuesPresets}
errors={passProps.errors}
/>
diff --git a/designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx b/designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx
index 72801b3522e..a8a44f0a66d 100644
--- a/designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx
+++ b/designer/client/src/components/graph/node-modal/fragment-input-definition/item/Item.tsx
@@ -3,7 +3,7 @@ import { isEqual } from "lodash";
import { TypeSelect } from "../TypeSelect";
import { getValidationErrorsForField } from "../../editors/Validators";
import { Option } from "../FieldsSelect";
-import { FixedValuesPresets, NodeValidationError, ReturnedType, VariableTypes } from "../../../../../types";
+import { NodeValidationError, ReturnedType, VariableTypes } from "../../../../../types";
import SettingsButton from "../buttons/SettingsButton";
import { FieldsRow } from "../FieldsRow";
import { Settings } from "../settings/Settings";
@@ -23,12 +23,11 @@ interface ItemProps {
variableTypes: VariableTypes;
onChange: (path: string, value: onChangeType) => void;
options: Option[];
- fixedValuesPresets: FixedValuesPresets;
errors: NodeValidationError[];
}
export function Item(props: ItemProps): JSX.Element {
- const { index, item, namespace, variableTypes, readOnly, showValidation, onChange, options, fixedValuesPresets, errors } = props;
+ const { index, item, namespace, variableTypes, readOnly, showValidation, onChange, options, errors } = props;
const { getIsOpen, toggleIsOpen } = useFieldsContext();
const isOpen = getIsOpen(item.uuid);
@@ -85,7 +84,6 @@ export function Item(props: ItemProps): JSX.Element {
item={item}
onChange={onChange}
variableTypes={variableTypes}
- fixedValuesPresets={fixedValuesPresets}
readOnly={readOnly}
errors={errors}
data-testid={`settings:${index}`}
diff --git a/designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts b/designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts
index 13a8b38be72..a656d1bb61a 100644
--- a/designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts
+++ b/designer/client/src/components/graph/node-modal/fragment-input-definition/item/types.ts
@@ -1,6 +1,6 @@
import { Expression, ReturnedType } from "../../../../../types";
-export type onChangeType = string | number | boolean | FixedValuesOption | FixedValuesOption[] | ValueCompileTimeValidation;
+export type onChangeType = string | number | boolean | FixedValuesOption | FixedValuesOption[] | ValueCompileTimeValidation | ValueEditor;
export interface ValueCompileTimeValidation {
validationExpression: Expression;
@@ -13,7 +13,7 @@ export interface FragmentValidation {
export enum FixedValuesType {
"ValueInputWithFixedValuesProvided" = "ValueInputWithFixedValuesProvided",
- "ValueInputWithFixedValuesPreset" = "ValueInputWithFixedValuesPreset",
+ "ValueInputWithDictEditor" = "ValueInputWithDictEditor",
}
export enum InputMode {
@@ -38,11 +38,11 @@ export interface GenericParameterVariant {
expression?: Expression;
}
-interface ValueEditor {
+export interface ValueEditor {
type: FixedValuesType;
fixedValuesList: FixedValuesOption[] | null;
allowOtherValue: boolean | null;
- fixedValuesPresetId: string | null;
+ dictId: string;
}
export interface DefaultParameterVariant extends GenericParameterVariant, FragmentValidation {
@@ -52,12 +52,10 @@ export interface DefaultParameterVariant extends GenericParameterVariant, Fragme
export interface FixedListParameterVariant extends GenericParameterVariant, FragmentValidation {
valueEditor: ValueEditor;
- fixedValuesListPresetId: string;
presetSelection?: string;
}
export interface AnyValueWithSuggestionsParameterVariant extends GenericParameterVariant, FragmentValidation {
valueEditor: ValueEditor;
- fixedValuesListPresetId: string;
presetSelection?: string;
}
export interface AnyValueParameterVariant extends GenericParameterVariant, FragmentValidation {
diff --git a/designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts b/designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts
index e74aa2080e9..ecbfe41d75c 100644
--- a/designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts
+++ b/designer/client/src/components/graph/node-modal/fragment-input-definition/item/utils.ts
@@ -9,10 +9,7 @@ export const getDefaultFields = (refClazzName: string): FragmentInputParameter =
required: false,
hintText: "",
initialValue: null,
- // fixedValuesType: FixedValuesType.UserDefinedList,
valueEditor: null,
- // fixedValuesListPresetId: "",
- // presetSelection: "",
valueCompileTimeValidation: null,
typ: { refClazzName } as ReturnedType,
};
diff --git a/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/Settings.tsx b/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/Settings.tsx
index 954c989a6ed..d94d88e5d9f 100644
--- a/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/Settings.tsx
+++ b/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/Settings.tsx
@@ -1,6 +1,6 @@
import React from "react";
import { onChangeType, FragmentInputParameter, isStringOrBooleanVariant } from "../item";
-import { FixedValuesPresets, NodeValidationError, VariableTypes } from "../../../../../types";
+import { NodeValidationError, VariableTypes } from "../../../../../types";
import { DefaultVariant, StringBooleanVariant } from "./variants";
interface Settings {
@@ -8,7 +8,6 @@ interface Settings {
path: string;
variableTypes: VariableTypes;
onChange: (path: string, value: onChangeType) => void;
- fixedValuesPresets: FixedValuesPresets;
readOnly: boolean;
errors: NodeValidationError[];
}
diff --git a/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/variants/StringBooleanVariant.tsx b/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/variants/StringBooleanVariant.tsx
index c98e5bf909b..6093f8a928d 100644
--- a/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/variants/StringBooleanVariant.tsx
+++ b/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/variants/StringBooleanVariant.tsx
@@ -10,7 +10,7 @@ import {
onChangeType,
StringOrBooleanParameterVariant,
} from "../../item";
-import { FixedValuesPresets, NodeValidationError, VariableTypes } from "../../../../../../types";
+import { NodeValidationError, VariableTypes } from "../../../../../../types";
import { useTranslation } from "react-i18next";
import { AnyValueVariant, AnyValueWithSuggestionVariant, FixedListVariant } from "./StringBooleanVariants";
@@ -19,12 +19,11 @@ interface Props {
onChange: (path: string, value: onChangeType) => void;
path: string;
variableTypes: VariableTypes;
- fixedValuesPresets: FixedValuesPresets;
readOnly: boolean;
errors: NodeValidationError[];
}
-export const StringBooleanVariant = ({ item, path, variableTypes, onChange, fixedValuesPresets, readOnly, errors, ...props }: Props) => {
+export const StringBooleanVariant = ({ item, path, variableTypes, onChange, readOnly, errors, ...props }: Props) => {
const inputModeOptions = [
{ label: "Fixed list", value: InputMode.FixedList },
{ label: "Any value with suggestions", value: InputMode.AnyValueWithSuggestions },
@@ -54,7 +53,6 @@ export const StringBooleanVariant = ({ item, path, variableTypes, onChange, fixe
item={item}
inputModeOptions={inputModeOptions}
readOnly={readOnly}
- fixedValuesPresets={fixedValuesPresets}
errors={errors}
/>
{isAnyValueParameter(item) && (
@@ -72,7 +70,6 @@ export const StringBooleanVariant = ({ item, path, variableTypes, onChange, fixe
item={item}
onChange={onChange}
path={path}
- fixedValuesPresets={fixedValuesPresets}
readOnly={readOnly}
variableTypes={variableTypes}
errors={errors}
@@ -84,7 +81,6 @@ export const StringBooleanVariant = ({ item, path, variableTypes, onChange, fixe
onChange={onChange}
path={path}
variableTypes={variableTypes}
- fixedValuesPresets={fixedValuesPresets}
readOnly={readOnly}
errors={errors}
/>
diff --git a/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/variants/StringBooleanVariants/AnyValueWithSuggestionVariant.tsx b/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/variants/StringBooleanVariants/AnyValueWithSuggestionVariant.tsx
index 8a9ef0a51e4..3b6a136d6d4 100644
--- a/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/variants/StringBooleanVariants/AnyValueWithSuggestionVariant.tsx
+++ b/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/variants/StringBooleanVariants/AnyValueWithSuggestionVariant.tsx
@@ -2,44 +2,41 @@ import React from "react";
import InitialValue from "../fields/InitialValue";
import { SettingLabelStyled } from "../fields/StyledSettingsComponnets";
import { TextAreaNode } from "../../../../../../FormElements";
-import { AnyValueWithSuggestionsParameterVariant, FixedValuesType, onChangeType } from "../../../item";
+import { AnyValueWithSuggestionsParameterVariant, onChangeType } from "../../../item";
import { useTranslation } from "react-i18next";
import { FixedValuesSetting } from "../fields/FixedValuesSetting";
-import { FixedValuesPresets, NodeValidationError, VariableTypes } from "../../../../../../../types";
+import { NodeValidationError, VariableTypes } from "../../../../../../../types";
import { ValidationsFields } from "../fields/validation";
import { getValidationErrorsForField } from "../../../../editors/Validators";
import { FormControl } from "@mui/material";
+import { FixedValuesGroup } from "../fields/FixedValuesGroup";
interface Props {
item: AnyValueWithSuggestionsParameterVariant;
onChange: (path: string, value: onChangeType) => void;
path: string;
variableTypes: VariableTypes;
- fixedValuesPresets: FixedValuesPresets;
readOnly: boolean;
errors: NodeValidationError[];
}
-export const AnyValueWithSuggestionVariant = ({ item, path, onChange, variableTypes, fixedValuesPresets, readOnly, errors }: Props) => {
+export const AnyValueWithSuggestionVariant = ({ item, path, onChange, variableTypes, readOnly, errors }: Props) => {
const { t } = useTranslation();
- const presetListItemOptions = fixedValuesPresets?.[item.fixedValuesListPresetId] ?? [];
-
const fixedValuesList = item.valueEditor.fixedValuesList ?? [];
const fixedValuesType = item.valueEditor.type;
return (
<>
- {/**/}
+
diff --git a/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/variants/StringBooleanVariants/FixedListVariant.tsx b/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/variants/StringBooleanVariants/FixedListVariant.tsx
index edf12dea824..226fffbf62e 100644
--- a/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/variants/StringBooleanVariants/FixedListVariant.tsx
+++ b/designer/client/src/components/graph/node-modal/fragment-input-definition/settings/variants/StringBooleanVariants/FixedListVariant.tsx
@@ -1,44 +1,41 @@
import React from "react";
import { useTranslation } from "react-i18next";
-import { FixedListParameterVariant, FixedValuesType, onChangeType } from "../../../item";
+import { FixedListParameterVariant, onChangeType } from "../../../item";
import InitialValue from "../fields/InitialValue";
import { FixedValuesSetting } from "../fields/FixedValuesSetting";
import { SettingLabelStyled } from "../fields/StyledSettingsComponnets";
import { TextAreaNode } from "../../../../../../FormElements";
-import { FixedValuesPresets, NodeValidationError, VariableTypes } from "../../../../../../../types";
+import { NodeValidationError, VariableTypes } from "../../../../../../../types";
import { getValidationErrorsForField } from "../../../../editors/Validators";
import { FormControl } from "@mui/material";
+import { FixedValuesGroup } from "../fields/FixedValuesGroup";
interface Props {
item: FixedListParameterVariant;
onChange: (path: string, value: onChangeType) => void;
path: string;
- fixedValuesPresets: FixedValuesPresets;
readOnly: boolean;
variableTypes: VariableTypes;
errors: NodeValidationError[];
}
-export const FixedListVariant = ({ item, path, onChange, fixedValuesPresets, readOnly, variableTypes, errors }: Props) => {
+export const FixedListVariant = ({ item, path, onChange, readOnly, variableTypes, errors }: Props) => {
const { t } = useTranslation();
- const presetListItemOptions = fixedValuesPresets?.[item.fixedValuesListPresetId] ?? [];
-
const fixedValuesList = item.valueEditor.fixedValuesList ?? [];
const fixedValuesType = item.valueEditor.type;
return (
<>
- {/**/}
+
{
+ const [processDefinitionDicts, setProcessDefinitionDicts] = useState