[add] Page Builder API (15%)
This commit is contained in:
parent
198fd88449
commit
572a486f4f
9 changed files with 242 additions and 74 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
61
sui/storages/local/template_test.go
Normal file
61
sui/storages/local/template_test.go
Normal 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")
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ func TestLoad(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
check(t)
|
||||
}
|
||||
|
||||
func check(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue