8000 Fix seo by zhangshanwen · Pull Request #594 · qor5/admin · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Fix seo #594

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

Merged
merged 7 commits into from
Sep 24, 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
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,7 @@ func TestPageBuilderCampaign(t *testing.T) {
Query(presets.ParamID, "1_2024-05-20-v01").
Query("section", "Page").
AddField("Page.Title", "123").
AddField("Page.Slug", "/123").
AddField("Page.Slug", "123").
AddField("Page.CategoryID", "2").
BuildEventFuncRequest()
},
Expand All @@ -601,6 +601,10 @@ func TestPageBuilderCampaign(t *testing.T) {
t.Fatalf("Expected Page Title, got %s", cons[0].Title)
return
}
if cons[0].Slug != "/123" {
t.Fatalf("Expected Page Slug, got %s", cons[0].Slug)
return
}
},
},
{
Expand Down
8 changes: 4 additions & 4 deletions docs/docsrc/examples/examples_admin/seo.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ package examples_admin
import (
"net/http"

"gorm.io/gorm"

"github.com/qor5/admin/v3/presets"
"github.com/qor5/admin/v3/presets/gorm2op"
"github.com/qor5/admin/v3/seo"
"gorm.io/gorm"
)

type SEOPost struct {
gorm.Model
Title string
Seo seo.Setting
SEO seo.Setting
}

func SEOExampleBasic(b *presets.Builder, db *gorm.DB) http.Handler {
Expand All @@ -24,8 +25,7 @@ func SEOExampleBasic(b *presets.Builder, db *gorm.DB) http.Handler {
b.DataOperator(gorm2op.DataOperator(db))

mb := b.Model(&SEOPost{})
dp := mb.Detailing("Title", seo.SeoDetailFieldName).Drawer(true)
_ = dp
mb.Detailing("Title", seo.SeoDetailFieldName).Drawer(true)
seob := seo.New(db).AutoMigrate()
seob.RegisterSEO("Post", &SEOPost{}).
RegisterContextVariable(
Expand Down
47 changes: 40 additions & 7 deletions docs/docsrc/examples/examples_admin/seo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@ import (
"net/http/httptest"
"testing"

"github.com/qor5/admin/v3/presets"
"github.com/qor5/web/v3/multipartestutils"
"github.com/theplant/gofixtures"

"github.com/qor5/admin/v3/presets"
"github.com/qor5/admin/v3/presets/actions"
)

var seoData = gofixtures.Data(gofixtures.Sql(`
INSERT INTO public.seo_posts (title, seo, id, created_at, updated_at, deleted_at) VALUES ('The seo post 1',
'{"OpenGraphImageFromMediaLibrary":{"ID":0,"Url":"","VideoLink":"","FileName":"","Description":""}}', 1, '2024-05-31 10:02:13.114089 +00:00', '2024-05-31 10:02:13.114089 +00:00', null);
INSERT INTO public.seo_posts (title, seo, id, created_at, updated_at, deleted_at) VALUES
('The seo post 1',
'{"OpenGraphImageFromMediaLibrary":{"ID":0,"Url":"","VideoLink":"","FileName":"","Description":""}}', 1, '2024-05-31 10:02:13.114089 +00:00', '2024-05-31 10:02:13.114089 +00:00', null),
('The seo post 2',
'{"OpenGraphImageFromMediaLibrary":{"ID":0,"Url":"","VideoLink":"","FileName":"","Description":""},"Title":"123","EnabledCustomize":true,"OpenGraphImageURL":"http://www.text.jpg"}', 2, '2024-05-31 10:02:13.114089 +00:00', '2024-05-31 10:02:13.114089 +00:00', null)
;

`, []string{"seo_posts"}))

Expand All @@ -37,13 +43,40 @@ func TestSEOExampleBasic(t *testing.T) {
seoData.TruncatePut(SqlDB)
req := multipartestutils.NewMultipartBuilder().
PageURL("/seo-posts?__execute_event__=presets_Detailing_Field_Save&section=SEO&id=1").
AddField("Seo.EnabledCustomize", "true").
AddField("Seo.Title", "My seo title").
AddField("SEO.EnabledCustomize", "true").
AddField("SEO.Title", "My seo title").
BuildEventFuncRequest()
return req
},
ExpectPortalUpdate0ContainsInOrder: []string{`My seo title`},
},
{
Name: "SEO Detail With OpenGraphImageURL",
Debug: true,
ReqFunc: func() *http.Request {
seoData.TruncatePut(SqlDB)
req := multipartestutils.NewMultipartBuilder().
PageURL("/seo-posts").
EventFunc(actions.DetailingDrawer).
Query(presets.ParamID, "2").
BuildEventFuncRequest()
return req
},
ExpectPortalUpdate0ContainsInOrder: []string{`<v-img :src=`},
},
{
Name: "SEO Detail Without OpenGraphImageURL",
Debug: true,
ReqFunc: func() *http.Request {
seoData.TruncatePut(SqlDB)
req := multipartestutils.NewMultipartBuilder().
PageURL("/seo-posts").
EventFunc(actions.DetailingDrawer).
Query(presets.ParamID, "1").
BuildEventFuncRequest()
return req
},
// TODO: Not assert correct, should be "My seo title"
ExpectPortalUpdate0ContainsInOrder: []string{`Open Graph Preview`},
ExpectPortalUpdate0NotContains: []string{`<v-img :src=`},
},
}

Expand Down
2 changes: 1 addition & 1 deletion docs/docsrc/examples/examples_presets/listing.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ func PresetsListingCustomizationFilters(b *presets.Builder, db *gorm.DB) (
ItemType: vuetifyx.ItemTypeDatetimeRange,
// SQLCondition: `cast(strftime('%%s', created_at) as INTEGER) %s ?`,
SQLCondition: `created_at %s ?`,
DateOptions: &[]vuetifyx.DateOption{{Label: "Approved_Start_At"}, {Label: "Approved_End_At"}},
DateOptions: &[]vuetifyx.DateOption{{Label: "Approved_Start_At", ClearText: "Cancel1"}, {Label: "Approved_End_At"}},
ValidateFunc: func(ctx *web.EventContext, vErr *web.ValidationErrors, it *vuetifyx.FilterItem) {
if it.ValueFrom >= it.ValueTo {
vErr.GlobalError("ApprovedAt Error")
Expand Down
2 changes: 1 addition & 1 deletion docs/docsrc/examples/examples_presets/listing_test.go
F438
Original file line number Diff line number Diff line change
1E79 Expand Up @@ -121,7 +121,7 @@ func TestPresetsListingCustomizationFilters(t *testing.T) {
ReqFunc: func() *http.Request {
return httptest.NewRequest("GET", "/customers", nil)
},
ExpectPageBodyContainsInOrder: []string{`StartAt`, "EndAt", "Approved_Start_At", "Approved_End_At"},
ExpectPageBodyContainsInOrder: []string{`StartAt`, "EndAt", "Approved_Start_At", "Cancel1", "Approved_End_At"},
},
{
Name: "DateOptions Filter Validate",
Expand Down
15 changes: 8 additions & 7 deletions docs/docsrc/examples/examples_presets/perm_role_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ import (
"testing"
"time"

"github.com/qor5/admin/v3/example/admin"
"github.com/qor5/admin/v3/example/models"
"github.com/qor5/admin/v3/presets"
"github.com/qor5/admin/v3/presets/gorm2op"
"github.com/qor5/admin/v3/role"
"github.com/qor5/web/v3"
"github.com/qor5/web/v3/multipartestutils"
"github.com/qor5/x/v3/login"
Expand All @@ -19,6 +14,12 @@ import (
"github.com/theplant/gofixtures"
h "github.com/theplant/htmlgo"
"gorm.io/gorm"

"github.com/qor5/admin/v3/example/admin"
"github.com/qor5/admin/v3/example/models"
"github.com/qor5/admin/v3/presets"
"github.com/qor5/admin/v3/presets/gorm2op"
"github.com/qor5/admin/v3/role"
)

type customer struct {
Expand Down Expand Up @@ -139,7 +140,7 @@ func TestPermWithoutID(t *testing.T) {
BuildEventFuncRequest()
return req
},
ExpectPortalUpdate0ContainsInOrder: []string{"v-assign='[form, {\"name_section.Name\":\"OldName\"}]' :disabled='false' class='section-field'></v-text-field>"},
ExpectPortalUpdate0ContainsInOrder: []string{"v-assign='[form, {\"name_section.Name\":\"OldName\"}]' :error-messages='null' :disabled='false'></vx-field>"},
},
Role: models.RoleViewer,
},
Expand All @@ -154,7 +155,7 @@ func TestPermWithoutID(t *testing.T) {
BuildEventFuncRequest()
return req
},
ExpectPortalUpdate0ContainsInOrder: []string{"v-assign='[form, {\"name_section.Name\":\"OldName\"}]' :disabled='false' class='section-field'></v-text-field>"},
ExpectPortalUpdate0ContainsInOrder: []string{"v-assign='[form, {\"name_section.Name\":\"OldName\"}]' :error-messages='null' :disabled='false'></vx-field>"},
},
Role: models.RoleEditor,
},
Expand Down
29 changes: 25 additions & 4 deletions example/integration/pagebuilder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ INSERT INTO public.page_builder_pages (id, created_at, updated_at, deleted_at, t
SELECT setval('page_builder_pages_id_seq', 10, true);
INSERT INTO public.container_in_numbers (id, add_top_space, add_bottom_space, anchor_id, heading, items) VALUES (1, false, false, 'test1', '', 'null');
INSERT INTO public.page_builder_demo_containers (id, created_at, updated_at, deleted_at, model_name, model_id, locale_code) VALUES (1, '2024-06-25 02:21:41.014915 +00:00', '2024-06-25 02:21:41.014915 +00:00', null, 'InNumbers', 1, 'International');
`, []string{"page_builder_pages", "page_builder_containers", "container_in_numbers", "page_builder_demo_containers"}))
INSERT INTO public.container_headings (id, add_top_space, add_bottom_space, anchor_id, heading, font_color, background_color, link, link_text, link_display_option, text) VALUES (1, false, false, '', '', '', '', '', '', '', '');
`, []string{"page_builder_pages", "page_builder_containers", "container_in_numbers", "page_builder_demo_containers", "container_headings"}))

func TestPageBuilder(t *testing.T) {
h := admin.TestHandler(TestDB, nil)
Expand Down Expand Up @@ -602,7 +603,7 @@ func TestPageBuilder(t *testing.T) {
Query(presets.ParamID, "10_2024-05-21-v01_International").
Query("section", "Page").
AddField("Page.Title", "123").
AddField("Page.Slug", "/123").
AddField("Page.Slug", "123").
AddField("Page.CategoryID", "0").
BuildEventFuncRequest()
},
Expand All @@ -617,6 +618,10 @@ func TestPageBuilder(t *testing.T) {
t.Fatalf("Expected Page Title, got %s", cons[0].Title)
return
}
if cons[0].Slug != "/123" {
t.Fatalf("Expected Page Slug, got %s", cons[0].Slug)
return
}
},
},
{
Expand Down Expand Up @@ -660,7 +665,7 @@ func TestPageBuilder(t *testing.T) {
BuildEventFuncRequest()
return req
},
ExpectPortalUpdate0ContainsInOrder: []string{`"Page.CategoryID":""`},
ExpectPortalUpdate0ContainsInOrder: []string{`"CategoryID":""`},
},
{
Name: "Page Detail Editing Has Category",
Expand All @@ -675,7 +680,7 @@ func TestPageBuilder(t *testing.T) {
BuildEventFuncRequest()
return req
},
ExpectPortalUpdate0ContainsInOrder: []string{`"Page.CategoryID":1`},
ExpectPortalUpdate0ContainsInOrder: []string{`"CategoryID":1`},
},

{
Expand Down Expand Up @@ -818,6 +823,22 @@ func TestPageBuilder(t *testing.T) {
}
},
},
{
Name: "Container Heading Update Validate",
Debug: true,
ReqFunc: func() *http.Request {
pageBuilderDemoContainerTestData.TruncatePut(dbr)
req := NewMultipartBuilder().
PageURL("/page_builder/headings").
EventFunc(actions.Update).
Query(presets.ParamID, "1").
AddField("FontColor", "blue").
BuildEventFuncRequest()

return req
},
ExpectPortalUpdate0ContainsInOrder: []string{"blue", "LinkText 不能为空"},
},
}

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 @@ -27,7 +27,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.8
github.com/qor5/x/v3 v3.0.10-0.20240923055518-106596f5c644
github.com/qor5/x/v3 v3.0.10-0.20240924033603-390b10c33399
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 @@ -323,6 +323,8 @@ github.com/qor5/x/v3 v3.0.10-0.20240923031926-4715a7497269 h1:4CS1Fug99k+kyjfULt
github.com/qor5/x/v3 v3.0.10-0.20240923031926-4715a7497269/go.mod h1:ebg7TORMQLVRlZyDyZbAsxbQoiN4wMBVhyFHdYxv6Tw=
github.com/qor5/x/v3 v3.0.10-0.20240923055518-106596f5c644 h1:J0E/cE5nLtS4/tR9o+eHlww6wvCsxfaS0Tb4Nv024ZU=
github.com/qor5/x/v3 v3.0.10-0.20240923055518-106596f5c644/go.mod h1:ebg7TORMQLVRlZyDyZbAsxbQoiN4wMBVhyFHdYxv6Tw=
github.com/qor5/x/v3 v3.0.10-0.20240924033603-390b10c33399 h1:+wBQnLFUwkC5UHLXNgJNQwVPLxHBn4iWi01DVuBPC04=
github.com/qor5/x/v3 v3.0.10-0.20240924033603-390b10c33399/go.mod h1:ebg7TORMQLVRlZyDyZbAsxbQoiN4wMBVhyFHdYxv6Tw=
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
5 changes: 4 additions & 1 deletion pagebuilder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,10 @@ func (b *ContainerBuilder) Model(m interface{}) *ContainerBuilder {
URL(b.mb.Info().ListingHref()).
EventFunc(actions.Update).
Query(presets.ParamID, web.Var("payload.id")).
ThenScript(web.Plaid().EventFunc(ReloadRenderPageOrTemplateEvent).Query(paramStatus, ctx.Param(paramStatus)).MergeQuery(true).Go()).
Query(presets.ParamPortalName, pageBuilderRightContentPortal).
Query(presets.ParamOverlay, actions.Content).
ThenScript(web.Plaid().EventFunc(ReloadRenderPageOrTemplateEvent).
Query(paramStatus, ctx.Param(paramStatus)).MergeQuery(true).Go()).
Go(),
),
)
Expand Down
16 changes: 13 additions & 3 deletions pagebuilder/example/containers/heading.go
BE96
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package containers

