Compare commits
3 Commits
8deabbcb99
...
49be579bd3
Author | SHA1 | Date | |
---|---|---|---|
49be579bd3 | |||
4fd5c634bb | |||
2e2524450d |
42
CHANGELOG.md
42
CHANGELOG.md
@ -1,12 +1,31 @@
|
||||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
## Unreleased
|
||||
|
||||
### 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
|
||||
- MeshLine for thick lines
|
||||
- Custom client-side events and thier processing in VisionServer
|
||||
|
||||
### Changed
|
||||
|
||||
- Color accessor property is now `colorProperty`. Color uses non-nullable `invoke` instead of `set`.
|
||||
- API update for server and pages
|
||||
- Edges moved to solids module for easier construction
|
||||
@ -17,17 +36,14 @@
|
||||
- Naming of Canvas3D options.
|
||||
- Lights are added to the scene instead of 3D options.
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
|
||||
- Jupyter integration for IDEA and Jupyter lab.
|
||||
|
||||
### Security
|
||||
## 0.2.0
|
||||
|
||||
## [0.2.0]
|
||||
### Added
|
||||
|
||||
- Server module
|
||||
- Change collector
|
||||
- Customizable accessors for colors
|
||||
@ -38,8 +54,8 @@
|
||||
- Markdown module
|
||||
- Tables module
|
||||
|
||||
|
||||
### Changed
|
||||
|
||||
- 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.
|
||||
- JavaFX support moved to a separate module
|
||||
@ -54,16 +70,10 @@
|
||||
- Property listeners are not triggered if there are no changes.
|
||||
- Feedback websocket connection in the client.
|
||||
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
|
||||
- Primary modules dependencies on UI
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
- Version conflicts
|
||||
|
||||
|
||||
### Security
|
||||
|
||||
|
@ -11,7 +11,7 @@ val dataforgeVersion by extra("0.7.1")
|
||||
|
||||
allprojects {
|
||||
group = "space.kscience"
|
||||
version = "0.3.0"
|
||||
version = "0.3.1"
|
||||
}
|
||||
|
||||
subprojects {
|
||||
|
@ -4,6 +4,7 @@ import ringui.SmartTabs
|
||||
import ringui.Tab
|
||||
import space.kscience.dataforge.context.Context
|
||||
import space.kscience.dataforge.context.request
|
||||
import space.kscience.plotly.Plotly.plot
|
||||
import space.kscience.plotly.models.Trace
|
||||
import space.kscience.plotly.scatter
|
||||
import space.kscience.visionforge.Application
|
||||
@ -97,7 +98,7 @@ private class JsPlaygroundApp : Application {
|
||||
Tab("plotly") {
|
||||
Plotly {
|
||||
attrs {
|
||||
plot = space.kscience.plotly.Plotly.plot {
|
||||
plot = plot {
|
||||
scatter {
|
||||
x(1, 2, 3)
|
||||
y(5, 8, 7)
|
||||
|
@ -11,6 +11,7 @@ import space.kscience.visionforge.markup.VisionOfMarkup
|
||||
import space.kscience.visionforge.react.flexRow
|
||||
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
||||
import space.kscience.visionforge.ring.solid
|
||||
import space.kscience.visionforge.setAsRoot
|
||||
import space.kscience.visionforge.solid.*
|
||||
import styled.css
|
||||
import styled.styledDiv
|
||||
@ -27,7 +28,9 @@ val GravityDemo = fc<DemoProps> { props ->
|
||||
val energyTrace = Trace {
|
||||
name = "energy"
|
||||
}
|
||||
val markup = VisionOfMarkup()
|
||||
val markup = VisionOfMarkup().apply {
|
||||
setAsRoot(props.solids.visionManager)
|
||||
}
|
||||
|
||||
styledDiv {
|
||||
css {
|
||||
|
@ -44,7 +44,7 @@ val Markup = fc<MarkupProps>("Markup") { props ->
|
||||
css {
|
||||
width = 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)
|
||||
backgroundColor = Color.white
|
||||
flex = Flex(1.0)
|
||||
|
@ -10,7 +10,7 @@ import space.kscience.dataforge.context.request
|
||||
import space.kscience.visionforge.VisionManager
|
||||
import space.kscience.visionforge.html.VisionOfHtmlForm
|
||||
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.server.close
|
||||
import space.kscience.visionforge.server.openInBrowser
|
||||
@ -36,7 +36,7 @@ fun main() {
|
||||
visionManager,
|
||||
VisionPage.scriptHeader("js/visionforge-playground.js"),
|
||||
) {
|
||||
bindForm(form) {
|
||||
visionOfForm(form) {
|
||||
label {
|
||||
htmlFor = "fname"
|
||||
+"First name:"
|
||||
@ -67,8 +67,8 @@ fun main() {
|
||||
value = "Submit"
|
||||
}
|
||||
}
|
||||
println(form.values)
|
||||
vision(form)
|
||||
println(form.values)
|
||||
}
|
||||
|
||||
}.start(false)
|
||||
|
@ -9,7 +9,9 @@ kscience {
|
||||
// useSerialization {
|
||||
// json()
|
||||
// }
|
||||
jvm()
|
||||
jvm{
|
||||
withJava()
|
||||
}
|
||||
jvmMain{
|
||||
implementation("io.ktor:ktor-server-cio")
|
||||
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 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/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 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/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 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;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;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;Ljava/util/Map;Lspace/kscience/visionforge/html/HtmlVisionFragment;ILjava/lang/Object;)V
|
||||
}
|
||||
|
||||
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 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 static final field Companion Lspace/kscience/visionforge/html/VisionOfCheckbox$Companion;
|
||||
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 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 fun <init> (Ljava/lang/String;)V
|
||||
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 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 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 {
|
||||
|
@ -39,7 +39,8 @@ public interface ControlVision : Vision {
|
||||
@Serializable
|
||||
@SerialName("control.click")
|
||||
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()
|
||||
|
||||
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.VisionManager
|
||||
|
||||
public fun interface HtmlVisionFragment{
|
||||
public fun interface HtmlVisionFragment {
|
||||
public fun VisionTagConsumer<*>.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
|
||||
* @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 fetchDataUrl fetch data after first render from given url
|
||||
* @param updatesUrl receive push updates from the server at given url
|
||||
* @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(
|
||||
visionManager: VisionManager,
|
||||
@ -28,39 +32,31 @@ public fun TagConsumer<*>.visionFragment(
|
||||
fetchDataUrl: String? = null,
|
||||
updatesUrl: String? = null,
|
||||
idPrefix: String? = null,
|
||||
onVisionRendered: (Name, Vision) -> Unit = { _, _ -> },
|
||||
displayCache: MutableMap<Name, VisionDisplay> = mutableMapOf(),
|
||||
fragment: HtmlVisionFragment,
|
||||
) {
|
||||
|
||||
val collector: MutableMap<Name, Pair<VisionOutput, Vision>> = mutableMapOf()
|
||||
|
||||
val consumer = object : VisionTagConsumer<Any?>(this@visionFragment, visionManager, idPrefix) {
|
||||
|
||||
override fun <T> TagConsumer<T>.vision(name: Name?, buildOutput: VisionOutput.() -> Vision): T {
|
||||
//Avoid re-creating cached visions
|
||||
val actualName = name ?: NameToken(
|
||||
DEFAULT_VISION_NAME,
|
||||
buildOutput.hashCode().toUInt().toString()
|
||||
buildOutput.hashCode().toString(16)
|
||||
).asName()
|
||||
|
||||
val (output, vision) = collector.getOrPut(actualName) {
|
||||
val display = displayCache.getOrPut(actualName) {
|
||||
val output = VisionOutput(context, actualName)
|
||||
val vision = output.buildOutput()
|
||||
onVisionRendered(actualName, vision)
|
||||
output to vision
|
||||
VisionDisplay(output.visionManager, vision, output.meta)
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
val (_, actualVision) = collector.getOrPut(name) {
|
||||
val output = VisionOutput(context, name)
|
||||
onVisionRendered(name, vision)
|
||||
output to vision
|
||||
}
|
||||
|
||||
displayCache[name] = VisionDisplay(manager, vision, outputMeta)
|
||||
|
||||
// Toggle update mode
|
||||
updatesUrl?.let {
|
||||
@ -76,7 +72,7 @@ public fun TagConsumer<*>.visionFragment(
|
||||
type = "text/json"
|
||||
attributes["class"] = OUTPUT_DATA_CLASS
|
||||
unsafe {
|
||||
+"\n${manager.encodeToString(actualVision)}\n"
|
||||
+"\n${manager.encodeToString(vision)}\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -91,8 +87,8 @@ public fun FlowContent.visionFragment(
|
||||
embedData: Boolean = true,
|
||||
fetchDataUrl: String? = null,
|
||||
updatesUrl: String? = null,
|
||||
onVisionRendered: (Name, Vision) -> Unit = { _, _ -> },
|
||||
idPrefix: String? = null,
|
||||
displayCache: MutableMap<Name, VisionDisplay> = mutableMapOf(),
|
||||
fragment: HtmlVisionFragment,
|
||||
): Unit = consumer.visionFragment(
|
||||
visionManager = visionManager,
|
||||
@ -100,6 +96,6 @@ public fun FlowContent.visionFragment(
|
||||
fetchDataUrl = fetchDataUrl,
|
||||
updatesUrl = updatesUrl,
|
||||
idPrefix = idPrefix,
|
||||
onVisionRendered = onVisionRendered,
|
||||
displayCache = displayCache,
|
||||
fragment = fragment
|
||||
)
|
@ -1,15 +1,15 @@
|
||||
package space.kscience.visionforge.html
|
||||
|
||||
import kotlinx.html.FORM
|
||||
import kotlinx.html.TagConsumer
|
||||
import kotlinx.html.form
|
||||
import kotlinx.html.id
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.html.*
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.node
|
||||
import space.kscience.dataforge.meta.string
|
||||
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
|
||||
@ -18,19 +18,31 @@ import space.kscience.visionforge.ClickControl
|
||||
@SerialName("html.form")
|
||||
public class VisionOfHtmlForm(
|
||||
public val formId: String,
|
||||
) : VisionOfHtmlControl() {
|
||||
) : VisionOfHtmlControl(), ClickControl {
|
||||
public var values: Meta? by properties.node()
|
||||
}
|
||||
|
||||
public fun <R> TagConsumer<R>.bindForm(
|
||||
visionOfForm: VisionOfHtmlForm,
|
||||
builder: FORM.() -> Unit,
|
||||
): R = form {
|
||||
this.id = visionOfForm.formId
|
||||
builder()
|
||||
|
||||
/**
|
||||
* Create a [VisionOfHtmlForm] and bind this form to the id
|
||||
*/
|
||||
@HtmlTagMarker
|
||||
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
|
||||
@SerialName("html.button")
|
||||
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.VisionOfHtmlForm
|
||||
|
||||
|
||||
internal fun FormData.toMeta(): Meta {
|
||||
/**
|
||||
* Convert form data to Meta
|
||||
*/
|
||||
public fun FormData.toMeta(): Meta {
|
||||
@Suppress("UNUSED_VARIABLE") val formData = this
|
||||
//val res = js("Object.fromEntries(formData);")
|
||||
val `object` = js("{}")
|
||||
@ -67,8 +69,10 @@ internal val formVisionRenderer: ElementVisionRenderer =
|
||||
form.onsubmit = { event ->
|
||||
event.preventDefault()
|
||||
val formData = FormData(form).toMeta()
|
||||
client.sendMetaEvent(name, formData)
|
||||
console.info("Sent: ${formData.toMap()}")
|
||||
client.context.launch {
|
||||
client.sendEvent(name, VisionClickEvent(name = name, payload = formData))
|
||||
}
|
||||
console.info("Sent form data: ${formData.toMap()}")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,9 @@ import space.kscience.dataforge.context.info
|
||||
import space.kscience.dataforge.context.logger
|
||||
import space.kscience.dataforge.meta.*
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.visionforge.Vision
|
||||
import space.kscience.visionforge.VisionManager
|
||||
import space.kscience.visionforge.html.HtmlVisionFragment
|
||||
import space.kscience.visionforge.html.VisionDisplay
|
||||
import space.kscience.visionforge.html.visionFragment
|
||||
import space.kscience.visionforge.server.VisionRoute
|
||||
import space.kscience.visionforge.server.serveVisionData
|
||||
@ -142,7 +142,7 @@ public class VisionForge(
|
||||
//server.serveVisionsFromFragment(consumer, "content-${counter++}", fragment)
|
||||
val cellRoute = "content-${counter++}"
|
||||
|
||||
val collector: MutableMap<Name, Vision> = mutableMapOf()
|
||||
val cache: MutableMap<Name, VisionDisplay> = mutableMapOf()
|
||||
|
||||
val url = engine.environment.connectors.first().let {
|
||||
url {
|
||||
@ -153,13 +153,13 @@ public class VisionForge(
|
||||
}
|
||||
}
|
||||
|
||||
engine.application.serveVisionData(VisionRoute(cellRoute, visionManager), collector)
|
||||
engine.application.serveVisionData(VisionRoute(cellRoute, visionManager), cache)
|
||||
|
||||
visionFragment(
|
||||
visionManager,
|
||||
embedData = true,
|
||||
updatesUrl = url,
|
||||
onVisionRendered = { name, vision -> collector[name] = vision },
|
||||
displayCache = cache,
|
||||
fragment = fragment
|
||||
)
|
||||
} else {
|
||||
|
@ -1,31 +1,50 @@
|
||||
package space.kscience.visionforge.server
|
||||
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.engine.*
|
||||
import io.ktor.server.html.*
|
||||
import io.ktor.server.http.content.*
|
||||
import io.ktor.server.plugins.*
|
||||
import io.ktor.server.plugins.cors.routing.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.URLProtocol
|
||||
import io.ktor.http.path
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.application.call
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.application.log
|
||||
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.util.*
|
||||
import io.ktor.server.websocket.*
|
||||
import io.ktor.util.pipeline.*
|
||||
import io.ktor.websocket.*
|
||||
import io.ktor.server.util.getOrFail
|
||||
import io.ktor.server.util.url
|
||||
import io.ktor.server.websocket.WebSockets
|
||||
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.collect
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
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 space.kscience.dataforge.context.Context
|
||||
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.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 kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
@ -72,7 +91,6 @@ public class VisionRoute(
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@ -137,8 +155,8 @@ public fun Application.serveVisionData(
|
||||
|
||||
public fun Application.serveVisionData(
|
||||
configuration: VisionRoute,
|
||||
data: Map<Name, Vision>,
|
||||
): Unit = serveVisionData(configuration) { data[it] }
|
||||
data: Map<Name, VisionDisplay>,
|
||||
): Unit = serveVisionData(configuration) { data[it]?.vision }
|
||||
|
||||
/**
|
||||
* 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)
|
||||
|
||||
val collector: MutableMap<Name, Vision> = mutableMapOf()
|
||||
val cache: MutableMap<Name, VisionDisplay> = mutableMapOf()
|
||||
|
||||
//serve data
|
||||
serveVisionData(configuration, collector)
|
||||
serveVisionData(configuration, cache)
|
||||
|
||||
//filled pages
|
||||
routing {
|
||||
@ -193,7 +211,7 @@ public fun Application.visionPage(
|
||||
path(route, "ws")
|
||||
}
|
||||
} else null,
|
||||
onVisionRendered = { name, vision -> collector[name] = vision },
|
||||
displayCache = cache,
|
||||
fragment = visionFragment
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user