rjaros / kvision Goto Github PK
View Code? Open in Web Editor NEWObject oriented web framework for Kotlin/JS
Home Page: https://kvision.io
License: MIT License
Object oriented web framework for Kotlin/JS
Home Page: https://kvision.io
License: MIT License
I'm trying to share data between my backend and front end by following your Ktor full stack example.
I have a data class like below:
data class Aircraft(var id:String = "",
var aircraft_image:Image? = null,
var aircraft_pdf:Binary? = null)
The my question is are there any Kvision native types that I can use to transfer these from back to front? or is it best to just encode them in Base64 and then decode on the frontend?
Firstly I just wanted to pass on a compliment, KVision is brilliant. I'm not sure why it's not more popular, perhaps because its still relatively new.
My question might be a little novice, is it possible to use Bootstrap 4 themes with Kvision? As far as I can tell the docs only mention bootstrap 3
I am getting import errors on the following packages when switching across to version 0.0.30:
import com.lightningkite.kotlin.observable.list.*
import pl.treksoft.kvision.data.*
Are you seeing the same thing?
Here is my dependencies in build.gradle:
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:${kotlinVersion}"
compile "pl.treksoft:kvision:${kvisionVersion}"
compile "pl.treksoft:kvision-bootstrap:${kvisionVersion}"
compile "pl.treksoft:kvision-select:${kvisionVersion}"
compile "pl.treksoft:kvision-datetime:${kvisionVersion}"
compile "pl.treksoft:kvision-spinner:${kvisionVersion}"
compile "pl.treksoft:kvision-richtext:${kvisionVersion}"
compile "pl.treksoft:kvision-upload:${kvisionVersion}"
compile "pl.treksoft:kvision-handlebars:${kvisionVersion}"
compile "pl.treksoft:kvision-i18n:${kvisionVersion}"
compile "pl.treksoft:kvision-remote:${kvisionVersion}"
compile "pl.treksoft:kvision-electron:${kvisionVersion}"
compile "pl.treksoft:kvision-chart:${kvisionVersion}"
compile "org.jetbrains.kotlin:kotlin-test-js:${kotlinVersion}"
}
With DataContainer tables I could use
is EventState -> cell {
button(I18n.tr(logEntry.title), icon = v.iconName, style = ButtonStyle.LINK)
}
in order to get LinkButtons in tables.
How can I do it with Tabolator based tables?
I am trying to stretch my containers vertically to fill available space. To give you an example:
root = Root("kvapp") {
width = 100.perc
height = 100.perc
vPanel {
background = Background(Col.RED)
width = 100.perc
height = 100.perc
label("Label") { }
}
}
When I run the app however, it appears there is an extra container being inserted between the Root and first divs which I can't access:
Is there an example for tooltips (aka: popup / bubble help)?
Hello there, thanks for sharing this framework. It is amazing.
I would like to have a client-side requesting data from server-side(ktor). The server-side will be API. See below, a sample...
I got a Forbidden(403) request when I try to use the POST method. The GET function works fine.
How can I get it to work? Am I missing a config here?
I'm trying to figure out if its feasible to use an observable on the server side drive a subscriber on the client side.
Let's say I have an observable array on the Ktor server and a service of something like getArray which updates a list on the client side. Is there any way to have the array on the server drive a change on the client without calling getArray again?
Hi, this looks very nice and it's much easier to understand coming from desktop java than other web frameworks.
I tried adding a gradle dependency "pl.treksoft:kvision:0.0.12" to my project (after digging a little through the code) but when i build try to run it in the browser it says "Error loading module 'mymodule-js'. Its dependency 'kvision' was not found. Please, check whether 'kvision' is loaded prior to 'mymodule-js'."
I'm not using webpack or kotlin frontend pluging, because i have an existing project using spring boot. Is there a way to use kvision as a dependency using gradle?
Hi Robert,
first of all: thanks for providing kvision!
I have an issue with extracting data (user input) from a form. In the examples you assume a fixed model class that allows to extract user input via getData().
I hava a use case where I would like to be able to create forms dynamically, ie. there is no static model class.
I would like to access Form.fields but FormPanel.form is protected.
How should I address this? Roll my own FormPanel and make form accessible?
Thanks in advance
Jörg
Is it possible to change the client side port to something other than 8088? I am trying to deploy my ktor-kvision app to GCP and there is only port 443 available for HTTPS
Hi! Thanks for your awesome framework
Do you have any plans to create reference template with Ktor?
The guide has an example for receiving routes:
routing.on({ _ -> println("Main page") })
.on("/test", { _ -> println("Test route") })
.on(RegExp("/test3/(.*)/(.*)/(.*)"), { x, y, z -> println("Regexp: $x $y $z") })
.resolve()
but what would I do if I wanted to navigate to one, lets say via a link:
link("Go to test", url = "/test")
However this just seems to point to the browser to a file with path /test
As far as I could see in the examples, all HTML rendering is done on the client-side. That's ok for "internal" apps. But I would be interested in using kvision for a public website which would highly benefit from SSR (because SEO and speed).
Do you think its possible to do SSR with kvision? Do you have ideas about what would be needed to implement it?
And while we're at it: code splitting for the css would be great too, to improve initial page load/render.
I think this would be great enhancements to kvision, whats your opinion on this?
I'm really enjoying kvision. I'm actually using it to write a simple application, however I haven't found a wrapper for service workers.
An example for creating a simple Progressive web app would be really useful.
I'll be happy to contribute once I've figured out how to do it.
I am trying to add a formPanel to a responsiveGridPanel but running up against a roadblock:
I've got both defined as below:
val clientSelect = Select(label = "Client").apply {
liveSearch = true
setEventListener<Select> {
change = {
console.log(self.value ?: "")
}
}
}
DataContainer(clientNameList, { client, _, _ ->
SelectOption(client.id, client.name)
}, clientSelect)
val clientFormSelectPanel = formPanel<ClientSelectForm> {
add(ClientSelectForm::clientName, clientSelect)
}
responsiveGridPanel {
add(clientFormSelectPanel, 1, 1, 2)
}
However because I'm using formPanel DSL, it adds it to the DOM twice as would be expected.
If I wanted to add a label I could just use:
val someLabel = Label("Some Label")
responsiveGridPanel {
add(someLabel, 1, 1, 2)
}
Is there a way to initialize a form panel like this? perhaps it might look something like:
val clientFormSelectPanel = FormPanel<ClientSelectForm> {
add(ClientSelectForm::clientName, clientSelect)
}
I am getting some strange results when using DataContainer with table rows.
I have a table that looks something like this:
table(
listOf("Column 1", "Column 2"),
setOf(TableType.BORDERED, TableType.CONDENSED, TableType.STRIPED, TableType.HOVER), responsive = true
) {
dataContainer(pairList, { element, idx, list ->
row {
cell(element.first)
cell(element.second)
}
})
}
where pairList
is defined as:
var pairList:ObservableList<Pair<String, String>> = observableListOf()
init {
pairList.add(Pair("first","second"))
pairList.add(Pair("third","fourth"))
}
and the result I am getting looks like this:
Nowhere else is pairList being set to an element, so I'm not sure why the duplicate values are showing up
How do I access properties of the title bar? specifically I would like to do something like this:
https://github.com/binaryfunt/electron-seamless-titlebar-tutorial
I guess the fix is a simple rename of the modules to something like ChartOptions and TabulatorOptions. It would only come up if you were to use both in the same namespace.
I am requesting support for custom editors in Tabulator as described here.
http://tabulator.info/docs/4.2/edit#edit-custom
To learn a codebase, I refactor stuff.
I like how the codebase is built!
I got a bit to excited with refactoring, so I break it down before I hijack your project...
So at the moment, it's not compiling.
I made a class DelegationMap to which the fields are delegated as well as some refreshing-logic.
I intentionally wanted to just create a delegationClass for the fields, but that would create a lot of objects, therefor I grouped them.
The advantage now is that it's very easy to store state and getSnStyle is a lot easier as well.
So, it's up to you if you want (it) to continue this direction.
my current refactorings can be found overhere: https://github.com/tieskedh/kvision/tree/refactoring/delegates
Keep up the good work!!!
In the Kvision-Ktor framework, I can define a service manager and automate routing like so:
applyRoutes(AuthenticationServiceManager)
However, I would also like to use Ktor sessions and cookies for tracking users. With Ktor routing I can do the following:
data class SampleSession(val name: String, val value: Int)
...
get("/get") {
val session = call.sessions.get<SampleSession>() ?: SampleSession(0)
call.respondHtml {"Counter: ${session.counter}"}
}
What's the best way to achieve this using ktor but access the result as a function from Kvision?
This is the error I am getting when trying to set format = Formatter.DATETIME in a ColumnDefinition:
Uncaught (in promise) ReferenceError: moment is not defined
at C.datetime (tabulator.min.js:11)
at C.formatValue (tabulator.min.js:11)
at l._generateContents (tabulator.min.js:8)
at l.setValueActual (tabulator.min.js:8)
at l.build (tabulator.min.js:8)
at new l (tabulator.min.js:8)
at t.i.generateCell (tabulator.min.js:6)
at eval (tabulator.min.js:6)
at Array.forEach (<anonymous>)
at t.generateCells (tabulator.min.js:6)
My Class has a date field of type pl.treksoft.kvision.types.Date
as I am using Ktor for my backend
Currently I use a context menu to close a tab, an icon would be nice.
The Bootstrap progress bar actually supports adding a label, which is unsupported in kvision
since the ProgressBar
class is missing the label
property.
Workaround, we set the content of the ProgressIndicator to the desired label:
progressBar(10) {
(getChildren().first() as Tag).content = "My label"
}
Hi Robert,
I would like to add tabs to TabPanel at runtime. Showcase.start() and TabPanel.addTab() suggest that this is not possible right now.
SubClassing didn't work out since TabPanel.content & nav are private.
How should I proceed?
Thanks in advance
Jörg
To learn a codebase, I refactor stuff.
I like how the codebase is built!
I got a bit to excited with refactoring, so I break it down before I hijack your project...
So at the moment, it's not compiling.
I made a class DelegationMap to which the fields are delegated as well as some refreshing-logic.
I intentionally wanted to just create a delegationClass for the fields, but that would create a lot of objects, therefor I grouped them.
The advantage now is that it's very easy to store state and getSnStyle is a lot easier as well.
So, it's up to you if you want (it) to continue this direction.
my current refactorings can be found overhere: https://github.com/tieskedh/kvision/tree/refactoring/delegates
Keep up the good work!!!
I have the following code
div(classes = setOf("alert", "alert-dismissible")) {
maxWidth = 20.rem
button(text = "×", classes = setOf("close")) {
setAttribute("data-dismiss", "alert")
}
}
}
which I'm expecting to add a data-dismiss attribute to the button, but is actually being applied to the parent div.
Is this correct behaviour? Is it possible to achieve without wrapping the button in another div?
Many Thanks.
I get an error of Interface Dialog does not have constructors
when trying to run the following code snippet:
GlobalScope.launch {
val dialog = Dialog<String>("Dialog with result") {
add(Label("Press a button"))
addButton(Button("Button").onClick {
setResult("STRING RESULT")
})
}
val result = dialog.getResult()
console.log(result)
}
If there is another way to do this, I'd love to hear it but this is the way I've tried so far. Maybe you can correct my method.
I've got a table that I've made reactive using dataContainer:
val tableTemplate = Table(
listOf("Column 1", "Column 2"),
responsive = true
)
dataContainer(rowList, { element, idx, list ->
Row {
cell(element.one)
cell(element.two)
}, tableTemplate)
This works well, but it is read-only. I would like to integrate a form panel into each row, something like this:
@Serializable
data class SomeClass(val one:String = "", val two:String = "")
dataContainer(rowList, { element, idx, list ->
Row {
val internalFormPanel = formPanel<SomeClass> {
cell {
[email protected](
SomeClass::one,
Text()
)
}
cell {
[email protected](
SomeClass::two,
Text()
)
}
}
add(internalFormPanel)
internalFormPanel.setData(element)
}
}, tableTemplate)
The result is the correct number of rows but with empty cells. What is the correct way to create editable tables?
Figure I may as well start. This issue for future, you mentioned a while ago that you were looking at Cordova integration.
I just want to flesh out a plan for how to go about it. We will eventually need to release our apps on Android and iOS.
It looks like you can create a Cordova app using npm, we're you thinking something like an npm package that creates a cordova-kvision app for the various platforms? Or something in gradle? I'm not sure how the latter would work in production
I might be jumping the gun here, but all I have changed about my project is setting KVision version from 0.0.34 to 0.0.35 in gradle properties. This appears to lead to the following error on the front end of my Ktor-KVision project:
Uncaught Error: Cannot find module 'core-js/features/object/assign'
at webpackMissingModule (webpack:///../node_modules_imported/kotlin-extensions/kotlin-extensions.js?:116)
at eval (webpack:///../node_modules_imported/kotlin-extensions/kotlin-extensions.js?:116)
at Object.../node_modules_imported/kotlin-extensions/kotlin-extensions.js (main.bundle.js:2207)
at __webpack_require__ (main.bundle.js:724)
at fn (main.bundle.js:101)
at eval (webpack:///../node_modules_imported/kotlin-redux/kotlin-redux.js?:143)
at Object.../node_modules_imported/kotlin-redux/kotlin-redux.js (main.bundle.js:2229)
at __webpack_require__ (main.bundle.js:724)
at fn (main.bundle.js:101)
at eval (webpack:///../node_modules_imported/kvision-redux/kvision-redux.js?:3)
If it's just a difference in the gradle process, then I can wait for the documentation and just ignore this :)
What would be the best way to add non-text things to cells? In this case I specifically wanted to add buttons in a cell.
I have an existing SpringBoot RESTful backend that I want to create a kvision frontend for. I can't seem to find any documentation highlighting how that would behave.
Does that support exist?
Alternatively, is there kvision support for serializing to/from json? If I could find an example of that I could get un-stuck.
I might be using Select form the wrong way, but I have an internal API that returns an observable list which I would like to use in a select box. I'm not sure how to make the select options update with the new elements added to the observable list.
This is what I have so far:
class SomeContainer: SimplePanel() {
var someList: ObservableList<Pair<String, String>> = observableListOf()
init {
val formPanel = formPanel<SomeForm> {
add(
SomeForm::select,
Select(
label = "Simple select"
).also {
options = someList
liveSearch = true
}
)
}
someList.add(Pair("someValue", "someLabel"))
someList.add(Pair("someOtherValue", "someOtherLabel"))
.....
}
}
The result is an empty options list when selecting, perhaps this is expected since options expects a non-mutable list.
Is there any way to do this?
In Chart.js, I can update the chart like this, how would I access these methods in KVision?
chart.data.labels.push(label);
chart.data.datasets.forEach((dataset) => {
dataset.data.push(data);
});
chart.update();
Specifically, I am trying to bind the chart state to an observable list of data but I'm not sure if Chart.js can handle observables so I can just update the chart manually if there is a way to do so.
I think one of the things missing for KVision is a good loader/spinner module. Since a lot of the cool things KVision can do are using coroutines and ajax requests, it stands to reason that KVision needs a good loading bar.
I saw there is ProgressBar
which works well for our team in our forms, but we also would like a generic loader when we load our data from the backend (our app is very data intensive and makes a lot of requests).
I could just create something for our team, but would rather contribute something to KVision for others. Let me know what you think, I was thinking something like a wrapper for nanobar.js or pace.js
My resources folder looks like this:
resources
-css
-bootstrap.min.css
I am trying to require a new bootstrap file like this in my start function:
...
pl.treksoft.kvision.require("./css/bootstrap.min.css")
...
However, I get a 404 not found error. Just as in the showcase example, I've got this copy resources task defined in my build.gradle:
task copyResources(type: Copy) {
from "src/main/resources"
into file(buildDir.path + "/js")
}
The copyResources
task does the right thing and copies it into build/js/css/bootstrap.min.css
, but it doesn't let me require the css file in my code
I want to write feedback as a user who used the framework, maybe you need it.
It is a framework that can have great skills in the future as I think, perhaps will compete with Vaadin. It's a good thing you support him. It would be very good to have documentation with live examples (no only code), such as within the yested framework (see here) which is also written on kotlin, you can directly see the code and what UI it generates, in the same place, it will be very nice.
Thank you for attention
I have a modal I initialize and show with the following code in the root of the showcase example:
root = Root("showcase") {
val modal = Modal("Example Modal", size = ModalSize.LARGE, closeButton = true,
animation = false, escape = false)
modal.show()
tabPanel {
width = 80.perc
margin = 20.px
.....
}
The result looks fine:
until I try to close the modal:
Is there any way to remove the background effect and UI blocking after calling modal.hide() or pressing the closeButton?
I am trying to create a form panel but running into an issue, the following code produces an error:
val formPanel = FormPanel(serializer = Form.serializer())
The error is Unresolved reference: serializer
I'm a little stumped on how to get the underlying ObservableList to change when
I've got a table like below:
@Serializable
data class Numbers(val number1: Int, val number2: Int)
val someObservableList= observableListOf(
Numbers(2, 4),
Numbers(3, 1)
)
tabulator(
someObservableList,
pl.treksoft.kvision.tabulator.Options(
dataEdited = {
someObservableList.clear()
someObservableList.addAll(it as List<dynamic>)
someObservableList.addAll(it as Array<dynamic>)
},
reactiveData = true,
layout = Layout.FITCOLUMNS,
columns = listOf(
ColumnDefinition("Number 1", "number1", editor = Editor.INPUT),
ColumnDefinition("Number 2", "number2", editor = Editor.INPUT)
)
)
) {
height = 100.perc
width = 100.perc
}
I've tried accepting the data back into the observable list with the dataEdited
parameter but I get a casting error.
Any ideas?
I've been developing with KVision for a couple of months so I can see the applicability as a web development tool. I'd love to get more involved.
Are you open to getting some help in developing the platform? If so, perhaps you could share some of the items on the to-do list you mentioned in another issue
I have a karma proxy.js on the client like the following:
var old = module.exports;
module.exports = function(config) {
var temp = new Object();
temp.set = function(c) {
temp.conf = c;
};
var oldConfig = old(temp);
temp.conf.proxies = {
'/tmp/_karma_webpack_/': 'http://localhost:8088/'
}
config.set(temp.conf);
};
My server port is set to 8080 just like in the example, when I run the client and the server it says webpack is already running, and throws an error on localhost:8088:
POST http://localhost:8088/kv/routeMongoDBServiceManager0 504 (Gateway Timeout)
I've tried changning ports but it just says webpack is still running on port 8088 and throws the gateway timeout error
Hi,
I was playing with the numbers-fullstack-ktor sample. I could not get to work when pushing to Heroku. Did you not place the "stage" task on the sample? Just wondering how did you push it to Heroku.
`! Warning: Multiple default buildpacks reported the ability to handle this app. The first buildpack in the list below will be used.
Detected buildpacks: Gradle,Node.js
See https://devcenter.heroku.com/articles/buildpacks#buildpack-detect-order
-----> Gradle app detected
-----> Installing JDK 1.8... done
-----> Building Gradle app...
-----> executing ./gradlew stage
Downloading https://services.gradle.org/distributions/gradle-5.3.1-all.zip
..............................................................................................................................
FAILURE: Build failed with an exception.
* What went wrong:
Task 'stage' not found in root project 'build_ec5df8584cf853f6eed8de6fbf8979ff'.
* Try:
Run gradlew tasks to get a list of available tasks. Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 27s
! ERROR: Failed to run Gradle!
It looks like your project does not contain a 'stage' task, which Heroku needs in order
to build your app. Our Dev Center article on preparing a Gradle application for Heroku
describes how to create this task:
https://devcenter.heroku.com/articles/deploying-gradle-apps-on-heroku
If you're stilling having trouble, please submit a ticket so we can help:
https://help.heroku.com
Thanks,
Heroku
! Push rejected, failed to compile Gradle app.
! Push failed`
Is it possible to run native JavaScript in KVision?
For example, I have some code that authenticates a user with a MongoDB database:
const app = Stitch.defaultAppClient
const credential = new UserPasswordCredential("<email>", "<password>")
app.auth.loginWithCredential(credential)
// Returns a promise that resolves to the authenticated user
.then(authedUser => console.log(`successfully logged in with id: ${authedUser.id}`))
.catch(err => console.error(`login failed with error: ${err}`))
It depends on a JavaScript library I include in /web/index.html and doesn't have a kotlin extension I can use:
<!DOCTYPE html>
<html>
<head>
....
<script src="https://s3.amazonaws.com/stitch-sdks/js/bundles/4.0.0/stitch.js"></script>
</head>
<body>
<div id="kvapp"></div>
</body>
</html>
I would like to embed the JavaScript into a Kotlin function, something like this:
fun doLogin(): Boolean {
val loggedIn:Boolean = runNativeJavascript()
return loggedIn
}
is it possible to use the inbuilt Navigo routing API without having the hash show up?
This is what I have tried so far to no avail:
val customRouter = Navigo("/", false)
customRouter
.on("/some-url", { _ ->
console.log("currently on some-url!")
})
.resolve()
It just throws a 404 error when visiting the url
How would I get the parameters from the URL?
Hi,
Using KVision 0.0.31. When I attempt to show a modal Alert I get a javascript error stating that tmp$.modal is not a function. If I add a custom bootstrap theme and put an href in the index.html for it (css/bootstrap.min.css) then the error goes away. Seems that it might be an issue loading the bootstrap.js?
Quick example of this issue:
root = Root("fhirApp") {
navbar(label = "My Meds", type = NavbarType.FIXEDTOP, inverted = true)
GlobalScope.launch {
try {
val result = PatientService.patientInContext()
add(PatientHeader(result))
throw Exception()
} catch (e: Exception) {
console.log(e)
Alert.show("Alert dialog", "Lorem ipsum dolor sit amet, consectetur adipiscing.")
} finally {
val div = document.getElementById("loaderDiv")
div?.remove()
}
}
add(LoaderPanel("loaderDiv"))
}
Thanks
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.