import (
"github.com/qor5/admin/v3/pagebuilder"
"github.com/qor5/admin/v3/presets"
"github.com/qor5/admin/v3/richeditor"
"github.com/qor5/web/v3"
"github.com/qor5/x/v3/ui/vuetify"
. "github.com/theplant/htmlgo"
"gorm.io/gorm"

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

const (
Expand Down Expand Up @@ -46,6 +47,15 @@ func RegisterHeadingContainer(pb *pagebuilder.Builder, db *gorm.DB) {
ed.Field("Text").ComponentFunc(func(obj interface{}, field *presets.FieldContext, ctx *web.EventContext) HTMLComponent {
return richeditor.RichEditor(db, "Text").Plugins([]string{"alignment", "video", "imageinsert", "fontcolor"}).Value(obj.(*Heading).Text).Label(field.Label)
})
ed.ValidateFunc(func(obj interface{}, ctx *web.EventContext) (err web.ValidationErrors) {
p := obj.(*Heading)
if p.ID != 0 {
if p.LinkText == "" {
err.FieldError("LinkText", "LinkText 不能为空")
}
}
return
})

ed.Field("FontColor").ComponentFunc(func(obj interface{}, field *presets.FieldContext, ctx *web.EventContext) HTMLComponent {
return vuetify.VSelect().
Expand Down
31 changes: 16 additions & 15 deletions pagebuilder/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@

"github.com/qor5/x/v3/i18n"

"github.com/qor5/admin/v3/l10n"
"github.com/qor5/web/v3"
"gorm.io/gorm"

"github.com/qor5/admin/v3/l10n"
)

var directoryRe = regexp.MustCompile(`^([\/]{1}[a-zA-Z0-9._-]+)+(\/?){1}$|^([\/]{1})$`)
Expand Down Expand Up @@ -38,14 +39,14 @@
msgr := i18n.MustGetModuleMessages(ctx.R, I18nPageBuilderKey, Messages_en_US).(*Messages)

if p.Title == "" {
err.FieldError("Page.Title", msgr.InvalidTitleMsg)
err.FieldError("Title", msgr.InvalidTitleMsg)
return
}

if p.Slug != "" {
pagePath := path.Clean(p.Slug)
if !directoryRe.MatchString(pagePath) {
err.FieldError("Page.Slug", msgr.InvalidSlugMsg)
err.FieldError("Slug", msgr.InvalidSlugMsg)

Check warning on line 49 in pagebuilder/helper.go

View check run for this annotation

Codecov / codecov/patch

pagebuilder/helper.go#L49

Added line #L49 was not covered by tests
return
}
}
Expand All @@ -62,21 +63,21 @@
currentPagePublishUrl := p.getPublishUrl(localePath, currentPageCategory.Path)

var pagePathInfos []pagePathInfo
if err := db.Raw(queryLocaleCodeCategoryPathSlugSQL).Scan(&pagePathInfos).Error; err != nil {
panic(err)
if dbErr := db.Raw(queryLocaleCodeCategoryPathSlugSQL).Scan(&pagePathInfos).Error; dbErr != nil {
panic(dbErr)

Check warning on line 67 in pagebuilder/helper.go

View check run for this annotation

Codecov / codecov/patch

pagebuilder/helper.go#L67

Added line #L67 was not covered by tests
}

for _, info := range pagePathInfos {
if info.ID == p.ID && info.LocaleCode == p.LocaleCode {
continue
}
var localePath string
var innerLocalePath string
if l10nB != nil {
localePath = l10nB.GetLocalePath(info.LocaleCode)
innerLocalePath = l10nB.GetLocalePath(info.LocaleCode)
}

if generatePublishUrl(localePath, info.CategoryPath, info.Slug) == currentPagePublishUrl {
err.FieldError("Page.Slug", msgr.ConflictSlugMsg)
if generatePublishUrl(innerLocalePath, info.CategoryPath, info.Slug) == currentPagePublishUrl {
err.FieldError("Slug", msgr.ConflictSlugMsg)
return
}
}
Expand Down Expand Up @@ -104,20 +105,20 @@

currentCategoryPathPublishUrl := generatePublishUrl(localePath, categoryPath, "")

categories := []*Category{}
if err := db.Model(&Category{}).Find(&categories).Error; err != nil {
panic(err)
var categories []*Category
if dbErr := db.Model(&Category{}).Find(&categories).Error; dbErr != nil {
panic(dbErr)

Check warning on line 110 in pagebuilder/helper.go

View check run for this annotation

Codecov / codecov/patch

pagebuilder/helper.go#L110

Added line #L110 was not covered by tests
}

for _, c := range categories {
if c.ID == category.ID && c.LocaleCode == category.LocaleCode {
continue
}
var localePath string
var innerLocalePath string
if l10nB != nil {
localePath = l10nB.GetLocalePath(c.LocaleCode)
innerLocalePath = l10nB.GetLocalePath(c.LocaleCode)

Check warning on line 119 in pagebuilder/helper.go

View check run for this annotation

Codecov / codecov/patch

pagebuilder/helper.go#L119

Added line #L119 was not covered by tests
}
if generatePublishUrl(localePath, c.Path, "") == currentCategoryPathPublishUrl {
if generatePublishUrl(innerLocalePath, c.Path, "") == currentCategoryPathPublishUrl {
err.FieldError("Category.Category", msgr.ExistingPathMsg)
return
}
Expand Down
Loading
Loading
0