Merge pull request #498 from trheyi/main
[add] SUI Template MediaSearch
This commit is contained in:
commit
4d26ba6be8
7 changed files with 113 additions and 17 deletions
1
go.mod
1
go.mod
|
|
@ -105,6 +105,7 @@ require (
|
||||||
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
|
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
|
||||||
go.mongodb.org/mongo-driver v1.13.0 // indirect
|
go.mongodb.org/mongo-driver v1.13.0 // indirect
|
||||||
golang.org/x/arch v0.6.0 // indirect
|
golang.org/x/arch v0.6.0 // indirect
|
||||||
|
golang.org/x/image v0.14.0 // indirect
|
||||||
golang.org/x/mod v0.14.0 // indirect
|
golang.org/x/mod v0.14.0 // indirect
|
||||||
golang.org/x/net v0.18.0 // indirect
|
golang.org/x/net v0.18.0 // indirect
|
||||||
golang.org/x/oauth2 v0.14.0 // indirect
|
golang.org/x/oauth2 v0.14.0 // indirect
|
||||||
|
|
|
||||||
3
go.sum
3
go.sum
|
|
@ -261,8 +261,9 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0
|
||||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
||||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||||
golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo=
|
|
||||||
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
|
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
|
||||||
|
golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
|
||||||
|
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,7 @@ var dsl = []byte(`
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"guard": "-",
|
"guard": "-",
|
||||||
"process": "sui.Template.Asset",
|
"process": "sui.Template.Asset",
|
||||||
"in": ["$param.id", "$param.template_id", "$param.path"],
|
"in": ["$param.id", "$param.template_id", "$param.path", "$query.w", "$query.h"],
|
||||||
"out": {
|
"out": {
|
||||||
"status": 200,
|
"status": 200,
|
||||||
"body": "?:content",
|
"body": "?:content",
|
||||||
|
|
@ -185,7 +185,7 @@ var dsl = []byte(`
|
||||||
"guard": "query-jwt",
|
"guard": "query-jwt",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"process": "sui.Page.Asset",
|
"process": "sui.Page.Asset",
|
||||||
"in": ["$param.id", "$param.template_id", "$param.path"],
|
"in": ["$param.id", "$param.template_id", "$param.path", "$query.w", "$query.h"],
|
||||||
"out": {
|
"out": {
|
||||||
"status": 200,
|
"status": 200,
|
||||||
"body": "?:content",
|
"body": "?:content",
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,9 @@ func TemplateAsset(process *process.Process) interface{} {
|
||||||
exception.New(err.Error(), 500).Throw()
|
exception.New(err.Error(), 500).Throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
asset, err := tmpl.Asset(process.ArgsString(2))
|
w := process.ArgsInt(3, 0)
|
||||||
|
h := process.ArgsInt(4, 0)
|
||||||
|
asset, err := tmpl.Asset(process.ArgsString(2), uint(w), uint(h))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exception.New(err.Error(), 404).Throw()
|
exception.New(err.Error(), 404).Throw()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ type ITemplate interface {
|
||||||
Locales() []SelectOption
|
Locales() []SelectOption
|
||||||
Themes() []SelectOption
|
Themes() []SelectOption
|
||||||
|
|
||||||
Asset(file string) (*Asset, error)
|
Asset(file string, width, height uint) (*Asset, error)
|
||||||
AssetUpload(reader io.Reader, name string) (string, error)
|
AssetUpload(reader io.Reader, name string) (string, error)
|
||||||
|
|
||||||
MediaSearch(query url.Values, page int, pageSize int) (MediaSearchResult, error)
|
MediaSearch(query url.Values, page int, pageSize int) (MediaSearchResult, error)
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package local
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -54,17 +53,32 @@ func (tmpl *Template) Themes() []core.SelectOption {
|
||||||
// MediaSearch search the asset
|
// MediaSearch search the asset
|
||||||
func (tmpl *Template) MediaSearch(query url.Values, page int, pageSize int) (core.MediaSearchResult, error) {
|
func (tmpl *Template) MediaSearch(query url.Values, page int, pageSize int) (core.MediaSearchResult, error) {
|
||||||
res := core.MediaSearchResult{Data: []core.Media{}, Page: page, PageSize: pageSize}
|
res := core.MediaSearchResult{Data: []core.Media{}, Page: page, PageSize: pageSize}
|
||||||
|
keyword := query.Get("keyword")
|
||||||
|
types := query["types"]
|
||||||
|
if types == nil {
|
||||||
|
types = []string{"image", "video", "audio"}
|
||||||
|
}
|
||||||
|
exts := tmpl.mediaExts(types)
|
||||||
|
path := filepath.Join(tmpl.Root, "__assets", "upload")
|
||||||
|
files, total, pagecnt, err := tmpl.local.fs.List(path, exts, page, pageSize, func(s string) bool {
|
||||||
|
if keyword == "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return strings.Contains(s, keyword)
|
||||||
|
})
|
||||||
|
|
||||||
total := 124
|
if err != nil {
|
||||||
pagecnt := int(math.Ceil(float64(total) / float64(pageSize)))
|
return res, err
|
||||||
for i := 0; i < pageSize; i++ {
|
}
|
||||||
test := fmt.Sprintf("https://plus.unsplash.com/premium_photo-1671641797903-fd39ec702b16?auto=format&fit=crop&q=80&w=2334&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%%3D%%3D&id=%d", (page-1)*pageSize+i)
|
|
||||||
thumb := fmt.Sprintf("https://plus.unsplash.com/premium_photo-1671641797903-fd39ec702b16?auto=format&fit=crop&q=80&w=100&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%%3D%%3D&id=%d", (page-1)*pageSize+i)
|
for _, file := range files {
|
||||||
|
|
||||||
|
file = strings.TrimPrefix(file, filepath.Join(tmpl.Root, "__assets", "upload"))
|
||||||
res.Data = append(res.Data, core.Media{
|
res.Data = append(res.Data, core.Media{
|
||||||
ID: test,
|
ID: file,
|
||||||
URL: test,
|
URL: filepath.Join("@assets", "upload", file),
|
||||||
Thumb: thumb,
|
Thumb: filepath.Join("@assets", "upload", file),
|
||||||
Type: "image",
|
Type: tmpl.mediaType(file),
|
||||||
Width: 100,
|
Width: 100,
|
||||||
Height: 100,
|
Height: 100,
|
||||||
})
|
})
|
||||||
|
|
@ -86,6 +100,57 @@ func (tmpl *Template) MediaSearch(query url.Values, page int, pageSize int) (cor
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tmpl *Template) mediaExts(types []string) []string {
|
||||||
|
exts := []string{}
|
||||||
|
for _, typ := range types {
|
||||||
|
switch typ {
|
||||||
|
|
||||||
|
case "image":
|
||||||
|
exts = append(exts, []string{".jpg", ".jpeg", ".png"}...)
|
||||||
|
break
|
||||||
|
|
||||||
|
case "video":
|
||||||
|
exts = append(exts, []string{".mp4"}...)
|
||||||
|
break
|
||||||
|
|
||||||
|
case "audio":
|
||||||
|
exts = append(exts, []string{".mp3"}...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return exts
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tmpl *Template) mediaType(file string) string {
|
||||||
|
ext := strings.ToLower(filepath.Ext(file))
|
||||||
|
switch ext {
|
||||||
|
|
||||||
|
case ".jpg":
|
||||||
|
return "image"
|
||||||
|
|
||||||
|
case ".jpeg":
|
||||||
|
return "image"
|
||||||
|
|
||||||
|
case ".png":
|
||||||
|
return "image"
|
||||||
|
|
||||||
|
case ".gif":
|
||||||
|
return "image"
|
||||||
|
|
||||||
|
case ".bmp":
|
||||||
|
return "image"
|
||||||
|
|
||||||
|
case ".mp4":
|
||||||
|
return "video"
|
||||||
|
|
||||||
|
case ".mp3":
|
||||||
|
return "audio"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "file"
|
||||||
|
}
|
||||||
|
|
||||||
// AssetUpload upload the asset
|
// AssetUpload upload the asset
|
||||||
func (tmpl *Template) AssetUpload(reader io.Reader, name string) (string, error) {
|
func (tmpl *Template) AssetUpload(reader io.Reader, name string) (string, error) {
|
||||||
|
|
||||||
|
|
@ -101,11 +166,15 @@ func (tmpl *Template) AssetUpload(reader io.Reader, name string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Asset get the asset
|
// Asset get the asset
|
||||||
func (tmpl *Template) Asset(file string) (*core.Asset, error) {
|
func (tmpl *Template) Asset(file string, width, height uint) (*core.Asset, error) {
|
||||||
|
|
||||||
file = filepath.Join(tmpl.Root, "__assets", file)
|
file = filepath.Join(tmpl.Root, "__assets", file)
|
||||||
if exist, _ := tmpl.local.fs.Exists(file); exist {
|
if exist, _ := tmpl.local.fs.Exists(file); exist {
|
||||||
|
|
||||||
|
if width > 0 || height > 0 {
|
||||||
|
return tmpl.assetThumb(file, width, height)
|
||||||
|
}
|
||||||
|
|
||||||
content, err := tmpl.local.fs.ReadFile(file)
|
content, err := tmpl.local.fs.ReadFile(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -145,3 +214,26 @@ func (tmpl *Template) Asset(file string) (*core.Asset, error) {
|
||||||
|
|
||||||
return nil, fmt.Errorf("Asset %s not found", file)
|
return nil, fmt.Errorf("Asset %s not found", file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tmpl *Template) assetThumb(file string, width, height uint) (*core.Asset, error) {
|
||||||
|
|
||||||
|
cacheFile := filepath.Join(tmpl.Root, "__assets", ".cache", fmt.Sprintf("%dx%d", width, height), file)
|
||||||
|
exist, _ := tmpl.local.fs.Exists(cacheFile)
|
||||||
|
if !exist {
|
||||||
|
err := tmpl.local.fs.Resize(file, cacheFile, width, height)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typ, err := tmpl.local.fs.MimeType(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := tmpl.local.fs.ReadFile(cacheFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &core.Asset{Type: typ, Content: content}, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ func TestTemplateAsset(t *testing.T) {
|
||||||
t.Fatalf("GetTemplate error: %v", err)
|
t.Fatalf("GetTemplate error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
asset, err := tmpl.Asset("/css/tailwind.css")
|
asset, err := tmpl.Asset("/css/tailwind.css", 0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Asset error: %v", err)
|
t.Fatalf("Asset error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue