ACE Code Editor and Blog Random-Page Endpoint
This commit is contained in:
parent
b642562792
commit
4d97fec246
|
@ -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)
|
||||
|
|
|
@ -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
pkg/rng/rng.go
Normal file
16
pkg/rng/rng.go
Normal 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)
|
||||
}
|
|
@ -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…
Reference in New Issue
Block a user