Compare commits
3 Commits
8deabbcb99
...
49be579bd3
Author | SHA1 | Date | |
---|---|---|---|
49be579bd3 | |||
4fd5c634bb | |||
2e2524450d |
42
CHANGELOG.md
42
CHANGELOG.md
@ -1,12 +1,31 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## [Unreleased]
|
## Unreleased
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- **Breaking API** Move vision cache to upper level for renderers to avoid re-creating visions for page reload.
|
||||||
|
- **Breaking API** Forms refactor
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
## 0.3.0 - 2023-12-23
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
- Context receivers flag
|
- Context receivers flag
|
||||||
- MeshLine for thick lines
|
- MeshLine for thick lines
|
||||||
- Custom client-side events and thier processing in VisionServer
|
- Custom client-side events and thier processing in VisionServer
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Color accessor property is now `colorProperty`. Color uses non-nullable `invoke` instead of `set`.
|
- Color accessor property is now `colorProperty`. Color uses non-nullable `invoke` instead of `set`.
|
||||||
- API update for server and pages
|
- API update for server and pages
|
||||||
- Edges moved to solids module for easier construction
|
- Edges moved to solids module for easier construction
|
||||||
@ -17,17 +36,14 @@
|
|||||||
- Naming of Canvas3D options.
|
- Naming of Canvas3D options.
|
||||||
- Lights are added to the scene instead of 3D options.
|
- Lights are added to the scene instead of 3D options.
|
||||||
|
|
||||||
### Deprecated
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Jupyter integration for IDEA and Jupyter lab.
|
- Jupyter integration for IDEA and Jupyter lab.
|
||||||
|
|
||||||
### Security
|
## 0.2.0
|
||||||
|
|
||||||
## [0.2.0]
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Server module
|
- Server module
|
||||||
- Change collector
|
- Change collector
|
||||||
- Customizable accessors for colors
|
- Customizable accessors for colors
|
||||||
@ -38,8 +54,8 @@
|
|||||||
- Markdown module
|
- Markdown module
|
||||||
- Tables module
|
- Tables module
|
||||||
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Vision does not implement ItemProvider anymore. Property changes are done via `getProperty`/`setProperty` and `property` delegate.
|
- Vision does not implement ItemProvider anymore. Property changes are done via `getProperty`/`setProperty` and `property` delegate.
|
||||||
- Point3D and Point2D are made separate classes instead of expect/actual (to split up different engines.
|
- Point3D and Point2D are made separate classes instead of expect/actual (to split up different engines.
|
||||||
- JavaFX support moved to a separate module
|
- JavaFX support moved to a separate module
|
||||||
@ -54,16 +70,10 @@
|
|||||||
- Property listeners are not triggered if there are no changes.
|
- Property listeners are not triggered if there are no changes.
|
||||||
- Feedback websocket connection in the client.
|
- Feedback websocket connection in the client.
|
||||||
|
|
||||||
|
|
||||||
### Deprecated
|
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Primary modules dependencies on UI
|
- Primary modules dependencies on UI
|
||||||
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Version conflicts
|
- Version conflicts
|
||||||
|
|
||||||
|
|
||||||
### Security
|
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ val dataforgeVersion by extra("0.7.1")
|
|||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.3.0"
|
version = "0.3.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
|
@ -4,6 +4,7 @@ import ringui.SmartTabs
|
|||||||
import ringui.Tab
|
import ringui.Tab
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.dataforge.context.request
|
import space.kscience.dataforge.context.request
|
||||||
|
import space.kscience.plotly.Plotly.plot
|
||||||
import space.kscience.plotly.models.Trace
|
import space.kscience.plotly.models.Trace
|
||||||
import space.kscience.plotly.scatter
|
import space.kscience.plotly.scatter
|
||||||
import space.kscience.visionforge.Application
|
import space.kscience.visionforge.Application
|
||||||
@ -97,7 +98,7 @@ private class JsPlaygroundApp : Application {
|
|||||||
Tab("plotly") {
|
Tab("plotly") {
|
||||||
Plotly {
|
Plotly {
|
||||||
attrs {
|
attrs {
|
||||||
plot = space.kscience.plotly.Plotly.plot {
|
plot = plot {
|
||||||
scatter {
|
scatter {
|
||||||
x(1, 2, 3)
|
x(1, 2, 3)
|
||||||
y(5, 8, 7)
|
y(5, 8, 7)
|
||||||
|
@ -11,6 +11,7 @@ import space.kscience.visionforge.markup.VisionOfMarkup
|
|||||||
import space.kscience.visionforge.react.flexRow
|
import space.kscience.visionforge.react.flexRow
|
||||||
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
||||||
import space.kscience.visionforge.ring.solid
|
import space.kscience.visionforge.ring.solid
|
||||||
|
import space.kscience.visionforge.setAsRoot
|
||||||
import space.kscience.visionforge.solid.*
|
import space.kscience.visionforge.solid.*
|
||||||
import styled.css
|
import styled.css
|
||||||
import styled.styledDiv
|
import styled.styledDiv
|
||||||
@ -27,7 +28,9 @@ val GravityDemo = fc<DemoProps> { props ->
|
|||||||
val energyTrace = Trace {
|
val energyTrace = Trace {
|
||||||
name = "energy"
|
name = "energy"
|
||||||
}
|
}
|
||||||
val markup = VisionOfMarkup()
|
val markup = VisionOfMarkup().apply {
|
||||||
|
setAsRoot(props.solids.visionManager)
|
||||||
|
}
|
||||||
|
|
||||||
styledDiv {
|
styledDiv {
|
||||||
css {
|
css {
|
||||||
|
@ -44,7 +44,7 @@ val Markup = fc<MarkupProps>("Markup") { props ->
|
|||||||
css {
|
css {
|
||||||
width = 100.pct
|
width = 100.pct
|
||||||
height = 100.pct
|
height = 100.pct
|
||||||
border= Border(2.pt, BorderStyle.solid, Color.blue)
|
border = Border(2.pt, BorderStyle.solid, Color.blue)
|
||||||
padding = Padding(left = 8.pt)
|
padding = Padding(left = 8.pt)
|
||||||
backgroundColor = Color.white
|
backgroundColor = Color.white
|
||||||
flex = Flex(1.0)
|
flex = Flex(1.0)
|
||||||
|
@ -10,7 +10,7 @@ import space.kscience.dataforge.context.request
|
|||||||
import space.kscience.visionforge.VisionManager
|
import space.kscience.visionforge.VisionManager
|
||||||
import space.kscience.visionforge.html.VisionOfHtmlForm
|
import space.kscience.visionforge.html.VisionOfHtmlForm
|
||||||
import space.kscience.visionforge.html.VisionPage
|
import space.kscience.visionforge.html.VisionPage
|
||||||
import space.kscience.visionforge.html.bindForm
|
import space.kscience.visionforge.html.visionOfForm
|
||||||
import space.kscience.visionforge.onPropertyChange
|
import space.kscience.visionforge.onPropertyChange
|
||||||
import space.kscience.visionforge.server.close
|
import space.kscience.visionforge.server.close
|
||||||
import space.kscience.visionforge.server.openInBrowser
|
import space.kscience.visionforge.server.openInBrowser
|
||||||
@ -36,7 +36,7 @@ fun main() {
|
|||||||
visionManager,
|
visionManager,
|
||||||
VisionPage.scriptHeader("js/visionforge-playground.js"),
|
VisionPage.scriptHeader("js/visionforge-playground.js"),
|
||||||
) {
|
) {
|
||||||
bindForm(form) {
|
visionOfForm(form) {
|
||||||
label {
|
label {
|
||||||
htmlFor = "fname"
|
htmlFor = "fname"
|
||||||
+"First name:"
|
+"First name:"
|
||||||
@ -67,8 +67,8 @@ fun main() {
|
|||||||
value = "Submit"
|
value = "Submit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println(form.values)
|
|
||||||
vision(form)
|
vision(form)
|
||||||
|
println(form.values)
|
||||||
}
|
}
|
||||||
|
|
||||||
}.start(false)
|
}.start(false)
|
||||||
|
@ -9,7 +9,9 @@ kscience {
|
|||||||
// useSerialization {
|
// useSerialization {
|
||||||
// json()
|
// json()
|
||||||
// }
|
// }
|
||||||
jvm()
|
jvm{
|
||||||
|
withJava()
|
||||||
|
}
|
||||||
jvmMain{
|
jvmMain{
|
||||||
implementation("io.ktor:ktor-server-cio")
|
implementation("io.ktor:ktor-server-cio")
|
||||||
implementation(projects.visionforgeThreejs.visionforgeThreejsServer)
|
implementation(projects.visionforgeThreejs.visionforgeThreejsServer)
|
||||||
|
@ -750,10 +750,10 @@ public abstract interface class space/kscience/visionforge/html/HtmlVisionFragme
|
|||||||
|
|
||||||
public final class space/kscience/visionforge/html/HtmlVisionRendererKt {
|
public final class space/kscience/visionforge/html/HtmlVisionRendererKt {
|
||||||
public static final fun appendTo (Lspace/kscience/visionforge/html/HtmlVisionFragment;Lspace/kscience/visionforge/html/VisionTagConsumer;)V
|
public static final fun appendTo (Lspace/kscience/visionforge/html/HtmlVisionFragment;Lspace/kscience/visionforge/html/VisionTagConsumer;)V
|
||||||
public static final fun visionFragment (Lkotlinx/html/FlowContent;Lspace/kscience/visionforge/VisionManager;ZLjava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Ljava/lang/String;Lspace/kscience/visionforge/html/HtmlVisionFragment;)V
|
public static final fun visionFragment (Lkotlinx/html/FlowContent;Lspace/kscience/visionforge/VisionManager;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lspace/kscience/visionforge/html/HtmlVisionFragment;)V
|
||||||
public static final fun visionFragment (Lkotlinx/html/TagConsumer;Lspace/kscience/visionforge/VisionManager;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lspace/kscience/visionforge/html/HtmlVisionFragment;)V
|
public static final fun visionFragment (Lkotlinx/html/TagConsumer;Lspace/kscience/visionforge/VisionManager;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lspace/kscience/visionforge/html/HtmlVisionFragment;)V
|
||||||
public static synthetic fun visionFragment$default (Lkotlinx/html/FlowContent;Lspace/kscience/visionforge/VisionManager;ZLjava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Ljava/lang/String;Lspace/kscience/visionforge/html/HtmlVisionFragment;ILjava/lang/Object;)V
|
public static synthetic fun visionFragment$default (Lkotlinx/html/FlowContent;Lspace/kscience/visionforge/VisionManager;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lspace/kscience/visionforge/html/HtmlVisionFragment;ILjava/lang/Object;)V
|
||||||
public static synthetic fun visionFragment$default (Lkotlinx/html/TagConsumer;Lspace/kscience/visionforge/VisionManager;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lspace/kscience/visionforge/html/HtmlVisionFragment;ILjava/lang/Object;)V
|
public static synthetic fun visionFragment$default (Lkotlinx/html/TagConsumer;Lspace/kscience/visionforge/VisionManager;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;Lspace/kscience/visionforge/html/HtmlVisionFragment;ILjava/lang/Object;)V
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/visionforge/html/InputFeedbackMode : java/lang/Enum {
|
public final class space/kscience/visionforge/html/InputFeedbackMode : java/lang/Enum {
|
||||||
@ -782,6 +782,21 @@ public final class space/kscience/visionforge/html/ResourceLocation : java/lang/
|
|||||||
public abstract interface annotation class space/kscience/visionforge/html/VisionDSL : java/lang/annotation/Annotation {
|
public abstract interface annotation class space/kscience/visionforge/html/VisionDSL : java/lang/annotation/Annotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class space/kscience/visionforge/html/VisionDisplay {
|
||||||
|
public fun <init> (Lspace/kscience/visionforge/VisionManager;Lspace/kscience/visionforge/Vision;Lspace/kscience/dataforge/meta/Meta;)V
|
||||||
|
public final fun component1 ()Lspace/kscience/visionforge/VisionManager;
|
||||||
|
public final fun component2 ()Lspace/kscience/visionforge/Vision;
|
||||||
|
public final fun component3 ()Lspace/kscience/dataforge/meta/Meta;
|
||||||
|
public final fun copy (Lspace/kscience/visionforge/VisionManager;Lspace/kscience/visionforge/Vision;Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/visionforge/html/VisionDisplay;
|
||||||
|
public static synthetic fun copy$default (Lspace/kscience/visionforge/html/VisionDisplay;Lspace/kscience/visionforge/VisionManager;Lspace/kscience/visionforge/Vision;Lspace/kscience/dataforge/meta/Meta;ILjava/lang/Object;)Lspace/kscience/visionforge/html/VisionDisplay;
|
||||||
|
public fun equals (Ljava/lang/Object;)Z
|
||||||
|
public final fun getMeta ()Lspace/kscience/dataforge/meta/Meta;
|
||||||
|
public final fun getVision ()Lspace/kscience/visionforge/Vision;
|
||||||
|
public final fun getVisionManager ()Lspace/kscience/visionforge/VisionManager;
|
||||||
|
public fun hashCode ()I
|
||||||
|
public fun toString ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
public final class space/kscience/visionforge/html/VisionOfCheckbox : space/kscience/visionforge/html/VisionOfHtmlInput {
|
public final class space/kscience/visionforge/html/VisionOfCheckbox : space/kscience/visionforge/html/VisionOfHtmlInput {
|
||||||
public static final field Companion Lspace/kscience/visionforge/html/VisionOfCheckbox$Companion;
|
public static final field Companion Lspace/kscience/visionforge/html/VisionOfCheckbox$Companion;
|
||||||
public fun <init> ()V
|
public fun <init> ()V
|
||||||
@ -852,7 +867,7 @@ public final class space/kscience/visionforge/html/VisionOfHtmlControl$Companion
|
|||||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/visionforge/html/VisionOfHtmlForm : space/kscience/visionforge/html/VisionOfHtmlControl {
|
public final class space/kscience/visionforge/html/VisionOfHtmlForm : space/kscience/visionforge/html/VisionOfHtmlControl, space/kscience/visionforge/ClickControl {
|
||||||
public static final field Companion Lspace/kscience/visionforge/html/VisionOfHtmlForm$Companion;
|
public static final field Companion Lspace/kscience/visionforge/html/VisionOfHtmlForm$Companion;
|
||||||
public fun <init> (Ljava/lang/String;)V
|
public fun <init> (Ljava/lang/String;)V
|
||||||
public final fun getFormId ()Ljava/lang/String;
|
public final fun getFormId ()Ljava/lang/String;
|
||||||
@ -876,9 +891,11 @@ public final class space/kscience/visionforge/html/VisionOfHtmlForm$Companion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/visionforge/html/VisionOfHtmlFormKt {
|
public final class space/kscience/visionforge/html/VisionOfHtmlFormKt {
|
||||||
public static final fun bindForm (Lkotlinx/html/TagConsumer;Lspace/kscience/visionforge/html/VisionOfHtmlForm;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
|
|
||||||
public static final fun button (Lspace/kscience/visionforge/html/VisionOutput;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lspace/kscience/visionforge/html/VisionOfHtmlButton;
|
public static final fun button (Lspace/kscience/visionforge/html/VisionOutput;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lspace/kscience/visionforge/html/VisionOfHtmlButton;
|
||||||
public static synthetic fun button$default (Lspace/kscience/visionforge/html/VisionOutput;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/visionforge/html/VisionOfHtmlButton;
|
public static synthetic fun button$default (Lspace/kscience/visionforge/html/VisionOutput;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/visionforge/html/VisionOfHtmlButton;
|
||||||
|
public static final fun onSubmit (Lspace/kscience/visionforge/html/VisionOfHtmlForm;Lkotlinx/coroutines/CoroutineScope;Lkotlin/jvm/functions/Function1;)Lkotlinx/coroutines/Job;
|
||||||
|
public static final fun visionOfForm (Lkotlinx/html/TagConsumer;Lspace/kscience/visionforge/html/VisionOfHtmlForm;Ljava/lang/String;Lkotlinx/html/FormEncType;Lkotlinx/html/FormMethod;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
|
||||||
|
public static synthetic fun visionOfForm$default (Lkotlinx/html/TagConsumer;Lspace/kscience/visionforge/html/VisionOfHtmlForm;Ljava/lang/String;Lkotlinx/html/FormEncType;Lkotlinx/html/FormMethod;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class space/kscience/visionforge/html/VisionOfHtmlInput : space/kscience/visionforge/html/VisionOfHtmlControl {
|
public class space/kscience/visionforge/html/VisionOfHtmlInput : space/kscience/visionforge/html/VisionOfHtmlControl {
|
||||||
|
@ -39,7 +39,8 @@ public interface ControlVision : Vision {
|
|||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("control.click")
|
@SerialName("control.click")
|
||||||
public class VisionClickEvent(override val meta: Meta) : VisionControlEvent() {
|
public class VisionClickEvent(override val meta: Meta) : VisionControlEvent() {
|
||||||
public val payload: Meta? by meta.node()
|
public val payload: Meta get() = meta[::payload.name] ?: Meta.EMPTY
|
||||||
|
|
||||||
public val name: Name? get() = meta["name"].string?.parseAsName()
|
public val name: Name? get() = meta["name"].string?.parseAsName()
|
||||||
|
|
||||||
override fun toString(): String = meta.toString()
|
override fun toString(): String = meta.toString()
|
||||||
|
@ -8,19 +8,23 @@ import space.kscience.dataforge.names.asName
|
|||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.VisionManager
|
import space.kscience.visionforge.VisionManager
|
||||||
|
|
||||||
public fun interface HtmlVisionFragment{
|
public fun interface HtmlVisionFragment {
|
||||||
public fun VisionTagConsumer<*>.append()
|
public fun VisionTagConsumer<*>.append()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun HtmlVisionFragment.appendTo(consumer: VisionTagConsumer<*>): Unit = consumer.append()
|
public fun HtmlVisionFragment.appendTo(consumer: VisionTagConsumer<*>): Unit = consumer.append()
|
||||||
|
|
||||||
|
public data class VisionDisplay(val visionManager: VisionManager, val vision: Vision, val meta: Meta)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a fragment in the given consumer and return a map of extracted visions
|
* Render a fragment in the given consumer and return a map of extracted visions
|
||||||
* @param context a context used to create a vision fragment
|
* @param visionManager a context plugin used to create a vision fragment
|
||||||
* @param embedData embed Vision initial state in the HTML
|
* @param embedData embed Vision initial state in the HTML
|
||||||
* @param fetchDataUrl fetch data after first render from given url
|
* @param fetchDataUrl fetch data after first render from given url
|
||||||
* @param updatesUrl receive push updates from the server at given url
|
* @param updatesUrl receive push updates from the server at given url
|
||||||
* @param idPrefix a prefix to be used before vision ids
|
* @param idPrefix a prefix to be used before vision ids
|
||||||
|
* @param displayCache external cache for Vision displays. It is required to avoid re-creating visions on page update
|
||||||
|
* @param fragment the fragment to render
|
||||||
*/
|
*/
|
||||||
public fun TagConsumer<*>.visionFragment(
|
public fun TagConsumer<*>.visionFragment(
|
||||||
visionManager: VisionManager,
|
visionManager: VisionManager,
|
||||||
@ -28,39 +32,31 @@ public fun TagConsumer<*>.visionFragment(
|
|||||||
fetchDataUrl: String? = null,
|
fetchDataUrl: String? = null,
|
||||||
updatesUrl: String? = null,
|
updatesUrl: String? = null,
|
||||||
idPrefix: String? = null,
|
idPrefix: String? = null,
|
||||||
onVisionRendered: (Name, Vision) -> Unit = { _, _ -> },
|
displayCache: MutableMap<Name, VisionDisplay> = mutableMapOf(),
|
||||||
fragment: HtmlVisionFragment,
|
fragment: HtmlVisionFragment,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val collector: MutableMap<Name, Pair<VisionOutput, Vision>> = mutableMapOf()
|
|
||||||
|
|
||||||
val consumer = object : VisionTagConsumer<Any?>(this@visionFragment, visionManager, idPrefix) {
|
val consumer = object : VisionTagConsumer<Any?>(this@visionFragment, visionManager, idPrefix) {
|
||||||
|
|
||||||
override fun <T> TagConsumer<T>.vision(name: Name?, buildOutput: VisionOutput.() -> Vision): T {
|
override fun <T> TagConsumer<T>.vision(name: Name?, buildOutput: VisionOutput.() -> Vision): T {
|
||||||
//Avoid re-creating cached visions
|
//Avoid re-creating cached visions
|
||||||
val actualName = name ?: NameToken(
|
val actualName = name ?: NameToken(
|
||||||
DEFAULT_VISION_NAME,
|
DEFAULT_VISION_NAME,
|
||||||
buildOutput.hashCode().toUInt().toString()
|
buildOutput.hashCode().toString(16)
|
||||||
).asName()
|
).asName()
|
||||||
|
|
||||||
val (output, vision) = collector.getOrPut(actualName) {
|
val display = displayCache.getOrPut(actualName) {
|
||||||
val output = VisionOutput(context, actualName)
|
val output = VisionOutput(context, actualName)
|
||||||
val vision = output.buildOutput()
|
val vision = output.buildOutput()
|
||||||
onVisionRendered(actualName, vision)
|
VisionDisplay(output.visionManager, vision, output.meta)
|
||||||
output to vision
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return addVision(actualName, output.visionManager, vision, output.meta)
|
return addVision(actualName, display.visionManager, display.vision, display.meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun DIV.renderVision(manager: VisionManager, name: Name, vision: Vision, outputMeta: Meta) {
|
override fun DIV.renderVision(manager: VisionManager, name: Name, vision: Vision, outputMeta: Meta) {
|
||||||
|
|
||||||
val (_, actualVision) = collector.getOrPut(name) {
|
displayCache[name] = VisionDisplay(manager, vision, outputMeta)
|
||||||
val output = VisionOutput(context, name)
|
|
||||||
onVisionRendered(name, vision)
|
|
||||||
output to vision
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Toggle update mode
|
// Toggle update mode
|
||||||
updatesUrl?.let {
|
updatesUrl?.let {
|
||||||
@ -76,7 +72,7 @@ public fun TagConsumer<*>.visionFragment(
|
|||||||
type = "text/json"
|
type = "text/json"
|
||||||
attributes["class"] = OUTPUT_DATA_CLASS
|
attributes["class"] = OUTPUT_DATA_CLASS
|
||||||
unsafe {
|
unsafe {
|
||||||
+"\n${manager.encodeToString(actualVision)}\n"
|
+"\n${manager.encodeToString(vision)}\n"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,8 +87,8 @@ public fun FlowContent.visionFragment(
|
|||||||
embedData: Boolean = true,
|
embedData: Boolean = true,
|
||||||
fetchDataUrl: String? = null,
|
fetchDataUrl: String? = null,
|
||||||
updatesUrl: String? = null,
|
updatesUrl: String? = null,
|
||||||
onVisionRendered: (Name, Vision) -> Unit = { _, _ -> },
|
|
||||||
idPrefix: String? = null,
|
idPrefix: String? = null,
|
||||||
|
displayCache: MutableMap<Name, VisionDisplay> = mutableMapOf(),
|
||||||
fragment: HtmlVisionFragment,
|
fragment: HtmlVisionFragment,
|
||||||
): Unit = consumer.visionFragment(
|
): Unit = consumer.visionFragment(
|
||||||
visionManager = visionManager,
|
visionManager = visionManager,
|
||||||
@ -100,6 +96,6 @@ public fun FlowContent.visionFragment(
|
|||||||
fetchDataUrl = fetchDataUrl,
|
fetchDataUrl = fetchDataUrl,
|
||||||
updatesUrl = updatesUrl,
|
updatesUrl = updatesUrl,
|
||||||
idPrefix = idPrefix,
|
idPrefix = idPrefix,
|
||||||
onVisionRendered = onVisionRendered,
|
displayCache = displayCache,
|
||||||
fragment = fragment
|
fragment = fragment
|
||||||
)
|
)
|
@ -1,15 +1,15 @@
|
|||||||
package space.kscience.visionforge.html
|
package space.kscience.visionforge.html
|
||||||
|
|
||||||
import kotlinx.html.FORM
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.html.TagConsumer
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.html.form
|
import kotlinx.html.*
|
||||||
import kotlinx.html.id
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.node
|
import space.kscience.dataforge.meta.node
|
||||||
import space.kscience.dataforge.meta.string
|
import space.kscience.dataforge.meta.string
|
||||||
import space.kscience.visionforge.ClickControl
|
import space.kscience.visionforge.ClickControl
|
||||||
|
import space.kscience.visionforge.onClick
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param formId an id of the element in rendered DOM, this form is bound to
|
* @param formId an id of the element in rendered DOM, this form is bound to
|
||||||
@ -18,19 +18,31 @@ import space.kscience.visionforge.ClickControl
|
|||||||
@SerialName("html.form")
|
@SerialName("html.form")
|
||||||
public class VisionOfHtmlForm(
|
public class VisionOfHtmlForm(
|
||||||
public val formId: String,
|
public val formId: String,
|
||||||
) : VisionOfHtmlControl() {
|
) : VisionOfHtmlControl(), ClickControl {
|
||||||
public var values: Meta? by properties.node()
|
public var values: Meta? by properties.node()
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <R> TagConsumer<R>.bindForm(
|
|
||||||
visionOfForm: VisionOfHtmlForm,
|
/**
|
||||||
builder: FORM.() -> Unit,
|
* Create a [VisionOfHtmlForm] and bind this form to the id
|
||||||
): R = form {
|
*/
|
||||||
this.id = visionOfForm.formId
|
@HtmlTagMarker
|
||||||
builder()
|
public inline fun <T, C : TagConsumer<T>> C.visionOfForm(
|
||||||
|
vision: VisionOfHtmlForm,
|
||||||
|
action: String? = null,
|
||||||
|
encType: FormEncType? = null,
|
||||||
|
method: FormMethod? = null,
|
||||||
|
classes: String? = null,
|
||||||
|
crossinline block: FORM.() -> Unit = {},
|
||||||
|
) : T = form(action, encType, method, classes){
|
||||||
|
this.id = vision.formId
|
||||||
|
block()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public fun VisionOfHtmlForm.onSubmit(scope: CoroutineScope, block: (Meta?) -> Unit): Job = onClick(scope) { block(payload) }
|
||||||
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("html.button")
|
@SerialName("html.button")
|
||||||
public class VisionOfHtmlButton : VisionOfHtmlControl(), ClickControl {
|
public class VisionOfHtmlButton : VisionOfHtmlControl(), ClickControl {
|
||||||
|
@ -15,8 +15,10 @@ import space.kscience.dataforge.names.Name
|
|||||||
import space.kscience.visionforge.html.VisionOfHtmlButton
|
import space.kscience.visionforge.html.VisionOfHtmlButton
|
||||||
import space.kscience.visionforge.html.VisionOfHtmlForm
|
import space.kscience.visionforge.html.VisionOfHtmlForm
|
||||||
|
|
||||||
|
/**
|
||||||
internal fun FormData.toMeta(): Meta {
|
* Convert form data to Meta
|
||||||
|
*/
|
||||||
|
public fun FormData.toMeta(): Meta {
|
||||||
@Suppress("UNUSED_VARIABLE") val formData = this
|
@Suppress("UNUSED_VARIABLE") val formData = this
|
||||||
//val res = js("Object.fromEntries(formData);")
|
//val res = js("Object.fromEntries(formData);")
|
||||||
val `object` = js("{}")
|
val `object` = js("{}")
|
||||||
@ -67,8 +69,10 @@ internal val formVisionRenderer: ElementVisionRenderer =
|
|||||||
form.onsubmit = { event ->
|
form.onsubmit = { event ->
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
val formData = FormData(form).toMeta()
|
val formData = FormData(form).toMeta()
|
||||||
client.sendMetaEvent(name, formData)
|
client.context.launch {
|
||||||
console.info("Sent: ${formData.toMap()}")
|
client.sendEvent(name, VisionClickEvent(name = name, payload = formData))
|
||||||
|
}
|
||||||
|
console.info("Sent form data: ${formData.toMap()}")
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,9 @@ import space.kscience.dataforge.context.info
|
|||||||
import space.kscience.dataforge.context.logger
|
import space.kscience.dataforge.context.logger
|
||||||
import space.kscience.dataforge.meta.*
|
import space.kscience.dataforge.meta.*
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.visionforge.Vision
|
|
||||||
import space.kscience.visionforge.VisionManager
|
import space.kscience.visionforge.VisionManager
|
||||||
import space.kscience.visionforge.html.HtmlVisionFragment
|
import space.kscience.visionforge.html.HtmlVisionFragment
|
||||||
|
import space.kscience.visionforge.html.VisionDisplay
|
||||||
import space.kscience.visionforge.html.visionFragment
|
import space.kscience.visionforge.html.visionFragment
|
||||||
import space.kscience.visionforge.server.VisionRoute
|
import space.kscience.visionforge.server.VisionRoute
|
||||||
import space.kscience.visionforge.server.serveVisionData
|
import space.kscience.visionforge.server.serveVisionData
|
||||||
@ -142,7 +142,7 @@ public class VisionForge(
|
|||||||
//server.serveVisionsFromFragment(consumer, "content-${counter++}", fragment)
|
//server.serveVisionsFromFragment(consumer, "content-${counter++}", fragment)
|
||||||
val cellRoute = "content-${counter++}"
|
val cellRoute = "content-${counter++}"
|
||||||
|
|
||||||
val collector: MutableMap<Name, Vision> = mutableMapOf()
|
val cache: MutableMap<Name, VisionDisplay> = mutableMapOf()
|
||||||
|
|
||||||
val url = engine.environment.connectors.first().let {
|
val url = engine.environment.connectors.first().let {
|
||||||
url {
|
url {
|
||||||
@ -153,13 +153,13 @@ public class VisionForge(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
engine.application.serveVisionData(VisionRoute(cellRoute, visionManager), collector)
|
engine.application.serveVisionData(VisionRoute(cellRoute, visionManager), cache)
|
||||||
|
|
||||||
visionFragment(
|
visionFragment(
|
||||||
visionManager,
|
visionManager,
|
||||||
embedData = true,
|
embedData = true,
|
||||||
updatesUrl = url,
|
updatesUrl = url,
|
||||||
onVisionRendered = { name, vision -> collector[name] = vision },
|
displayCache = cache,
|
||||||
fragment = fragment
|
fragment = fragment
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,31 +1,50 @@
|
|||||||
package space.kscience.visionforge.server
|
package space.kscience.visionforge.server
|
||||||
|
|
||||||
import io.ktor.http.*
|
import io.ktor.http.ContentType
|
||||||
import io.ktor.server.application.*
|
import io.ktor.http.HttpStatusCode
|
||||||
import io.ktor.server.engine.*
|
import io.ktor.http.URLProtocol
|
||||||
import io.ktor.server.html.*
|
import io.ktor.http.path
|
||||||
import io.ktor.server.http.content.*
|
import io.ktor.server.application.Application
|
||||||
import io.ktor.server.plugins.*
|
import io.ktor.server.application.call
|
||||||
import io.ktor.server.plugins.cors.routing.*
|
import io.ktor.server.application.install
|
||||||
import io.ktor.server.request.*
|
import io.ktor.server.application.log
|
||||||
import io.ktor.server.response.*
|
import io.ktor.server.engine.EngineConnectorConfig
|
||||||
|
import io.ktor.server.html.respondHtml
|
||||||
|
import io.ktor.server.plugins.cors.routing.CORS
|
||||||
|
import io.ktor.server.request.header
|
||||||
|
import io.ktor.server.request.host
|
||||||
|
import io.ktor.server.request.port
|
||||||
|
import io.ktor.server.response.header
|
||||||
|
import io.ktor.server.response.respond
|
||||||
|
import io.ktor.server.response.respondText
|
||||||
import io.ktor.server.routing.*
|
import io.ktor.server.routing.*
|
||||||
import io.ktor.server.util.*
|
import io.ktor.server.util.getOrFail
|
||||||
import io.ktor.server.websocket.*
|
import io.ktor.server.util.url
|
||||||
import io.ktor.util.pipeline.*
|
import io.ktor.server.websocket.WebSockets
|
||||||
import io.ktor.websocket.*
|
import io.ktor.server.websocket.application
|
||||||
|
import io.ktor.server.websocket.webSocket
|
||||||
|
import io.ktor.websocket.Frame
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.html.*
|
import kotlinx.html.body
|
||||||
|
import kotlinx.html.head
|
||||||
|
import kotlinx.html.header
|
||||||
|
import kotlinx.html.meta
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.dataforge.context.ContextAware
|
import space.kscience.dataforge.context.ContextAware
|
||||||
import space.kscience.dataforge.meta.*
|
import space.kscience.dataforge.meta.Configurable
|
||||||
|
import space.kscience.dataforge.meta.ObservableMutableMeta
|
||||||
|
import space.kscience.dataforge.meta.enum
|
||||||
|
import space.kscience.dataforge.meta.long
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.visionforge.*
|
import space.kscience.visionforge.Vision
|
||||||
|
import space.kscience.visionforge.VisionEvent
|
||||||
|
import space.kscience.visionforge.VisionManager
|
||||||
|
import space.kscience.visionforge.flowChanges
|
||||||
import space.kscience.visionforge.html.*
|
import space.kscience.visionforge.html.*
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
|
|
||||||
@ -72,7 +91,6 @@ public class VisionRoute(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Serve visions in a given [route] without providing a page template.
|
* Serve visions in a given [route] without providing a page template.
|
||||||
* [visions] could be changed during the service.
|
|
||||||
*
|
*
|
||||||
* @return a [Flow] of backward events, including vision change events
|
* @return a [Flow] of backward events, including vision change events
|
||||||
*/
|
*/
|
||||||
@ -137,8 +155,8 @@ public fun Application.serveVisionData(
|
|||||||
|
|
||||||
public fun Application.serveVisionData(
|
public fun Application.serveVisionData(
|
||||||
configuration: VisionRoute,
|
configuration: VisionRoute,
|
||||||
data: Map<Name, Vision>,
|
data: Map<Name, VisionDisplay>,
|
||||||
): Unit = serveVisionData(configuration) { data[it] }
|
): Unit = serveVisionData(configuration) { data[it]?.vision }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serve a page, potentially containing any number of visions at a given [route] with given [header].
|
* Serve a page, potentially containing any number of visions at a given [route] with given [header].
|
||||||
@ -154,10 +172,10 @@ public fun Application.visionPage(
|
|||||||
) {
|
) {
|
||||||
require(WebSockets)
|
require(WebSockets)
|
||||||
|
|
||||||
val collector: MutableMap<Name, Vision> = mutableMapOf()
|
val cache: MutableMap<Name, VisionDisplay> = mutableMapOf()
|
||||||
|
|
||||||
//serve data
|
//serve data
|
||||||
serveVisionData(configuration, collector)
|
serveVisionData(configuration, cache)
|
||||||
|
|
||||||
//filled pages
|
//filled pages
|
||||||
routing {
|
routing {
|
||||||
@ -193,7 +211,7 @@ public fun Application.visionPage(
|
|||||||
path(route, "ws")
|
path(route, "ws")
|
||||||
}
|
}
|
||||||
} else null,
|
} else null,
|
||||||
onVisionRendered = { name, vision -> collector[name] = vision },
|
displayCache = cache,
|
||||||
fragment = visionFragment
|
fragment = visionFragment
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user