package app import ( "fmt" "html/template" "net/http" "strconv" ) func getDocumentURL(documentID int64) string { return fmt.Sprintf("/d/%s", encodeIDToBase36(documentID)) } func getDocumentEditURL(documentID int64) string { if documentID == 0 { return "/d/new" } return fmt.Sprintf("/d/%s/edit", encodeIDToBase36(documentID)) } func getDocumentDeleteURL(documentID int64) string { return fmt.Sprintf("/d/%s/delete", encodeIDToBase36(documentID)) } func formSubmitSaveDocument(w http.ResponseWriter, r *http.Request, form *Form) error { documentID := int64(0) field := form.GetFieldByName("id") if field != nil { documentID, _ = strconv.ParseInt(field.GetStringValue(), 10, 64) } document := DocumentRecord{} if documentID > 0 { var err error document, err = fetchDocumentRecordByID(db, documentID) if err != nil { return err } } document.CreatedBy = getUserID(r) field = form.GetFieldByName("title") if field != nil { document.Title = field.GetStringValue() } field = form.GetFieldByName("content") if field != nil { document.Content = field.GetStringValue() } if err := updateDocumentsRecord(db, &document); err != nil { return err } http.Redirect(w, r, getDocumentURL(document.ID), http.StatusFound) return nil } func httpHandleEditDocument(w http.ResponseWriter, r *http.Request, documentID int64) { // fetch existing document record document := DocumentRecord{} if documentID > 0 { var err error document, err = fetchDocumentRecordByID(db, documentID) if err != nil { httpHandleError(w, err) return } } // no permission to edit if documentID > 0 && document.CreatedBy != getUserID(r) { httpHandleError(w, errAuthError) return } // render form form := Form{ Name: "document", Title: "Document Editor", Fields: []*FormField{ {ID: "id", Type: "hidden", Values: []string{fmt.Sprintf("%d", documentID)}}, {ID: "title", Type: "text", Label: "Title", Required: true, Values: []string{document.Title}}, {ID: "content", Type: "textarea", Label: "Content", Description: "Supports Markdown and strategy board codes.", Required: true, Values: []string{document.Content}}, }, SubmitHandlers: []string{"save_document"}, } if _, err := form.Submit(w, r); err != nil { httpHandleError(w, err) return } form.Render(w, r) } func httpHandleViewDocument(w http.ResponseWriter, r *http.Request, documentID int64) { // fetch existing document record document, err := fetchDocumentRecordByID(db, documentID) if err != nil { httpHandleError(w, err) return } // inject strategy boards in to document markdown userID := getUserID(r) markdown, err := markdownInjectStrategyBoard([]byte(document.Content), userID) if err != nil { httpHandleError(w, err) return } // render recordDetails, err := fetchRecordDetails(DocumentRecord{}, documentID) if err != nil { httpHandleError(w, err) return } recordOptions := [][]string{} if document.CreatedBy == userID { recordOptions = [][]string{{"Edit", getDocumentEditURL(documentID)}, {"Delete", getDocumentDeleteURL(documentID)}} } content := markdownToHTML(markdown) httpHandleTemplate(w, "document.html", map[string]any{ "title": document.Title, "content": template.HTML(content), "canEdit": document.CreatedBy == userID, "editURL": getDocumentEditURL(document.ID), "recordDetails": recordDetails, "recordOptions": recordOptions, }) } /* Handle document path. */ func httpBaseHandleDocument(w http.ResponseWriter, r *http.Request, path []string) bool { if path[0] == "d" || path[0] == "doc" { if len(path) < 2 { httpHandleError(w, errHttpNotFound) return true } if path[1] == "new" { httpHandleEditDocument(w, r, 0) return true } documentID := getIDFromBase36(path[1]) if documentID == 0 { httpHandleError(w, errHttpNotFound) return true } if len(path) > 2 && path[2] == "edit" { httpHandleEditDocument(w, r, documentID) return true } if len(path) > 2 && path[2] == "delete" { httpHandleRecordDelete(w, r, DocumentRecord{}, documentID) return true } httpHandleViewDocument(w, r, documentID) return true } return false }