github.com/bosssauce/ponzu@v0.11.1-0.20200102001432-9bc41b703131/examples/deleteable/content/song.go (about)

     1  package content
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"net/http"
     8  
     9  	"github.com/ponzu-cms/ponzu/management/editor"
    10  	"github.com/ponzu-cms/ponzu/system/admin/user"
    11  	"github.com/ponzu-cms/ponzu/system/api"
    12  	"github.com/ponzu-cms/ponzu/system/item"
    13  )
    14  
    15  type Song struct {
    16  	item.Item
    17  
    18  	Title      string `json:"title"`
    19  	Artist     string `json:"artist"`
    20  	Rating     int    `json:"rating"`
    21  	Opinion    string `json:"opinion"`
    22  	SpotifyURL string `json:"spotify_url"`
    23  }
    24  
    25  // MarshalEditor writes a buffer of html to edit a Song within the CMS
    26  // and implements editor.Editable
    27  func (s *Song) MarshalEditor() ([]byte, error) {
    28  	view, err := editor.Form(s,
    29  		// Take note that the first argument to these Input-like functions
    30  		// is the string version of each Song field, and must follow
    31  		// this pattern for auto-decoding and auto-encoding reasons:
    32  		editor.Field{
    33  			View: editor.Input("Title", s, map[string]string{
    34  				"label":       "Title",
    35  				"type":        "text",
    36  				"placeholder": "Enter the Title here",
    37  			}),
    38  		},
    39  		editor.Field{
    40  			View: editor.Input("Artist", s, map[string]string{
    41  				"label":       "Artist",
    42  				"type":        "text",
    43  				"placeholder": "Enter the Artist here",
    44  			}),
    45  		},
    46  		editor.Field{
    47  			View: editor.Input("Rating", s, map[string]string{
    48  				"label":       "Rating",
    49  				"type":        "text",
    50  				"placeholder": "Enter the Rating here",
    51  			}),
    52  		},
    53  		editor.Field{
    54  			View: editor.Richtext("Opinion", s, map[string]string{
    55  				"label":       "Opinion",
    56  				"placeholder": "Enter the Opinion here",
    57  			}),
    58  		},
    59  		editor.Field{
    60  			View: editor.Input("SpotifyURL", s, map[string]string{
    61  				"label":       "SpotifyURL",
    62  				"type":        "text",
    63  				"placeholder": "Enter the SpotifyURL here",
    64  			}),
    65  		},
    66  	)
    67  
    68  	if err != nil {
    69  		return nil, fmt.Errorf("Failed to render Song editor view: %s", err.Error())
    70  	}
    71  
    72  	return view, nil
    73  }
    74  
    75  func init() {
    76  	item.Types["Song"] = func() interface{} { return new(Song) }
    77  }
    78  
    79  // String defines the display name of a Song in the CMS list-view
    80  func (s *Song) String() string { return s.Title }
    81  
    82  // BeforeAPIDelete is only called if the Song type implements api.Deleteable
    83  // It is called before Delete, and returning an error will cancel the request
    84  // causing the system to reject the data sent in the POST
    85  func (s *Song) BeforeAPIDelete(res http.ResponseWriter, req *http.Request) error {
    86  	// do initial user authentication here on the request, checking for a
    87  	// token or cookie, or that certain form fields are set and valid
    88  
    89  	// for example, this will check if the request was made by a CMS admin user:
    90  	if !user.IsValid(req) {
    91  		return api.ErrNoAuth
    92  	}
    93  
    94  	// you could then to data validation on the request post form, or do it in
    95  	// the Delete method, which is called after BeforeAPIDelete
    96  
    97  	return nil
    98  }
    99  
   100  // Delete is called after BeforeAPIDelete and implements api.Deleteable. All
   101  // other delete-based hooks are only called if this is implemented.
   102  func (s *Song) Delete(res http.ResponseWriter, req *http.Request) error {
   103  	// See BeforeAPIDelete above, how we have checked the request for some
   104  	// form of auth. This could be done here instead, but if it is done once
   105  	// above, it means the request is valid here too.
   106  	return nil
   107  }
   108  
   109  // AfterAPIDelete is called after Delete, and is useful for logging or triggering
   110  // notifications, etc. after the data is deleted frm the database, etc.
   111  func (s *Song) AfterAPIDelete(res http.ResponseWriter, req *http.Request) error {
   112  	addr := req.RemoteAddr
   113  	log.Println("Song deleted by:", addr, "id:", req.URL.Query().Get("id"))
   114  
   115  	return nil
   116  }