Browse Source

ACE Code Editor and Blog Random-Page Endpoint

master
Noah Petherbridge 7 months ago
parent
commit
4d97fec246
4 changed files with 127 additions and 2 deletions
  1. +16
    -0
      pkg/controllers/posts.go
  2. +16
    -0
      pkg/models/posts.go
  3. +16
    -0
      pkg/rng/rng.go
  4. +79
    -2
      pvt-www/_builtin/blog/edit.gohtml

+ 16
- 0
pkg/controllers/posts.go View File

@@ -41,6 +41,11 @@ func init() {
Methods: []string{"GET"},
Handler: BlogArchive,
})
glue.Register(glue.Endpoint{
Path: "/blog/random",
Methods: []string{"GET"},
Handler: BlogRandom,
})
glue.Register(glue.Endpoint{
Path: "/blog/drafts",
Middleware: []mux.MiddlewareFunc{
@@ -196,6 +201,17 @@ func BlogArchive(w http.ResponseWriter, r *http.Request) {
responses.RenderTemplate(w, r, "_builtin/blog/archive.gohtml", v)
}

// BlogRandom handles the /blog/random route and picks a random post.
func BlogRandom(w http.ResponseWriter, r *http.Request) {
post, err := models.Posts.LoadRandom(models.Public)
if err != nil {
responses.Error(w, r, http.StatusInternalServerError, err.Error())
return
}

responses.Redirect(w, r, "/"+post.Fragment)
}

// EditPost at "/blog/edit"
func EditPost(w http.ResponseWriter, r *http.Request) {
v := responses.NewTemplateVars(w, r)


+ 16
- 0
pkg/models/posts.go View File

@@ -12,6 +12,7 @@ import (

"git.kirsle.net/apps/gophertype/pkg/console"
"git.kirsle.net/apps/gophertype/pkg/markdown"
"git.kirsle.net/apps/gophertype/pkg/rng"
"github.com/albrow/forms"
)

@@ -85,6 +86,21 @@ func (m postMan) LoadFragment(fragment string) (Post, error) {
return post, r.Error
}

// LoadRandom gets a random post for a given privacy setting.
func (m postMan) LoadRandom(privacy string) (Post, error) {
// Find all the post IDs.
var pp []Post
r := DB.Debug().Select("id").Where("privacy = ?", privacy).Find(&pp)
if r.Error != nil || len(pp) == 0 {
return Post{}, r.Error
}

// Pick one at random.
randPost := pp[rng.Intn(len(pp))]
post, err := Posts.Load(randPost.ID)
return post, err
}

// GetIndex returns the index page of blog posts.
func (m postMan) GetIndexPosts(privacy string, page, perPage int) (PagedPosts, error) {
var pp = PagedPosts{


+ 16
- 0
pkg/rng/rng.go View File

@@ -0,0 +1,16 @@
// Package rng provides the random number generator for the app.
package rng

import (
"math/rand"
"time"
)

func init() {
rand.Seed(time.Now().UnixNano())
}

// Intn returns a random number between 0 and n-1.
func Intn(v int) int {
return rand.Intn(v)
}

+ 79
- 2
pvt-www/_builtin/blog/edit.gohtml View File

@@ -15,6 +15,22 @@

{{ $Post := .V.post }}

<style type="text/css" media="screen">
#editor-box {
position: relative;
display: none;
width: 100%;
height: 500px;
}
#ace-editor {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
</style>

<form method="POST" action="/blog/edit">
{{ CSRF }}
<input type="hidden" name="id" value="{{ $Post.ID }}">
@@ -44,17 +60,38 @@
<div class="form-group">
<div class="float-right">
<label>
<input type="radio" name="content-type" value="markdown"{{ if ne $Post.ContentType "html" }} checked{{ end }}>
<input type="radio"
name="content-type"
value="markdown"
onChange="setSyntax(this.value)"
{{ if eq $Post.ContentType "markdown" }}checked{{ end }}
>
Markdown
</label>

<label>
<input type="radio" name="content-type" value="html"{{ if eq $Post.ContentType "html" }} checked{{ end }}>
<input type="radio"
name="content-type"
value="html"
onChange="setSyntax(this.value)"
{{ if eq $Post.ContentType "html" }}checked{{ end }}
>
HTML
</label>
</div>
<label for="body">Body</label>

<div id="editor-box">
<div id="ace-editor">{{ $Post.Body }}</div>
</div>

<textarea class="form-control" cols="40" rows="12" name="body" id="body">{{ $Post.Body }}</textarea>

<div class="mt-2">
<button id="ace-toggle-button" type="button" class="btn btn-sm btn-secondary">
Toggle Rich Code Editor
</button>
</div>
</div>

<div class="form-group">
@@ -141,7 +178,47 @@
</div>
</form>

<!-- ACE Code Editor and helper code -->
<script src="/_builtin/js/ace-toggle.js"></script>
<script src="/_builtin/js/ace-1.4.8/src-min-noconflict/ace.js" charset="utf-8"></script>

<script>
var ACE;
(function() {
console.log("BEGIN: %s", DISABLE_ACE_EDITOR);
if (DISABLE_ACE_EDITOR) return;

let editor = ace.edit("ace-editor");
ACE = editor;
document.querySelector("#editor-box").style.display = "block";
document.querySelector("#body").style.display = "none";

console.log("HERE");

// Default editor settings.
editor.setTheme("ace/theme/monokai");
let ses = editor.getSession();
ses.setTabSize(4);
ses.setUseSoftTabs(false);
ses.setUseWrapMode(true);

// On save.
ses.on("change", () => {
document.querySelector("#body").value = editor.getValue();
});
setSyntax("markdown");
})();

// Set syntax for ACE.
function setSyntax(lang) {
if (typeof(ACE) !== undefined) {
let ses = ACE.getSession();
ses.setMode("ace/mode/"+lang);
ses.setTabSize(lang === "markdown" ? 2 : 4);
}
return false;
}

(function() {
// Image uploader.
let $link = document.querySelector("#attach-img-link");


Loading…
Cancel
Save