kyoto-framework / kyoto Goto Github PK
View Code? Open in Web Editor NEWAsynchronous frontends with Go
Home Page: https://docs.kyoto.codes
License: MIT License
Asynchronous frontends with Go
Home Page: https://docs.kyoto.codes
License: MIT License
In case when additional component are registered on Async stage, call async for newly added component
Explore possibility to use server-sent events to deliver multiple UI updates.
Logic must to be similar to "flush" functionality of ORM frameworks, something like kyoto.SSAFlush(p)
Required knowledge:
Issue might be pretty hard to implement for people unfamiliar with project, but very interesting for those who want to explore project codebase.
This may lead to collision error while handling requests concurrently
I've been trying to figure out a pattern to use embed.FS
and template.ParseFS
for delivering the HTML files
Do you have any examples for this? I've been struggling with a couple of different errors and including the Funcs with the parsed templates
template: \"templates/pages.home.html\" is an incomplete or empty template
//go:embed templates
Templates embed.FS
return template.Must(
template.New("templates/pages.home.html").Funcs(kyoto.TFuncMap()).ParseFS(assets.Templates, "templates/pages.home.html"),
)
Start polling on page load. It's like calling action
with interval.
Trigger an action on page load
Need to provide adapter for comfortable attaching to application
Need a separate payload
folder with TS+esbuild setup. We need to build each file separately. JS builds can be included into Go project manually, just for now.
It's possible that it will be needed while implementing Render interface (#42).
We can extract functions to be available with preffix "T", like kyoto.TMeta
, kyoto.TDynamics
, kyoto.TComponentAttrs
, etc.
TFuncMap can be refactored just to map to existing public template functions.
Hey guys,
looks pretty cool. Is there a demo of an app running on it anywhere? Plus, what's SSC?
Best
Need to provide something like ImplementsRender
interface. This interface will give rendering control to page/component.
Steps to implement:
Template
method in page interfaceTemplate
methodPros:
html/template
usage, developer can choose alternative ways like maragudk/gomponents
*.go
files will allow to distribute component libraries with Go packagesI have an action which I've defined on a component. The component code looks like this:
package components
import (
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/yuriizinets/go-ssc"
"github.com/kodah/blog/controller"
"github.com/kodah/blog/service"
)
type SignIn struct {
Context *gin.Context
Username string
Password string
Errors []string
}
func (c *SignIn) Actions() ssc.ActionsMap {
return ssc.ActionsMap{
"DoSignIn": func(args ...interface{}) {
var configService service.ConfigService = service.ConfigurationService("")
if configService.Error() != nil {
log.Printf("Error while connecting to DB service. error=%s", configService.Error())
c.Errors = append(c.Errors, "Internal server error")
return
}
log.Printf("Triggered sign in")
var dbService service.DBService = service.SQLiteDBService("")
if dbService.Error() != nil {
log.Printf("Error while connecting to DB service. error=%s", dbService.Error())
c.Errors = append(c.Errors, "Internal server error")
return
}
var loginService service.LoginService = service.DynamicLoginService(dbService)
var jwtService service.JWTService = service.JWTAuthService()
var loginController controller.LoginController = controller.LoginHandler(loginService, jwtService)
c.Context.Set("Username", c.Username)
c.Context.Set("Password", c.Password)
session := service.NewSessionService(c.Context, false)
token := loginController.Login(c.Context)
session.Set("token", token)
err := session.Save()
if err != nil {
log.Printf("Error while saving session. error=%s", err)
}
log.Printf("Login successful. user=%s", c.Username)
c.Context.Redirect(http.StatusFound, "/")
},
}
}
The template:
{{ define "SignIn" }}
<div {{ componentattrs . }}>
<h1 class="title is-4">Sign in</h1>
<p id="errorFeedback" class="help has-text-danger is-hidden">
{{ .Username }} {{ .Password }}
</p>
<div class="field">
<div class="control">
<input class="input is-medium" value="{{ .Username }}" oninput="{{ bind `Username` }}" type="text" placeholder="username">
</div>
</div>
<div class="field">
<div class="control">
<input class="input is-medium" value="{{ .Password }}" oninput="{{ bind `Password` }}" type="password" placeholder="password">
</div>
</div>
<button onclick="{{ action `DoSignIn` `{}` }}" class="button is-block is-primary is-fullwidth is-medium">Submit</button>
<br />
<small><em>Be nice to the auth system.</em></small>
</div>
{{ end }}
and is included like this:
<div class="column sign-in has-text-centered">
{{ template "SignIn" .SignInComponent }}
</div>
Where the component inclusion looks like this:
package frontend
import (
"html/template"
"github.com/gin-gonic/gin"
"github.com/yuriizinets/go-ssc"
"github.com/kodah/blog/frontend/components"
)
type PageSignIn struct {
ctx *gin.Context
SignInComponent ssc.Component
}
func (p *PageSignIn) Template() *template.Template {
return template.Must(template.New("page.signin.html").Funcs(ssc.Funcs()).ParseGlob("frontend/new_templates/*/*.html"))
}
func (p *PageSignIn) Init() {
p.SignInComponent = ssc.RegC(p, &components.SignIn{
Context: p.ctx,
})
return
}
func (*PageSignIn) Meta() ssc.Meta {
return ssc.Meta{
Title: "Test kodah's blog",
Description: "Test description",
Canonical: "",
Hreflangs: nil,
Additional: nil,
}
}
When I run the DoSignIn
action it is not executed though;
<button onclick="{{ action `DoSignIn` `{}` }}" class="button is-block is-primary is-fullwidth is-medium">Submit</button>
I realize there's not a lot of documentation but I went off of the examples and this seems right.
Create separate interfaces for each feature, leave only required methods in base interface
Trigger an action on intersection
It would be nice to have per-component async cache configuration
Make SSA, same as in the components
How is it possible to access the request context from a call to a Server-Side Action.
Say, for instance you want to set a cookie in the response to an SSA call.
In the example demo app for the form submission example (email validator) you have the following:
type ComponentDemoEmailValidator struct {
Email string
Message string
Color string
}
func (c *ComponentDemoEmailValidator) Actions() ssc.ActionMap {
return ssc.ActionMap{
"Submit": func(args ...interface{}) {
if emailregex.MatchString(c.Email) {
c.Message = "Provided email is valid"
c.Color = "green"
} else {
c.Message = "Provided email is not valid"
c.Color = "red"
}
},
}
}
I am aware you can create an "Init" method function to access the request context i.e.
func (c *ComponentDemoEmailValidator) Init(p ssc.Page) {
c.Page = p
r := ssc.GetContext(p, "internal:r").(*http.Request)
rw := ssc.GetContext(p, "internal:rw").(http.ResponseWriter)
}
But how do you access the request/response context from within the "Actions()" method so that you can, for example, set a cookie in the response.
Is this possible?
Need an automatic way to convert payload outputs to Go files
Catching an error while calling SSA on cold run. SSA components store is populated while initial page rendering, which is never triggered on cold run.
Need some optional explicit way to register components on app start.
Need to include all features with short description and status (stable, unstable, deprecated, planned)
Because Kyoto makes a roundtrip to the server every time an action is triggered on the page, there are cases when the page may not react immediately to a user event (like a click). We need to provide a way to easily display loading states.
Been playing around with Kyoto and really liking the pattern once I managed to get my head around it
But now I'm starting to wonder what are the best practices for passing Go packages to Pages/Components seen as the handlers create a new instance of the page on each page load it's not possible to pass in a dependency inside the Page/Component structs
One way I've managed to do this is passing it into the Context but I don't really want to fill up my context with lots of dependencies but I feel like there must be a nicer way of doing this that is more scalable?
Add INSIGHTS_CLI_JSON
config to support output in JSON format
Needed attributes for:
Will be useful in case of large state payloads.
Instead of saving state inline as html tag, store state on server side and inject state hash as html tag.
This feature will decrease amount of data, sent with SSA request and total HTML document size.
Key requirements:
As a replacement for current BENCH flags.
Insights must to store and provide detailed rendering timings.
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.