123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- package slug
- import (
- "fmt"
- "reflect"
- "regexp"
- "strings"
- syncp "sync"
- . "github.com/qor5/ui/vuetify"
- "github.com/qor5/web"
- "github.com/qor5/x/i18n"
- "github.com/qor5/admin/presets"
- "github.com/gosimple/unidecode"
- "github.com/sunfmin/reflectutils"
- h "github.com/theplant/htmlgo"
- "golang.org/x/text/language"
- )
- type Slug string
- const (
- syncEvent = "slug_sync"
- I18nSlugKey i18n.ModuleKey = "I18nSlugKey"
- )
- var once = syncp.Once{}
- func Configure(b *presets.Builder, mb *presets.ModelBuilder) {
- once.Do(func() {
- b.I18n().
- RegisterForModule(language.English, I18nSlugKey, Messages_en_US).
- RegisterForModule(language.SimplifiedChinese, I18nSlugKey, Messages_zh_CN)
- b.GetWebBuilder().RegisterEventFunc(syncEvent, sync)
- })
- reflectType := reflect.Indirect(reflect.ValueOf(mb.NewModel())).Type()
- if reflectType.Kind() != reflect.Struct {
- panic("slug: model must be struct")
- }
- for i := 0; i < reflectType.NumField(); i++ {
- if reflectType.Field(i).Type != reflect.TypeOf(Slug("")) {
- continue
- }
- fieldName := reflectType.Field(i).Name
- relatedFieldName := strings.TrimSuffix(fieldName, "WithSlug")
- if _, ok := reflectType.FieldByName(relatedFieldName); ok {
- editingBuilder := mb.Editing()
- if f := editingBuilder.Field(relatedFieldName); f != nil {
- f.ComponentFunc(SlugEditingComponentFunc)
- }
- editingBuilder.Field(fieldName).ComponentFunc(func(obj interface{}, field *presets.FieldContext, ctx *web.EventContext) (r h.HTMLComponent) { return })
- editingBuilder.Field(fieldName).SetterFunc(SlugEditingSetterFunc)
- }
- }
- }
- func SlugEditingComponentFunc(obj interface{}, field *presets.FieldContext, ctx *web.EventContext) h.HTMLComponent {
- msgr := i18n.MustGetModuleMessages(ctx.R, I18nSlugKey, Messages_en_US).(*Messages)
- slugFieldName := field.Name + "WithSlug"
- slugLabel := field.Label + " Slug"
- return VSheet(
- VTextField().
- Type("text").
- FieldName(field.Name).
- Label(field.Label).
- Value(field.Value(obj)).
- Attr("v-debounce:input", "300").
- Attr("@input:debounced", web.Plaid().
- EventFunc(syncEvent).Query("field_name", field.Name).Query("slug_label", slugLabel).Go()),
- VRow(
- VCol(
- web.Portal(
- VTextField().
- Type("text").
- FieldName(slugFieldName).
- Label(slugLabel).
- Value(reflectutils.MustGet(obj, slugFieldName).(Slug))).Name(portalName(slugFieldName)),
- ).Cols(8),
- VCol(
- VCheckbox().FieldName(checkBoxName(slugFieldName)).InputValue("checked").Label(fmt.Sprintf(msgr.Sync, strings.ToLower(field.Label))),
- ).Cols(4),
- ),
- )
- }
- func SlugEditingSetterFunc(obj interface{}, field *presets.FieldContext, ctx *web.EventContext) (err error) {
- v := ctx.R.FormValue(field.Name)
- err = reflectutils.Set(obj, field.Name, Slug(v))
- if err != nil {
- return
- }
- return
- }
- func sync(ctx *web.EventContext) (r web.EventResponse, err error) {
- fieldName := ctx.R.FormValue("field_name")
- if fieldName == "" {
- return
- }
- slugFieldName := fieldName + "WithSlug"
- if checked := ctx.R.FormValue(checkBoxName(slugFieldName)); checked != "checked" {
- return
- }
- r.UpdatePortals = append(r.UpdatePortals, &web.PortalUpdate{
- Name: portalName(slugFieldName),
- Body: VTextField().
- Type("text").
- FieldName(slugFieldName).
- Label(ctx.R.FormValue("slug_label")).
- Value(slug(ctx.R.FormValue(fieldName))),
- })
- return
- }
- var (
- regexpNonAuthorizedChars = regexp.MustCompile("[^a-zA-Z0-9-_]")
- regexpMultipleDashes = regexp.MustCompile("-+")
- )
- func slug(value string) string {
- value = strings.TrimSpace(value)
- value = unidecode.Unidecode(value)
- value = strings.ToLower(value)
- value = regexpNonAuthorizedChars.ReplaceAllString(value, "-")
- value = regexpMultipleDashes.ReplaceAllString(value, "-")
- value = strings.Trim(value, "-_")
- return value
- }
- func portalName(field string) string {
- return fmt.Sprintf("%s_Portal", field)
- }
- func checkBoxName(field string) string {
- return fmt.Sprintf("%s_Checkbox", field)
- }
|