// Package editor enables users to create edit views from their content // structs so that admins can manage content package editor import ( "bytes" "log" "net/http" ) // Editable ensures data is editable type Editable interface { MarshalEditor() ([]byte, error) } // Mergeable allows external post content to be approved and published through // the public-facing API type Mergeable interface { // Approve copies an external post to the internal collection and triggers // a re-sort of its content type posts Approve(http.ResponseWriter, *http.Request) error } // Editor is a view containing fields to manage content type Editor struct { ViewBuf *bytes.Buffer } // Field is used to create the editable view for a field // within a particular content struct type Field struct { View []byte } // Form takes editable content and any number of Field funcs to describe the edit // page for any content struct added by a user func Form(post Editable, fields ...Field) ([]byte, error) { editor := &Editor{} editor.ViewBuf = &bytes.Buffer{} _, err := editor.ViewBuf.WriteString(``) if err != nil { log.Println("Error writing HTML string to editor Form buffer") return nil, err } // content items with Item embedded have some default fields we need to render _, err = editor.ViewBuf.WriteString(`
`) if err != nil { log.Println("Error writing HTML string to editor Form buffer") return nil, err } for _, f := range fields { addFieldToEditorView(editor, f) } _, err = editor.ViewBuf.WriteString(`
`) if err != nil { log.Println("Error writing HTML string to editor Form buffer") return nil, err } publishTime := `
:
` _, err = editor.ViewBuf.WriteString(publishTime) if err != nil { log.Println("Error writing HTML string to editor Form buffer") return nil, err } err = addPostDefaultFieldsToEditorView(post, editor) if err != nil { return nil, err } submit := `
` _, ok := post.(Mergeable) if ok { submit += `
` } script := ` ` _, err = editor.ViewBuf.WriteString(submit + script + `
`) if err != nil { log.Println("Error writing HTML string to editor Form buffer") return nil, err } return editor.ViewBuf.Bytes(), nil } func addFieldToEditorView(e *Editor, f Field) error { _, err := e.ViewBuf.Write(f.View) if err != nil { log.Println("Error writing field view to editor view buffer") return err } return nil } func addPostDefaultFieldsToEditorView(p Editable, e *Editor) error { defaults := []Field{ { View: Input("Slug", p, map[string]string{ "label": "URL Slug", "type": "text", "disabled": "true", "placeholder": "Will be set automatically", }), }, { View: Timestamp("Timestamp", p, map[string]string{ "type": "hidden", "class": "timestamp __ponzu", }), }, { View: Timestamp("Updated", p, map[string]string{ "type": "hidden", "class": "updated __ponzu", }), }, } for _, f := range defaults { err := addFieldToEditorView(e, f) if err != nil { return err } } return nil }