https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
g

Gunslingor

08/30/2020, 12:19 AM
So in mpp, all content change happen in the frontend right, the server is just queried for data and front end back end are pretty isolated right? So onclick, change content with server data... typically, to change pages. So how does one change the url, and if someone enters an url they expect to see how do I tell the server to display that page. I'm also confused how the login page works... I get the impression it should be entirely defined in the ktor backend, not even the template should be in the front end is, is that right? Guess I'm confused about the handoff between front and backend
r

Robert Jaros

08/30/2020, 12:52 AM
In my opinion you should choose whether you want to build your UI on the client side (with Kotlin/JS) or on the server side (with Ktor html templates). Mixing those two ways is of course possible, but I think it won't do your project any good. It will be hard to understand and maintain.
Even though you write both sides with Kotlin, those are still separated parts of your project.
g

Gunslingor

08/30/2020, 12:57 AM
I agree, and I'm trying to do it all in the front end... but then I wonder: a) should the login/login be in the front or back... i.e. I would have to transfer the entire compressed project JS file to just to login, isn't that a bit of a security issue... gives everyone lots of stuff. b) if I do it all in the front end, I still need to change urls because that is what the user is used to, but really I would be changing the content of a single pane... But then what happens when the user refreshes the page or goes to an URL I am manually changing on click... I mean, I don't think KotlinJS provides any routing machanisms but ktor does
hmmm... guess react is the router
r

Robert Jaros

08/30/2020, 1:04 AM
a) there are some standard and widely used models of authentication for single page applications (OAuth, JWT). You should read about it before you try to reinvent the wheel 🙂 b) if you want to stick to frontend you should use JS routing. Kotlin/JS indeed doesn't provide any support for this, but there are libraries you can use. You have react-routing if you use kotlin-react. You can use my bindings for Navigo https://github.com/rjaros/navigo-kotlin (fully usable even without KVision 😉)
g

Gunslingor

08/30/2020, 1:09 AM
Ok, that's what I was thinking. So then the only route that goes in the backend is REST api routes and one route for the single page application... the only html in the backend is the head tag with libs and css links for the single page route, and a body tag that gets replaced by the login page part from the front end on startup. Sound reasonable? I cant think of a way to eliminate the head and body tags, based on how I think this works.
r

Robert Jaros

08/30/2020, 1:15 AM
yep, i think that's how it should be done
g

Gunslingor

08/30/2020, 1:16 AM
Thanks, sanity check really helps!!!
This look okay?
Copy code
fun main() {
    val root = "test"
    val useHash = false
    val hash = "#!"
    val router = Navigo(root, useHash, hash)
    router.on(
        mutableMapOf(
            "/testDemo" to demoWebEditor(),
            "/testProj" to demoTableAndProjection()
        )
    ).resolve()
    document.addEventListener("DOMContentLoaded", {
        stdNotifier()
        demoWebEditor()
    })
}
http://localhost:8080/test/testDemo doesnt seem to work
I think I got something partly working. Remaining issues: a) weird pathing behavior (http://localhost:8080/web/home works but add a "/" on the end and it still works but my image linked are broken. I wasted at least an hour on this, lol, a single slash. b) really would prefer a catch all/most in the backend, so that even http://localhost:8080/k/aj/sdf/lka/wjf8/90432u takes me somewhere, default page. Had to move stuff in the /static pathing and make that generic route (but doesn't work for anything, just web/ANYTHING till next start. Backend code next, seems the route has to be open in both for this to work, is there a better wildcard? I thought
**.*.*
worked somewhere but I think my brain is creating language salad now.
Copy code
route("web") {
  route("*") {
      get {
          call.respondHtml {
              frontend()
          }
      }
  }
}
static("/static") {
    resources("web")
    defaultResource("web/index.html")
}
Frontend:
Copy code
fun main() {
    document.addEventListener("DOMContentLoaded", {
        val router = Navigo(null, false)
        router
            .on("/web/home*", fun () {
                stdNotifier()
                demoWebEditor()
            }).on("/web/projection*", fun () {
                stdNotifier()
                demoTableAndProjection()
            })
            .resolve()
    })
}
Also a little concerned about security with front end routing... I mean I know the clients brain and they usually want to restrict access to pages as well as data, one giant JS file with front end routing makes that kinda pointless. But, I mean... there will be a user/group/role admin panel in this... so even user's will have that in the JS file they download? Granted there shouldn't be users, but just having access to the interface and calls and such saves a hacker much work. Or are we just being paranoid? Learning... trying to wrap my head around this... I feel like an old man trying to learn AOL in 1991, lol, or a grandmother learning to program her VCR in 1982, lol.
Copy code
static("/static") {
            resources("web")
            defaultResource("web/index.html")
        }
        route("{...}") {
            get {
                call.respondHtml {
                    frontend()
                }
            }
        }
Seems to work great, fixes all the above except for the images... when I go to localhost:8080/web/home the page works great, but when I add /asdf/asdf/asdf the img src and css background img urls break. Kind of interesting.
There we go, life is grand.... front end mod fixes:
Copy code
router
    .on("/web/home", fun () {
        demoWebEditor()
    }).on("/web/projection", fun () {
        demoTableAndProjection()
    }).on("/web/login", fun () {
        login()
    }).on("/web*", fun () {
        router.navigate("/web/login")
    }).resolve()
13 Views