[add] block export and media api

This commit is contained in:
Max 2023-10-18 21:18:54 +08:00
parent e9844819e2
commit 5e371f1dfb
8 changed files with 251 additions and 4 deletions

View file

@ -44,12 +44,28 @@ var dsl = []byte(`
"process": "sui.Block.Get",
"in": ["$param.id", "$param.template_id"],
"out": { "status": 200, "type": "application/json" }
},{
"path": "/:id/block/export/:template_id",
"method": "GET",
"process": "sui.Block.Export",
"in": ["$param.id", "$param.template_id"],
"out": { "status": 200, "type": "application/json" }
},{
"path": "/:id/block/:template_id/:block_id",
"method": "GET",
"process": "sui.Block.Find",
"in": ["$param.id", "$param.template_id", "$param.block_id"],
"out": { "status": 200, "type": "text/javascript" }
},{
"path": "/:id/block/:template_id/:block_id/media",
"method": "GET",
"process": "sui.Block.Media",
"in": ["$param.id", "$param.template_id", "$param.block_id"],
"out": {
"status": 200,
"body": "?:content",
"headers": { "Content-Type": "?:type"}
}
},
{

View file

@ -22,8 +22,10 @@ func init() {
"locale.get": LocaleGet,
"theme.get": ThemeGet,
"block.get": BlockGet,
"block.find": BlockFind,
"block.get": BlockGet,
"block.find": BlockFind,
"block.Media": BlockMedia,
"block.export": BlockExport,
"component.get": ComponentGet,
"component.find": ComponentFind,
@ -139,6 +141,49 @@ func BlockGet(process *process.Process) interface{} {
return blocks
}
// BlockExport handle the find Template request
func BlockExport(process *process.Process) interface{} {
process.ValidateArgNums(2)
sui := get(process)
templateID := process.ArgsString(1)
tmpl, err := sui.GetTemplate(templateID)
if err != nil {
exception.New(err.Error(), 500).Throw()
}
items, err := tmpl.BlockLayoutItems()
if err != nil {
exception.New(err.Error(), 500).Throw()
}
return items
}
// BlockMedia handle the find Template request
func BlockMedia(process *process.Process) interface{} {
process.ValidateArgNums(3)
sui := get(process)
templateID := process.ArgsString(1)
blockID := strings.TrimRight(process.ArgsString(2), ".js")
tmpl, err := sui.GetTemplate(templateID)
if err != nil {
exception.New(err.Error(), 500).Throw()
}
asset, err := tmpl.BlockMedia(blockID)
if err != nil {
exception.New(err.Error(), 500).Throw()
}
return map[string]interface{}{
"content": asset.Content,
"type": asset.Type,
}
}
// BlockFind handle the find Template request
func BlockFind(process *process.Process) interface{} {
process.ValidateArgNums(3)

View file

@ -115,7 +115,7 @@ func TestTemplateThemeGet(t *testing.T) {
assert.Equal(t, "light", res.([]core.SelectOption)[1].Value)
}
func TestTemplateBlockGet(t *testing.T) {
func TestBlockGet(t *testing.T) {
load(t)
defer clean()
@ -138,7 +138,7 @@ func TestTemplateBlockGet(t *testing.T) {
assert.Equal(t, "Table", res.([]core.IBlock)[3].(*local.Block).ID)
}
func TestTemplateBlockFind(t *testing.T) {
func TestBlockFind(t *testing.T) {
load(t)
defer clean()
@ -157,6 +157,43 @@ func TestTemplateBlockFind(t *testing.T) {
assert.Contains(t, res.(string), "window.block__ColumnsTwo=")
}
func TestBlockExport(t *testing.T) {
load(t)
defer clean()
// test demo
p, err := process.Of("sui.block.export", "demo", "tech-blue")
if err != nil {
t.Fatal(err)
}
res, err := p.Exec()
if err != nil {
t.Fatal(err)
}
assert.IsType(t, &core.BlockLayoutItems{}, res)
assert.Equal(t, 2, len(res.(*core.BlockLayoutItems).Categories))
}
func TestBlockMedia(t *testing.T) {
load(t)
defer clean()
// test demo
p, err := process.Of("sui.block.media", "demo", "tech-blue", "ColumnsTwo")
if err != nil {
t.Fatal(err)
}
res, err := p.Exec()
if err != nil {
t.Fatal(err)
}
assert.IsType(t, map[string]interface{}{}, res)
assert.Equal(t, "image/png", res.(map[string]interface{})["type"])
assert.NotEmpty(t, res.(map[string]interface{})["content"])
}
func TestTemplateComponentGet(t *testing.T) {
load(t)
defer clean()

View file

@ -60,3 +60,8 @@ func (block *Block) Compile() (string, error) {
func (block *Block) Source() string {
return block.Compiled
}
// Get get the block
func (block *Block) Get() *Block {
return block
}

View file

@ -21,6 +21,8 @@ type ITemplate interface {
GetPageFromAsset(asset string) (IPage, error)
Blocks() ([]IBlock, error)
BlockLayoutItems() (*BlockLayoutItems, error)
BlockMedia(id string) (*Asset, error)
Block(name string) (IBlock, error)
Components() ([]IComponent, error)
@ -65,6 +67,7 @@ type IBlock interface {
Compile() (string, error)
Load() error
Source() string
Get() *Block
}
// IComponent is the interface for the component

View file

@ -46,6 +46,20 @@ type Block struct {
Codes SourceCodes `json:"-"`
}
// BlockLayoutItems is the struct for the block layout items
type BlockLayoutItems struct {
Categories []LayoutItem `json:"categories"`
Locals map[string]map[string]string `json:"locals,omitempty"`
}
// LayoutItem is the struct for the layout it
type LayoutItem struct {
ID string `json:"id"`
Label string `json:"label,omitempty"`
Width int `json:"width,omitempty"`
Blocks []LayoutItem `json:"blocks,omitempty"`
}
// Template is the struct for the template
type Template struct {
Version int `json:"version"` // Yao Builder version

View file

@ -4,6 +4,7 @@ import (
"fmt"
"path/filepath"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/yao/sui/core"
)
@ -64,6 +65,86 @@ func (tmpl *Template) Block(id string) (core.IBlock, error) {
return block, nil
}
// BlockMedia get the block media
func (tmpl *Template) BlockMedia(id string) (*core.Asset, error) {
path := filepath.Join(tmpl.Root, "__blocks", id, "media.png")
if exist, _ := tmpl.local.fs.Exists(path); exist {
content, err := tmpl.local.fs.ReadFile(path)
if err != nil {
return nil, err
}
return &core.Asset{
Type: "image/png",
Content: content,
}, nil
}
path = filepath.Join(tmpl.Root, "__blocks", id, "media.svg")
if exist, _ := tmpl.local.fs.Exists(path); !exist {
return nil, fmt.Errorf("Block %s media not found (media.png / media.png )", id)
}
content, err := tmpl.local.fs.ReadFile(path)
if err != nil {
return nil, err
}
return &core.Asset{
Type: "image/svg+xml",
Content: content,
}, nil
}
// BlockLayoutItems export the blocks
func (tmpl *Template) BlockLayoutItems() (*core.BlockLayoutItems, error) {
path := filepath.Join(tmpl.Root, "__blocks", "export.json")
if exist, _ := tmpl.local.fs.Exists(path); !exist {
blocks, err := tmpl.Blocks()
if err != nil {
return nil, err
}
// Default layout items
layoutItems := &core.BlockLayoutItems{
Categories: []core.LayoutItem{{
ID: "Basic",
Label: "Basic",
Blocks: []core.LayoutItem{},
}},
Locals: map[string]map[string]string{
"zh-CN": {"Basic": "基础"},
"zh-TW": {"Basic": "基礎"},
},
}
for _, block := range blocks {
layoutItems.Categories[0].Blocks = append(
layoutItems.Categories[0].Blocks, core.LayoutItem{
ID: block.Get().ID,
Label: block.Get().Name,
})
}
return layoutItems, nil
}
data, err := tmpl.local.fs.ReadFile(path)
if err != nil {
return nil, err
}
layoutItems := core.BlockLayoutItems{}
err = application.Parse(path, data, &layoutItems)
if err != nil {
return nil, err
}
return &layoutItems, nil
}
// Load get the block from the storage
func (block *Block) Load() error {

View file

@ -81,3 +81,49 @@ func TestTemplateBlockTS(t *testing.T) {
assert.Contains(t, block.(*Block).Compiled, "window.block__Hero")
assert.Contains(t, block.(*Block).Compiled, `<div data-gjs-type='Nav'></div>`)
}
func TestBlockLayoutItems(t *testing.T) {
tests := prepare(t)
defer clean()
tmpl, err := tests.Demo.GetTemplate("tech-blue")
if err != nil {
t.Fatalf("GetTemplate error: %v", err)
}
items, err := tmpl.BlockLayoutItems()
if err != nil {
t.Fatalf("BlockLayoutItems error: %v", err)
}
assert.Equal(t, 2, len(items.Categories))
tmpl, err = tests.Demo.GetTemplate("website-ai")
if err != nil {
t.Fatalf("GetTemplate error: %v", err)
}
items, err = tmpl.BlockLayoutItems()
if err != nil {
t.Fatalf("BlockLayoutItems error: %v", err)
}
assert.Equal(t, 1, len(items.Categories))
}
func TestBlockMedia(t *testing.T) {
tests := prepare(t)
defer clean()
tmpl, err := tests.Demo.GetTemplate("tech-blue")
if err != nil {
t.Fatalf("GetTemplate error: %v", err)
}
media, err := tmpl.BlockMedia("ColumnsTwo")
if err != nil {
t.Fatalf("BlockMedia error: %v", err)
}
assert.Equal(t, "image/png", media.Type)
}