Git Product home page Git Product logo

kyoto's People

Contributors

bketelsen avatar cejder avatar dhax avatar failingprovince avatar john-g-g avatar opensauce avatar preslavrachev avatar rowdyhcs avatar smoorpal avatar stigkj avatar yznts avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kyoto's Issues

Multi-layer async handling

In case when additional component are registered on Async stage, call async for newly added component

Prototype: Multi-stage component UI update on Action

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.

Using ParseFS and embed.FS

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"),
	)

Improve JS payload setup

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.

Make functions from TFuncMap available outside of FuncMap

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.

Need a good demo project

Hey guys,

looks pretty cool. Is there a demo of an app running on it anywhere? Plus, what's SSC?

Best

Eliminate obligatory using of `html/template` and give control to user

Need to provide something like ImplementsRender interface. This interface will give rendering control to page/component.
Steps to implement:

  • Define new interface for implementing render
  • Remove obligatory Template method in page interface
  • Define new interface for optional Template method
  • Integrate manual rendering control into lifecycle (check for at least one rendering option must to be implemented)

Pros:

  • Giving developer a control over final rendering step
  • Eliminating obligatory html/template usage, developer can choose alternative ways like maragudk/gomponents
  • Keeping components templates/rendering inside of *.go files will allow to distribute component libraries with Go packages

Component actions not being executed

I 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.

Page SSA

Make SSA, same as in the components

Question - set cookie on response to SSA call

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?

SSA gives an error on cold run

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.

Add loading attribute

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.

Passing Go packages to Pages/Components

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?

Server Side State

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:

  • Implement at least in-memory storage
  • Support for multiple state storages (with interface)
  • Component-level storage configuration (inline or server-side)

Insights tooling

As a replacement for current BENCH flags.
Insights must to store and provide detailed rendering timings.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.