jwstegemann / fritz2 Goto Github PK
View Code? Open in Web Editor NEWEasily build reactive web-apps in Kotlin based on flows and coroutines.
Home Page: https://www.fritz2.dev
License: MIT License
Easily build reactive web-apps in Kotlin based on flows and coroutines.
Home Page: https://www.fritz2.dev
License: MIT License
and especially how to handle the http-responses and redirects involved.
Implement Store(s) that:
Concept a general way how multiple stores can interact with each other.
Currently fritz2 needs the id given by the idProvider as String
but most DB's uses Long
as datatype for their ids. That is why you must convert it in the backend. It would be better when fritz2 accept type for providing an id. If then a String
is needed it gets internally the toString()
function called.
there are no sub-methods on ModelIds to create SubModelIds for certain list-elements (according to sub-methods on Stores).
Change type from MapRouter back to Map<String, String> cause type casting from Any to specific type it not working correctly in js.
div {
comment("this is a comment")
text("this is text")
}
renders:
<div>
<!-- this is a comment -->
this is text
<div/>
With a second constructor in RootStore<T>
you can use the data from an other store as initialData
in your new store like:
val a = object: RootStore<String>("a") {}
val len: Flow<Int> = a.data.map { it.length }
val b = object: RootStore<Int>(len) {}
Is your feature request related to a problem? Please describe.
I would like to communicate with a backend that uses websockets, and flows seem to lend themselves nicely to that.
Describe the solution you'd like
val socket = remote("ws://server/ws").websocket() {
// transform frames here
} handledBy update
// In other places:
store.data.bind() // Render incoming data
socket.send(message) // Send a message
Describe alternatives you've considered
I am still unfamiliar with fritz2, but as an alternative I think that I could use window.fetch
and bind to the events.
We need an example sharing model- and validation-code between front and backend and shows how to packe and deploy the combination in
Providing a Store that offers handlers for CRUD functionalities. Maybe with remote-connection...
In Safari (mobile and desktop) the initial value of an observed attribute is not available on the Flow
created with attributeChanges
.
Right now, when an exception is thrown inside a handler or downstream it's coroutine is canceled and the handler will stop working forever.
We need a proper handling of exception on Store-Level which can be overridden on handler-level
The algorithm that compares two versions of a list und infers the resulting Patches from it needs attention.
At least something like a (configurable) look-ahead is needed, so that newly inserted elements in between or at front do not result in patches that replace element by element from that index on...
We should publish snapshot-artifacts of the upcoming release whenever a pr is merged. Maybe to bintray oss?
Would be conceivable to develop a parser, which inspect a html-site written with html, js and css to suggest codelines in fritz2?
If you use Store
as type in your functions, you don't have sub available....
calling html
to build a tree of elements, you can add more than one child to the root-html
in perfectly valid code.
Since it is later bound using a SingleMountPoint
only the last added child is visible in the DOM in the browser, because the others are simply overridden. This is not intuitive.
Describe the bug
Trying to add Fritz2 to an existing project. Adding the plugin causes the following exception:
FAILURE: Build failed with an exception.
* What went wrong:
org/gradle/kotlin/dsl/precompile/v1/PrecompiledProjectScript
> org.gradle.kotlin.dsl.precompile.v1.PrecompiledProjectScript
* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Exception is:
java.lang.NoClassDefFoundError: org/gradle/kotlin/dsl/precompile/v1/PrecompiledProjectScript
at dev.fritz2.Fritz2GradlePlugin.apply(Fritz2GradlePlugin.kt:12)
at dev.fritz2.Fritz2GradlePlugin.apply(Fritz2GradlePlugin.kt:8)
at org.gradle.api.internal.plugins.ImperativeOnlyPluginTarget.applyImperative(ImperativeOnlyPluginTarget.java:43)
at org.gradle.api.internal.plugins.RuleBasedPluginTarget.applyImperative(RuleBasedPluginTarget.java:51)
at org.gradle.api.internal.plugins.DefaultPluginManager.addPlugin(DefaultPluginManager.java:181)
at org.gradle.api.internal.plugins.DefaultPluginManager.access$300(DefaultPluginManager.java:51)
at org.gradle.api.internal.plugins.DefaultPluginManager$AddPluginBuildOperation.run(DefaultPluginManager.java:276)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
at org.gradle.api.internal.plugins.DefaultPluginManager$2.execute(DefaultPluginManager.java:159)
at org.gradle.api.internal.plugins.DefaultPluginManager$2.execute(DefaultPluginManager.java:156)
at org.gradle.configuration.internal.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:49)
at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:156)
at org.gradle.api.internal.plugins.DefaultPluginManager.apply(DefaultPluginManager.java:136)
at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator$3.run(DefaultPluginRequestApplicator.java:155)
at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugin(DefaultPluginRequestApplicator.java:231)
at org.gradle.plugin.use.internal.DefaultPluginRequestApplicator.applyPlugins(DefaultPluginRequestApplicator.java:151)
at org.gradle.configuration.DefaultScriptPluginFactory$ScriptPluginImpl.apply(DefaultScriptPluginFactory.java:206)
at org.gradle.configuration.BuildOperationScriptPlugin$1$1.run(BuildOperationScriptPlugin.java:69)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
at org.gradle.configuration.BuildOperationScriptPlugin$1.execute(BuildOperationScriptPlugin.java:66)
at org.gradle.configuration.BuildOperationScriptPlugin$1.execute(BuildOperationScriptPlugin.java:63)
at org.gradle.configuration.internal.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:49)
at org.gradle.configuration.BuildOperationScriptPlugin.apply(BuildOperationScriptPlugin.java:63)
at org.gradle.configuration.project.BuildScriptProcessor$1.run(BuildScriptProcessor.java:45)
at org.gradle.internal.Factories$1.create(Factories.java:26)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:201)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:187)
at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:42)
at org.gradle.configuration.project.BuildScriptProcessor.execute(BuildScriptProcessor.java:26)
at org.gradle.configuration.project.ConfigureActionsProjectEvaluator.evaluate(ConfigureActionsProjectEvaluator.java:35)
at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject$1.run(LifecycleProjectEvaluator.java:107)
at org.gradle.internal.Factories$1.create(Factories.java:26)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:189)
at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:40)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withProjectLock(DefaultProjectStateRegistry.java:227)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:221)
at org.gradle.api.internal.project.DefaultProjectStateRegistry$ProjectStateImpl.withMutableState(DefaultProjectStateRegistry.java:187)
at org.gradle.configuration.project.LifecycleProjectEvaluator$EvaluateProject.run(LifecycleProjectEvaluator.java:96)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:68)
at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:693)
at org.gradle.api.internal.project.DefaultProject.evaluate(DefaultProject.java:141)
at org.gradle.execution.TaskPathProjectEvaluator.configure(TaskPathProjectEvaluator.java:36)
at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:62)
at org.gradle.configuration.DefaultProjectsPreparer.prepareProjects(DefaultProjectsPreparer.java:55)
at org.gradle.configuration.BuildOperatingFiringProjectsPreparer$ConfigureBuild.run(BuildOperatingFiringProjectsPreparer.java:52)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92)
at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
at org.gradle.configuration.BuildOperatingFiringProjectsPreparer.prepareProjects(BuildOperatingFiringProjectsPreparer.java:40)
at org.gradle.initialization.DefaultGradleLauncher.prepareProjects(DefaultGradleLauncher.java:198)
at org.gradle.initialization.DefaultGradleLauncher.doClassicBuildStages(DefaultGradleLauncher.java:138)
at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:126)
at org.gradle.initialization.DefaultGradleLauncher.getConfiguredBuild(DefaultGradleLauncher.java:100)
at org.gradle.internal.invocation.GradleBuildController$2.execute(GradleBuildController.java:70)
at org.gradle.internal.invocation.GradleBuildController$2.execute(GradleBuildController.java:67)
at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:85)
at org.gradle.internal.invocation.GradleBuildController$3.create(GradleBuildController.java:78)
at org.gradle.internal.work.DefaultWorkerLeaseService.withLocks(DefaultWorkerLeaseService.java:189)
at org.gradle.internal.work.StopShieldingWorkerLeaseService.withLocks(StopShieldingWorkerLeaseService.java:40)
at org.gradle.internal.invocation.GradleBuildController.doBuild(GradleBuildController.java:78)
at org.gradle.internal.invocation.GradleBuildController.configure(GradleBuildController.java:67)
at org.gradle.tooling.internal.provider.runner.ClientProvidedPhasedActionRunner.run(ClientProvidedPhasedActionRunner.java:62)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
at org.gradle.launcher.exec.BuildOutcomeReportingBuildActionRunner.run(BuildOutcomeReportingBuildActionRunner.java:63)
at org.gradle.tooling.internal.provider.ValidatingBuildActionRunner.run(ValidatingBuildActionRunner.java:32)
at org.gradle.launcher.exec.BuildCompletionNotifyingBuildActionRunner.run(BuildCompletionNotifyingBuildActionRunner.java:39)
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:51)
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner$3.call(RunAsBuildOperationBuildActionRunner.java:45)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
at org.gradle.launcher.exec.RunAsBuildOperationBuildActionRunner.run(RunAsBuildOperationBuildActionRunner.java:45)
at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:50)
at org.gradle.launcher.exec.InProcessBuildActionExecuter$1.transform(InProcessBuildActionExecuter.java:47)
at org.gradle.composite.internal.DefaultRootBuildState.run(DefaultRootBuildState.java:78)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:47)
at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:31)
at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:42)
at org.gradle.launcher.exec.BuildTreeScopeBuildActionExecuter.execute(BuildTreeScopeBuildActionExecuter.java:28)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:78)
at org.gradle.tooling.internal.provider.ContinuousBuildActionExecuter.execute(ContinuousBuildActionExecuter.java:52)
at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:59)
at org.gradle.tooling.internal.provider.SubscribableBuildActionExecuter.execute(SubscribableBuildActionExecuter.java:36)
at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:68)
at org.gradle.tooling.internal.provider.SessionScopeBuildActionExecuter.execute(SessionScopeBuildActionExecuter.java:38)
at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:37)
at org.gradle.tooling.internal.provider.GradleThreadBuildActionExecuter.execute(GradleThreadBuildActionExecuter.java:26)
at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:43)
at org.gradle.tooling.internal.provider.ParallelismConfigurationBuildActionExecuter.execute(ParallelismConfigurationBuildActionExecuter.java:29)
at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:60)
at org.gradle.tooling.internal.provider.StartParamsValidatingActionExecuter.execute(StartParamsValidatingActionExecuter.java:32)
at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:55)
at org.gradle.tooling.internal.provider.SessionFailureReportingActionExecuter.execute(SessionFailureReportingActionExecuter.java:41)
at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:48)
at org.gradle.tooling.internal.provider.SetupLoggingActionExecuter.execute(SetupLoggingActionExecuter.java:32)
at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:68)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:39)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:27)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.RequestStopIfSingleUsedDaemon.execute(RequestStopIfSingleUsedDaemon.java:35)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:78)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.create(ForwardClientInput.java:75)
at org.gradle.util.Swapper.swap(Swapper.java:38)
at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:75)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.LogAndCheckHealth.execute(LogAndCheckHealth.java:55)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:63)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:82)
at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:37)
at org.gradle.launcher.daemon.server.api.DaemonCommandExecution.proceed(DaemonCommandExecution.java:104)
at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:52)
at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:297)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
Caused by: java.lang.ClassNotFoundException: org.gradle.kotlin.dsl.precompile.v1.PrecompiledProjectScript
... 150 more
* Get more help at https://help.gradle.org
CONFIGURE FAILED in 76ms
To Reproduce
Attaching the failing build.gradle
file. When using `apply plugin: 'kotlin-multiplatform' instead of the plugins block the project builds correctly but I cannot use fritz2.
buildscript {
repositories {
mavenLocal()
maven { url 'https://dl.bintray.com/kotlin/kotlin-eap' }
maven { url 'https://plugins.gradle.org/m2/' }
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id("dev.fritz2.fritz2-gradle") version "0.5"
}
group 'se.kth.somabits'
version '0.0.1'
repositories {
jcenter()
mavenLocal()
maven { url 'https://kotlin.bintray.com/ktor' }
maven { url 'https://kotlin.bintray.com/kotlinx' }
}
kotlin {
js('frontend') {
browser {
}
}
jvm('backend') {
compilations.main {
tasks.getByName(processResourcesTaskName) {
dependsOn(frontendBrowserProductionWebpack)
from(frontendBrowserProductionWebpack.outputPath)
}
}
}
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib-common')
implementation("dev.fritz2:core:$fritz_version")
}
}
commonTest {
dependencies {
implementation kotlin('test-common')
implementation kotlin('test-annotations-common')
}
}
backendMain {
dependencies {
implementation kotlin('stdlib-jdk8')
implementation "io.ktor:ktor-server-netty:$ktor_version"
implementation "io.ktor:ktor-html-builder:$ktor_version"
implementation "ch.qos.logback:logback-classic:$logback_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "io.ktor:ktor-server-netty:$ktor_version"
implementation "ch.qos.logback:logback-classic:$logback_version"
implementation "io.ktor:ktor-server-core:$ktor_version"
implementation "io.ktor:ktor-websockets:$ktor_version"
implementation "io.ktor:ktor-network:$ktor_version"
implementation "io.ktor:ktor-serialization:$ktor_version"
implementation "io.ktor:ktor-gson:$ktor_version"
implementation "org.jmdns:jmdns:3.5.5"
implementation "com.illposed.osc:javaosc-core:0.7"
implementation "io.ktor:ktor-html-builder:$ktor_version"
}
}
backendTest {
dependencies {
implementation kotlin('test')
implementation kotlin('test-junit')
}
}
frontendMain {
dependencies {
implementation kotlin('stdlib-js')
implementation "dev.fritz2:core:$fritz_version"
}
}
frontendTest {
dependencies {
implementation kotlin('test-js')
}
}
all {
languageSettings.enableLanguageFeature("InlineClasses")
}
}
}
task run(type: JavaExec, dependsOn: [backendJar]) {
main = "se.kth.somabits.backend.ApplicationKt"
classpath(configurations.backendRuntimeClasspath, backendJar)
args = []
jvmArgs = ["-Djava.net.preferIPv4Stack=true"]
}
Expected behavior
fritz2 gradle plugin working as described, or alternatively, instruction to use it without the plugin.
Additional context
Add any other context about the problem here.
Attributes that will not change over time should be offered as an optional parameter of the factory-method of the element.
This implemented at label
for the for
-attribute with #55.
The issue should collect all the attributes that should be handled this way to change implementation later in one row.
In the Fritz2 documentation it doesn't cover how to use KotlinX Serialization with remote calls. Also there is no guidance on how data modelling is handled with remote calls when using KotlinX Serialization.
At present we have
class Applicator<A, X>(inline val execute: suspend (A) -> Flow<X>) {
infix fun andThen(nextHandler: Handler<X>) = SimpleHandler<A> {
nextHandler.execute(it.flatMapConcat(this.execute))
}
Can be used as follows, eg to push another event onto a channel via offer
apply<> {
// some actions
} andThen handleAndOffer {
offer(it)
}
Unfortunately the resulting type is SimpleHandler, which does not implement Flow, and hence can't be subscribed to using handledBy
.
Can work around this by first assigning the handleAndOffer
instance as a property (so that it has an EmittingHandler
type) before composing after the action using andThen
. But would be nice if we could do this without the intermediate assignment.
Perhaps by having an additional andThen
overload that accepts an EmittingHandler
and returns a Handler type that implements Flow
?
Documentation on how to package the result as
Add detekt to gradle build.
When defining a WebComponent in Kotlin, the following message is shown in chrome:
webcomponent.kt:84 Uncaught TypeError: Failed to execute 'define' on 'CustomElementRegistry': The callback provided as parameter 2 is not a function.
at D (webcomponent.kt:84)
at Object.o (webcomponent.js:1)
at Object.<anonymous> (webcomponent.js:1)
at n (bootstrap:19)
at Object.<anonymous> (webcomponent.js:1)
at n (bootstrap:19)
at bootstrap:83
at webcomponent.js:1
at universalModuleDefinition:9
at universalModuleDefinition:1
The +"text"
function is identical to the text("text")
function. So it's only easier to write and similar to the Kotlin html DSL.
Add some tests and new documentation for connecting stores by using the handleAndEmit
method.
The method you must call inside of the function is called offer
so maybe it would be a better idea to name the method handleAndOffer
instead.
and make a multiplatfrom-project out of it.
I'm new to Kotlin/JS and came across fritz2 recently. I'm really impressed! It's focused, fast and well designed. Great job!
After having played with it for a while now and after writing first real code [1], I have questions here and there. So I'm wondering if there's something like a chat, mailing list or forum?
Would love to have a chat with the authors and users of fritz2, if that's feasible.
[1] I'm (re)writing halOS from using Kotlin HTML DSL to fritz2.
index.html has to be moved to src/main/resouces in all templates. The configuration of WebPack DevServer can be removed from gradle-files. This enables the use of distribution-tasks,
Build an extension for stores, so that they can remember the last n states an have the possibility to roll them back.
Like for HTMLInputElement
there is an extra SelectedAttributeDelegate
missing in fritz2.
The newly implemented algorithm to diff lists could be used for the class-attribute to add and remove single classes via addClass
and removeClass
to improve performance (?).
This is a feature request to open the element classes like A, Li, Div et al for inheritance.
I'm developing an UI library based on PatternFly. In order to integrate the PatternFly tags into the fritz2 DSL, I'd like to extend from the existing HTML tags like Li
or Div
.
Add a new andThen
method for other Appliers to chain and clean up code in store.kt
.
Try to use the new inline class mechanism for io.fritz2.binding.Seq<T>
class.
Documentation: Inline-classes.
To prevent caching-issues in the browser it would be good to include the actual version-number in the name of the js-file.
This requires adjusting the link in index.html automatically.
We need a way to dispatch arbitrary actions from anywhere in your application code.
Something like
val action<String>()
//...
action handledBy someStore.someHandler
//...
action.dispatch("hello world")
Maybe it is a good idea to use the browser's event-bus here, so third-party (JavaScript) components can be connected using the same api.
Make SingleMountPoint
atomic for updates like Handler. Therefore last attribute must be removed.
Describe the bug
After clicking on a button the connected event handler fails to execute. There is no error message/stack trace printed to the console.
To Reproduce
private val store = object : RootStore<Unit>(Unit) {
val handleBtnClick = handle {
console.log("Button clicked!")
Unit
}
}
fun main() {
render {
button {
text("Click Me")
clicks handledBy store.handleBtnClick
}
}.mount("target")
}
<!doctype html>
<html>
<head>
<title>Event Handler Test</title>
</head>
<body id="target">
Loading...
</body>
<script type="text/javascript" src="event-handling.js"></script>
</html>
Expected behaviour
A message is printed to the console after clicking on the button.
Desktop (please complete the following information):
gradle build-configuration is full of flaws (sorry, my first gradle-project...):
This should be streamlined and optimized.
The stores in fritz2 currently can handle concrete types T
and List<T>
but there is no support for Map<X, Y>
. Therefore we need a new keylens for maps and new methods.
Remote returns Result<Response>
instead of Response
.
Sometimes you need to know if a Handler
is currently running for showing a spinner in the right place. Therefore you need an extension for stores like Validation
which gives you a Flow
with the information of a running Handler
.
Right now you only have the parameter (action) that is forwarded to the Applicator
by the application code. It might be useful, to have a version, that can access the current model (i.e. a remote save operation).
While reading through the documentation I was wondering what the project name stands for?
Is it an acronym?
Was there a fritz (1)? If so, what happened to it?
I would love to see one or two sentences about this in the documentation.
The project looks very promising, keep up the good work!
When setting the value or checked attribute of an HTMLInputElement
from JS you must use the setting syntax directly like: elem.value = "new value";
Additionally for css selectors etc. you must call the setAttribute
and removeAttribute
for this attributes too.
Create an example that debounces events fired:
Use a range input to define the debouncing-interval and offer a button that uses this interval debouncing it's clicks.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.