[add] Page Builder API (15%)

This commit is contained in:
Max 2023-09-24 19:16:00 +08:00
parent 198fd88449
commit 572a486f4f
9 changed files with 242 additions and 74 deletions

View file

@ -9,9 +9,19 @@ type SUI interface {
// Page is the struct for the page
type Page struct {
template *Template
route string
file string
Route string `json:"route"`
Root string `json:"root"`
Files PageFiles `json:"files"`
}
// PageFiles is the struct for the page files
type PageFiles struct {
HTML string `json:"html"`
CSS string `json:"css"`
JS string `json:"js"`
TS string `json:"ts"`
LESS string `json:"less"`
DATA string `json:"data"`
}
// Component is the struct for the component

View file

@ -1,55 +1,54 @@
package azure
import (
"fmt"
"net/url"
"github.com/yaoapp/yao/sui/core"
)
// Remote is the struct for the azure sui
type Remote struct{ url url.URL }
// Azure is the struct for the azure sui
type Azure struct{ url url.URL }
// new create a new azure sui
func new(host url.URL) (*Remote, error) {
return &Remote{url: host}, nil
func new() (*Azure, error) {
return &Azure{}, nil
}
// New create a new azure sui
func New(dsl *core.DSL) (*Remote, error) {
func New(dsl *core.DSL) (*Azure, error) {
if dsl.Storage.Option == nil {
return nil, fmt.Errorf("option.host is required")
}
// if dsl.Storage.Option == nil {
// return nil, fmt.Errorf("option.host is required")
// }
if dsl.Storage.Option["host"] == nil {
return nil, fmt.Errorf("option.host is required")
}
// if dsl.Storage.Option["host"] == nil {
// return nil, fmt.Errorf("option.host is required")
// }
host, ok := dsl.Storage.Option["host"].(string)
if !ok {
return nil, fmt.Errorf("option.host %s is not a valid string", host)
}
// host, ok := dsl.Storage.Option["host"].(string)
// if !ok {
// return nil, fmt.Errorf("option.host %s is not a valid string", host)
// }
u, err := url.Parse(host)
if err != nil {
return nil, fmt.Errorf("option.host %s is not a valid url", host)
}
// u, err := url.Parse(host)
// if err != nil {
// return nil, fmt.Errorf("option.host %s is not a valid url", host)
// }
return new(*u)
return new()
}
// GetTemplates get the templates
func (azure *Remote) GetTemplates() ([]core.ITemplate, error) {
func (azure *Azure) GetTemplates() ([]core.ITemplate, error) {
return nil, nil
}
// GetTemplate get the template
func (azure *Remote) GetTemplate(name string) (core.ITemplate, error) {
func (azure *Azure) GetTemplate(name string) (core.ITemplate, error) {
return nil, nil
}
// UploadTemplate upload the template
func (azure *Remote) UploadTemplate(src string, dst string) (core.ITemplate, error) {
func (azure *Azure) UploadTemplate(src string, dst string) (core.ITemplate, error) {
return nil, nil
}

View file

@ -1,8 +1,15 @@
package local
import (
"fmt"
"path"
"path/filepath"
"strings"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou/fs"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/sui/core"
sui "github.com/yaoapp/yao/sui/core"
)
@ -63,7 +70,7 @@ func (local *Local) GetTemplates() ([]sui.ITemplate, error) {
continue
}
tmpl, err := local.NewTemplate(dir)
tmpl, err := local.getTemplateFrom(dir)
if err != nil {
log.Error("GetTemplates %s error: %s", dir, err.Error())
continue
@ -75,11 +82,53 @@ func (local *Local) GetTemplates() ([]sui.ITemplate, error) {
}
// GetTemplate get the template
func (local *Local) GetTemplate(name string) (sui.ITemplate, error) {
return nil, nil
func (local *Local) GetTemplate(id string) (sui.ITemplate, error) {
path := path.Join(local.root, id)
return local.getTemplate(id, path)
}
// UploadTemplate upload the template
func (local *Local) UploadTemplate(src string, dst string) (sui.ITemplate, error) {
return nil, nil
}
// GetTemplateFrom get the template from the path
func (local *Local) getTemplateFrom(path string) (*Template, error) {
id := local.getTemplateID(path)
return local.getTemplate(id, path)
}
// getTemplate get the template
func (local *Local) getTemplate(id string, path string) (*Template, error) {
tmpl := Template{
local: local,
Root: path,
Template: &core.Template{
ID: id,
Name: strings.ToUpper(id),
Version: 1,
Screenshots: []string{},
}}
// load the template.json
configFile := filepath.Join(path, fmt.Sprintf("%s.json", id))
if local.fs.IsFile(configFile) {
configBytes, err := local.fs.ReadFile(configFile)
if err != nil {
return nil, err
}
err = jsoniter.Unmarshal(configBytes, &tmpl.Template)
if err != nil {
return nil, err
}
}
return &tmpl, nil
}
// GetTemplateID get the template ID
func (local *Local) getTemplateID(path string) string {
return filepath.Base(path)
}

View file

@ -36,6 +36,22 @@ func TestGetTemplates(t *testing.T) {
}
func TestGetTemplate(t *testing.T) {
tests := prepare(t)
defer clean()
websiteAI, err := tests.Demo.GetTemplate("website-ai")
if err != nil {
t.Fatalf("GetTemplate error: %v", err)
}
assert.Equal(t, "website-ai", websiteAI.(*Template).ID)
assert.Equal(t, "Website DEMO", websiteAI.(*Template).Name)
assert.Equal(t, true, len(websiteAI.(*Template).Screenshots) > 0)
assert.Equal(t, 2, websiteAI.(*Template).Version)
assert.Equal(t, "AI Website DEMO", websiteAI.(*Template).Descrption)
}
func prepare(t *testing.T) struct {
Demo *Local
Screen *Local

View file

@ -5,45 +5,10 @@ import (
"path/filepath"
"strings"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/sui/core"
)
// NewTemplate create a new local template
func (local *Local) NewTemplate(path string) (*Template, error) {
id := local.GetTemplateID(path)
tmpl := Template{
Path: path,
Template: &core.Template{
ID: id,
Name: strings.ToUpper(id),
Version: 1,
Screenshots: []string{},
}}
// load the template.json
configFile := filepath.Join(path, fmt.Sprintf("%s.json", id))
if local.fs.IsFile(configFile) {
configBytes, err := local.fs.ReadFile(configFile)
if err != nil {
return nil, err
}
err = jsoniter.Unmarshal(configBytes, &tmpl.Template)
if err != nil {
return nil, err
}
}
return &tmpl, nil
}
// GetTemplateID get the template ID
func (local *Local) GetTemplateID(path string) string {
return filepath.Base(path)
}
// Get get the template
func (tmpl *Template) Get() error {
return nil
@ -56,7 +21,74 @@ func (tmpl *Template) Save() error {
// Pages get the pages
func (tmpl *Template) Pages() ([]core.IPage, error) {
return nil, nil
exts := []string{"*.sui", "*.html", "*.htm", "*.page"}
pages := []core.IPage{}
tmpl.local.fs.Walk(tmpl.Root, func(root, file string, isdir bool) error {
name := filepath.Base(file)
if isdir {
if strings.HasPrefix(name, "__") {
return filepath.SkipDir
}
return nil
}
if strings.HasPrefix(name, "__") {
return nil
}
page, err := tmpl.getPageFrom(file)
if err != nil {
log.Error("Get page error: %v", err)
return nil
}
pages = append(pages, page)
return nil
}, exts...)
return pages, nil
}
// Page get the page
func (tmpl *Template) Page(route string) (core.IPage, error) {
path := filepath.Join(tmpl.Root, route)
exts := []string{".sui", ".html", ".htm", ".page"}
for _, ext := range exts {
file := fmt.Sprintf("%s%s", path, ext)
if exist, _ := tmpl.local.fs.Exists(file); exist {
return tmpl.getPageFrom(file)
}
}
return nil, fmt.Errorf("Page %s not found", route)
}
func (tmpl *Template) getPageFrom(path string) (core.IPage, error) {
route := tmpl.getPageRoute(path)
return tmpl.getPage(route, path)
}
func (tmpl *Template) getPage(route, file string) (core.IPage, error) {
root := filepath.Dir(file)
return &Page{
tmpl: tmpl,
Page: &core.Page{
Route: route,
Root: root,
Files: core.PageFiles{
HTML: fmt.Sprintf("%s%s", route, filepath.Ext(file)),
CSS: fmt.Sprintf("%s.css", route),
JS: fmt.Sprintf("%s.js", route),
DATA: fmt.Sprintf("%s.json", route),
TS: fmt.Sprintf("%s.ts", route),
LESS: fmt.Sprintf("%s.less", route),
},
},
}, nil
}
func (tmpl *Template) getPageRoute(path string) string {
return strings.TrimSuffix(path[len(tmpl.Root):], filepath.Ext(path))
}
// Blocks get the blocks
@ -69,11 +101,6 @@ func (tmpl *Template) Components() ([]core.IComponent, error) {
return nil, nil
}
// Page get the page
func (tmpl *Template) Page(route string) (core.IPage, error) {
return nil, nil
}
// Block get the block
func (tmpl *Template) Block(name string) (core.IBlock, error) {
return nil, nil

View file

@ -0,0 +1,61 @@
package local
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestTemplatePages(t *testing.T) {
tests := prepare(t)
defer clean()
tmpl, err := tests.Demo.GetTemplate("website-ai")
if err != nil {
t.Fatalf("GetTemplate error: %v", err)
}
pages, err := tmpl.Pages()
if err != nil {
t.Fatalf("Pages error: %v", err)
}
if len(pages) < 1 {
t.Fatalf("Pages error: %v", len(pages))
}
assert.Equal(t, "/index", pages[0].(*Page).Route)
assert.Equal(t, "/templates/website-ai", pages[0].(*Page).Root)
assert.Equal(t, "/index.css", pages[0].(*Page).Files.CSS)
assert.Equal(t, "/index.html", pages[0].(*Page).Files.HTML)
assert.Equal(t, "/index.js", pages[0].(*Page).Files.JS)
assert.Equal(t, "/index.less", pages[0].(*Page).Files.LESS)
assert.Equal(t, "/index.ts", pages[0].(*Page).Files.TS)
assert.Equal(t, "/index.json", pages[0].(*Page).Files.DATA)
}
func TestTemplatePage(t *testing.T) {
tests := prepare(t)
defer clean()
tmpl, err := tests.Demo.GetTemplate("website-ai")
if err != nil {
t.Fatalf("GetTemplate error: %v", err)
}
page, err := tmpl.Page("/index")
if err != nil {
t.Fatalf("Page error: %v", err)
}
assert.Equal(t, "/index", page.(*Page).Route)
assert.Equal(t, "/templates/website-ai", page.(*Page).Root)
assert.Equal(t, "/index.css", page.(*Page).Files.CSS)
assert.Equal(t, "/index.html", page.(*Page).Files.HTML)
assert.Equal(t, "/index.js", page.(*Page).Files.JS)
assert.Equal(t, "/index.less", page.(*Page).Files.LESS)
assert.Equal(t, "/index.ts", page.(*Page).Files.TS)
assert.Equal(t, "/index.json", page.(*Page).Files.DATA)
_, err = tmpl.Page("/the/page/could/not/be/found")
assert.Contains(t, err.Error(), "Page /the/page/could/not/be/found not found")
}

View file

@ -14,12 +14,14 @@ type Local struct {
// Template is the struct for the local sui template
type Template struct {
Path string `json:"-"`
Root string `json:"-"`
local *Local
*core.Template
}
// Page is the struct for the local sui page
type Page struct {
tmpl *Template
*core.Page
}

View file

@ -5,6 +5,7 @@ import (
"strings"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/share"
"github.com/yaoapp/yao/sui/core"
@ -37,7 +38,7 @@ func New(dsl *core.DSL) (core.SUI, error) {
// Load load the sui
func Load(cfg config.Config) error {
exts := []string{"*.core.yao", "*.core.jsonc", "*.core.json"}
exts := []string{"*.sui.yao", "*.sui.jsonc", "*.sui.json"}
return application.App.Walk("suis", func(root, file string, isdir bool) error {
if isdir {
return nil
@ -46,6 +47,7 @@ func Load(cfg config.Config) error {
id := share.ID(root, file)
_, err := loadFile(file, id)
if err != nil {
log.Error("[sui] Load sui %s error: %s", id, err.Error())
return err
}
return nil

View file

@ -16,6 +16,8 @@ func TestLoad(t *testing.T) {
if err != nil {
t.Fatal(err)
}
check(t)
}
func check(t *testing.T) {