Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix auto save edit reload from sever; fix pagebuilder ,template permi… #625

Merged
merged 2 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions cmd/qor5/website-template/admin/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import (
"net/http"

"github.com/qor/oss/filesystem"
"github.com/qor5/web/v3"
"github.com/qor5/x/v3/perm"
"github.com/qor5/x/v3/ui/vuetify"
. "github.com/theplant/htmlgo"
"github.com/theplant/osenv"
"golang.org/x/text/language"
"gorm.io/gorm"

"github.com/qor5/admin/v3/activity"
"github.com/qor5/admin/v3/media"
"github.com/qor5/admin/v3/pagebuilder"
Expand All @@ -15,13 +23,6 @@ import (
"github.com/qor5/admin/v3/publish"
"github.com/qor5/admin/v3/seo"
"github.com/qor5/admin/v3/utils"
"github.com/qor5/web/v3"
"github.com/qor5/x/v3/perm"
"github.com/qor5/x/v3/ui/vuetify"
. "github.com/theplant/htmlgo"
"github.com/theplant/osenv"
"golang.org/x/text/language"
"gorm.io/gorm"
)

var PublishDir = osenv.Get(
Expand Down Expand Up @@ -77,7 +78,7 @@ func newConfig(db *gorm.DB) config {
publisher := publish.New(db, storage)
seoBuilder := seo.New(db).AutoMigrate()

pageBuilder := pagebuilder.New(b.GetURIPrefix()+"/page_builder", db).
pageBuilder := pagebuilder.New(b.GetURIPrefix()+"/page_builder", db, b).
AutoMigrate().
Publisher(publisher)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ func PageBuilderExample(b *presets.Builder, db *gorm.DB) http.Handler {
}
b.Use(puBuilder)

pb := pagebuilder.New(b.GetURIPrefix()+"/page_builder", db).
pb := pagebuilder.New(b.GetURIPrefix()+"/page_builder", db, b).
Activity(ab).
Only("Title", "Slug").
DisabledNormalContainersGroup(true).
Expand Down
24 changes: 12 additions & 12 deletions example/admin/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ import (
"github.com/qor/oss"
"github.com/qor/oss/filesystem"
"github.com/qor/oss/s3"
"github.com/qor5/web/v3"
"github.com/qor5/x/v3/i18n"
"github.com/qor5/x/v3/login"
"github.com/qor5/x/v3/perm"
v "github.com/qor5/x/v3/ui/vuetify"
vx "github.com/qor5/x/v3/ui/vuetifyx"
h "github.com/theplant/htmlgo"
"github.com/theplant/osenv"
"golang.org/x/text/language"
"gorm.io/gorm"

"github.com/qor5/admin/v3/activity"
"github.com/qor5/admin/v3/autosync"
"github.com/qor5/admin/v3/example/models"
Expand All @@ -38,16 +49,6 @@ import (
"github.com/qor5/admin/v3/role"
"github.com/qor5/admin/v3/utils"
"github.com/qor5/admin/v3/worker"
"github.com/qor5/web/v3"
"github.com/qor5/x/v3/i18n"
"github.com/qor5/x/v3/login"
"github.com/qor5/x/v3/perm"
v "github.com/qor5/x/v3/ui/vuetify"
vx "github.com/qor5/x/v3/ui/vuetifyx"
h "github.com/theplant/htmlgo"
"github.com/theplant/osenv"
"golang.org/x/text/language"
"gorm.io/gorm"
)

//go:embed assets
Expand Down Expand Up @@ -270,8 +271,7 @@ func NewConfig(db *gorm.DB) Config {
configNestedFieldDemo(b, db)

b.Use(w.Activity(ab))

pageBuilder := example.ConfigPageBuilder(db, "/page_builder", ``, b.GetI18n())
pageBuilder := example.ConfigPageBuilder(db, "/page_builder", ``, b)
pageBuilder.
Media(mediab).
L10n(l10nBuilder).
Expand Down
23 changes: 23 additions & 0 deletions example/integration/pagebuilder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,29 @@ func TestPageBuilder(t *testing.T) {
},
ExpectPortalUpdate0ContainsInOrder: []string{"blue", "LinkText 不能为空"},
},
{
Name: "Container Heading Update Reload Editing",
Debug: true,
ReqFunc: func() *http.Request {
pageBuilderDemoContainerTestData.TruncatePut(dbr)
req := NewMultipartBuilder().
PageURL("/page_builder/headings").
EventFunc(actions.Update).
Query(presets.ParamID, "1").
AddField("LinkText", "Replace{{Name}}").
BuildEventFuncRequest()

return req
},
EventResponseMatch: func(t *testing.T, er *TestEventResponse) {
heading := containers.Heading{}
TestDB.First(&heading, 1)
if heading.LinkText != "ReplaceLinkText" {
t.Fatalf("container has not updated")
return
}
},
},
}

for _, c := range cases {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ require (
github.com/qor/oss v0.0.0-20240729105053-88484a799a79
github.com/qor5/web v1.3.2
github.com/qor5/web/v3 v3.0.10-0.20240930021253-c7c6a418ae3d
github.com/qor5/x/v3 v3.0.11-0.20241008100135-f9614db5e9da
github.com/qor5/x/v3 v3.0.11-0.20241008101402-4249b9034f8b
github.com/samber/lo v1.47.0
github.com/shurcooL/sanitized_anchor_name v1.0.0
github.com/spf13/cast v1.6.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ github.com/qor5/web/v3 v3.0.10-0.20240930021253-c7c6a418ae3d h1:7A/JkehEyeZgqODQ
github.com/qor5/web/v3 v3.0.10-0.20240930021253-c7c6a418ae3d/go.mod h1:32vdHHcZb2JimlcaclW9hLUyimdXjrllZDHTh3rl6d0=
github.com/qor5/x/v3 v3.0.11-0.20241008100135-f9614db5e9da h1:RLp/llHs/xSeRCjspyPf1+fo9NHyegVsNrBHwMeNcHY=
github.com/qor5/x/v3 v3.0.11-0.20241008100135-f9614db5e9da/go.mod h1:kMR6DyRGm90zkro6v4xf+pfieESWEplueTZIiMh3M/Y=
github.com/qor5/x/v3 v3.0.11-0.20241008101402-4249b9034f8b h1:JJXHxPMiBZ86Xiypb/aSNjJV6yuoQrP7bYK7ZMxY9cQ=
github.com/qor5/x/v3 v3.0.11-0.20241008101402-4249b9034f8b/go.mod h1:kMR6DyRGm90zkro6v4xf+pfieESWEplueTZIiMh3M/Y=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
Expand Down
97 changes: 85 additions & 12 deletions pagebuilder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
vx "github.com/qor5/x/v3/ui/vuetifyx"
"github.com/sunfmin/reflectutils"
h "github.com/theplant/htmlgo"
"github.com/theplant/relay"
"golang.org/x/text/language"
"gorm.io/gorm"

Expand All @@ -33,7 +34,6 @@ import (
"github.com/qor5/admin/v3/richeditor"
"github.com/qor5/admin/v3/seo"
"github.com/qor5/admin/v3/utils"
"github.com/theplant/relay"
)

type RenderInput struct {
Expand Down Expand Up @@ -96,6 +96,7 @@ type Builder struct {
templateEnabled bool
expendContainers bool
pageEnabled bool
autoSaveReload bool
disabledNormalContainersGroup bool
previewOpenNewTab bool
previewContainer bool
Expand All @@ -116,11 +117,11 @@ const (
PageBuilderPreviewCard = "PageBuilderPreviewCard"
)

func New(prefix string, db *gorm.DB) *Builder {
return newBuilder(prefix, db)
func New(prefix string, db *gorm.DB, b *presets.Builder) *Builder {
return newBuilder(prefix, db, b)
}

func newBuilder(prefix string, db *gorm.DB) *Builder {
func newBuilder(prefix string, db *gorm.DB, b *presets.Builder) *Builder {
r := &Builder{
db: db,
wb: web.New(),
Expand All @@ -142,10 +143,9 @@ func newBuilder(prefix string, db *gorm.DB) *Builder {
BrandTitle("Page Builder").
DataOperator(gorm2op.DataOperator(db)).
URIPrefix(prefix).
I18n(b.GetI18n()).
DetailLayoutFunc(r.pageEditorLayout)
r.ps.Permission(perm.New().Policies(
perm.PolicyFor(perm.Anybody).WhoAre(perm.Allowed).ToDo(perm.Anything).On(perm.Anything),
))
r.ps.Permission(b.GetPermission())
return r
}

Expand All @@ -160,6 +160,11 @@ func (b *Builder) PageStyle(v h.HTMLComponent) (r *Builder) {
return b
}

func (b *Builder) AutoSaveReload(v bool) (r *Builder) {
b.autoSaveReload = v
return b
}

func (b *Builder) AutoMigrate() (r *Builder) {
err := AutoMigrate(b.db)
if err != nil {
Expand Down Expand Up @@ -383,6 +388,9 @@ func (b *Builder) Install(pb *presets.Builder) (err error) {
for _, t := range b.templates {
t.Install()
}
for _, t := range b.containerBuilders {
t.Install()
}
return
}

Expand Down Expand Up @@ -940,10 +948,52 @@ func (b *Builder) RegisterModelContainer(name string, mb *presets.ModelBuilder)
return
}

func (b *ContainerBuilder) Model(m interface{}) *ContainerBuilder {
b.model = m
b.mb = b.builder.ps.Model(m)
b.mb.Editing().WrapIdCurrentActive(func(in presets.IdCurrentActiveProcessor) presets.IdCurrentActiveProcessor {
type TagInterface interface {
SetAttr(k string, v interface{})
}

func (b *ContainerBuilder) setFieldsLazyWrapComponentFunc(fields *presets.FieldsBuilder) {
for _, fieldName := range fields.FieldNames() {
field := fields.GetField(fieldName.(string))
if field.GetNestedFieldsBuilder() != nil {
b.setFieldsLazyWrapComponentFunc(field.GetNestedFieldsBuilder())
continue
}
field.LazyWrapComponentFunc(func(in presets.FieldComponentFunc) presets.FieldComponentFunc {
return func(obj interface{}, field *presets.FieldContext, ctx *web.EventContext) h.HTMLComponent {
comp := in(obj, field, ctx)
formKey := field.ModelInfo.URIName() + "_" + field.FormKey
if p, ok := comp.(TagInterface); ok {
p.SetAttr("ref", formKey)
return h.Div(comp).Attr("v-on-mounted", fmt.Sprintf(`({el,window})=>{
const refName = "%s";
vars.__currentFocusUpdating = false;
el.__handleFocusIn=()=>{
vars.__currentFocusRefName = refName;
};
el.__handleFocusOut=(event)=>{
if(vars.__currentFocusUpdating){return}
vars.__currentFocusRefName ="";
};
el.addEventListener("focusin",el.__handleFocusIn);
el.addEventListener("focusout",el.__handleFocusOut);
}`, formKey)).Attr("v-on-unmounted", `({el})=>{
el.removeEventListener("focusin",el.__handleFocusIn);
el.removeEventListener("focusout",el.__handleFocusOut);
}`).Attr("v-before-unmount", `({el})=>{
vars.__currentFocusUpdating = true;
}`)
}
return comp
}
})
}
}

func (b *ContainerBuilder) Install() {
editing := b.mb.Editing()
editing.WrapIdCurrentActive(func(in presets.IdCurrentActiveProcessor) presets.IdCurrentActiveProcessor {
return func(ctx *web.EventContext, current string) (s string, err error) {
s, err = in(ctx, current)
if err != nil {
Expand All @@ -953,7 +1003,10 @@ func (b *ContainerBuilder) Model(m interface{}) *ContainerBuilder {
return
}
})
b.mb.Editing().AppendHiddenFunc(func(obj interface{}, ctx *web.EventContext) h.HTMLComponent {
if b.builder.autoSaveReload {
b.setFieldsLazyWrapComponentFunc(&editing.FieldsBuilder)
}
editing.AppendHiddenFunc(func(obj interface{}, ctx *web.EventContext) h.HTMLComponent {
if portalName := ctx.Param(presets.ParamPortalName); portalName != pageBuilderRightContentPortal {
return nil
}
Expand All @@ -971,6 +1024,9 @@ func (b *ContainerBuilder) Model(m interface{}) *ContainerBuilder {
const newAddRowBtn = window.document.getElementById(addRowBtnID);
newAddRowBtn.scrollIntoView({ behavior: 'smooth', block: 'end' });
}
const __currentFocusRefName = $refs[vars.__currentFocusRefName];
if(!__currentFocusRefName || typeof __currentFocusRefName.focus != 'function'){return}
__currentFocusRefName.focus();
}`, addRowBtnID)),
web.Listen(
b.mb.NotifRowUpdated(),
Expand All @@ -984,8 +1040,25 @@ func (b *ContainerBuilder) Model(m interface{}) *ContainerBuilder {
Query(paramStatus, ctx.Param(paramStatus)).MergeQuery(true).Go()).
Go(),
),
h.If(b.builder.autoSaveReload,
web.Listen(
b.mb.NotifModelsUpdated(),
web.Plaid().
URL(b.mb.Info().ListingHref()).
EventFunc(actions.Edit).
Query(presets.ParamID, web.Var("payload.ids[0]")).
Query(presets.ParamPortalName, pageBuilderRightContentPortal).
Query(presets.ParamOverlay, actions.Content).Go(),
),
),
)
})
}

func (b *ContainerBuilder) Model(m interface{}) *ContainerBuilder {
b.model = m
b.mb = b.builder.ps.Model(m)

val := reflect.ValueOf(m)
if val.Kind() != reflect.Ptr {
panic("model pointer type required")
Expand Down
8 changes: 5 additions & 3 deletions pagebuilder/editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,15 +275,17 @@ func (b *Builder) Editor(m *ModelBuilder) web.PageFunc {
Attr(":width", "vars.$pbLeftDrawerWidth"),

VNavigationDrawer(
h.Div().Style("display:none").Attr("v-on-mounted", fmt.Sprintf(`({el}) => {
h.Div().Style("display:none").Attr("v-on-mounted", fmt.Sprintf(`({el,window}) => {
el.__handleScroll = (event) => {
locals.__pageBuilderRightContentScrollTop = event.target.scrollTop;
}
el.parentElement.addEventListener('scroll', el.__handleScroll)
locals.__pageBuilderRightContentKeepScroll = () => {
el.parentElement.scrollTop = locals.__pageBuilderRightContentScrollTop;
}
const scrollTop = locals.__pageBuilderRightContentScrollTop;
window.setTimeout(()=>{
el.parentElement.scrollTop = scrollTop;
},0) }
}`)).Attr("v-on-unmounted", `({el}) => {
el.parentElement.removeEventListener('scroll', el.__handleScroll);
}`),
Expand Down
14 changes: 7 additions & 7 deletions pagebuilder/example/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ import (
"net/http"
"path"

"github.com/qor5/admin/v3/pagebuilder"
"github.com/qor5/admin/v3/pagebuilder/example/containers"
"github.com/qor5/admin/v3/richeditor"
"github.com/qor5/x/v3/i18n"
h "github.com/theplant/htmlgo"
"github.com/theplant/osenv"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"

"github.com/qor5/admin/v3/pagebuilder"
"github.com/qor5/admin/v3/pagebuilder/example/containers"
"github.com/qor5/admin/v3/presets"
"github.com/qor5/admin/v3/richeditor"
)

var dbParamsString = osenv.Get("DB_PARAMS", "page builder example database connection string", "")
Expand All @@ -33,7 +34,7 @@ func ConnectDB() (db *gorm.DB) {
//go:embed assets/images
var containerImages embed.FS

func ConfigPageBuilder(db *gorm.DB, prefix, style string, i18nB *i18n.Builder) *pagebuilder.Builder {
func ConfigPageBuilder(db *gorm.DB, prefix, style string, b *presets.Builder) *pagebuilder.Builder {
err := db.AutoMigrate(
&containers.WebHeader{},
&containers.WebFooter{},
Expand All @@ -51,11 +52,10 @@ func ConfigPageBuilder(db *gorm.DB, prefix, style string, i18nB *i18n.Builder) *
if err != nil {
panic(err)
}
pb := pagebuilder.New(prefix, db).AutoMigrate()
pb := pagebuilder.New(prefix, db, b).AutoMigrate().AutoSaveReload(true)
if style != "" {
pb.PageStyle(h.RawHTML(style))
}

richeditor.Plugins = []string{"alignment", "table", "video", "imageinsert"}
pb.GetPresetsBuilder().ExtraAsset("/redactor.js", "text/javascript", richeditor.JSComponentsPack())
pb.GetPresetsBuilder().ExtraAsset("/redactor.css", "text/css", richeditor.CSSComponentsPack())
Expand Down
Loading
Loading