A web blog and personal homepage engine written in Go.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

278 lines
7.5 KiB

{{ define "title" }}Update Blog{{ end }}
{{ define "content" }}
<h1>Update Blog</h1>
{{ if .V.preview }}
<div class="card mb-4">
<div class="card-header">
Preview
</div>
<div class="card-body">
{{ .V.preview }}
</div>
</div>
{{ end }}
{{ $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 }}">
<div class="card mb-4">
<div class="card-body">
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control"
name="title" id="title"
value="{{ $Post.Title }}"
placeholder="Subject">
</div>
<div class="form-group">
<label for="fragment">URL Fragment</label>
<input type="text" class="form-control"
name="fragment" id="fragment"
aria-describedby="fragment-help"
value="{{ $Post.Fragment }}"
placeholder="url-fragment-for-blog-entry">
<small id="fragment-help" class="form-text text-muted">
You can leave this blank if writing a new post; it will automatically
get a unique fragment based on the post title.
</small>
</div>
<div class="form-group">
<div class="float-right">
<label>
<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"
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">
<label>Attach Image</label><br>
<a href="#" id="attach-img-link">+ Upload</a>
<div id="attach-img-form" style="display: none; border: 1px dashed #333; padding: 1rem">
File: <input type="file" class="form-control" id="attach-img-file"><br>
Filename: <input type="text" class="form-control" id="attach-img-filename"><br>
<button type="button" class="btn btn-primary" id="attach-img-button">Upload</button>
</div>
</div>
<div class="form-group">
<label for="tags">Tags</label>
<input type="text" class="form-control"
name="tags" id="tags"
value="{{ $Post.TagsString }}"
placeholder="comma, separated, list">
</div>
<div class="form-group">
<label for="privacy">Privacy</label>
<select class="form-control"
name="privacy" id="privacy">
<option value="public"{{ if eq $Post.Privacy "public" }} selected{{ end }}>
Public: everyone can see this post</option>
<option value="private"{{ if eq $Post.Privacy "private" }} selected{{ end }}>
Private: only logged-in users can see this post</option>
<option value="unlisted"{{ if eq $Post.Privacy "unlisted" }} selected{{ end }}>
Unlisted: only logged-in users and those with the direct link can see this post</option>
<option value="draft"{{ if eq $Post.Privacy "draft" }} selected{{ end }}>
Draft: only you can see this post</option>
</select>
</div>
<div class="form-group">
<label>Options</label>
</div>
<div class="form-check">
<input type="checkbox" class="form-input-check"
name="sticky" id="sticky"
value="true"
{{ if $Post.Sticky }} checked{{ end }}>
<label class="check-form-label" for="sticky">
Make this post sticky (always on top)
</label>
</div>
<div class="form-check">
<input type="checkbox" class="form-input-check"
name="enable-comments" id="enable-comments"
value="true"
{{ if $Post.EnableComments }} checked{{ end }}>
<label class="check-form-label" for="enable-comments">
Enable comments on this post
</label>
</div>
{{ if not .V.isNew }}
<div class="form-check">
<input type="checkbox" class="form-input-check"
name="no-update" id="no-update"
value="true"
{{ if eq (FormValue "no-update") "true" }} checked{{ end }}>
<label class="check-form-label" for="no-update">
<strong>Editing:</strong> do not update the "modified time" of this post.
</label>
</div>
{{ end }}
<div class="form-group">
<button type="submit" class="btn btn-success"
name="submit" value="preview">
Preview
</button>
<button type="submit" class="btn btn-primary"
name="submit" value="post">
Publish
</button>
</div>
</div>
</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");
let $form = document.querySelector("#attach-img-form");
let $file = document.querySelector("#attach-img-file");
let $filename = document.querySelector("#attach-img-filename");
let $button = document.querySelector("#attach-img-button");
$link.addEventListener("click", (e) => {
e.preventDefault();
$form.style.display = "block";
$link.style.display = "none";
});
$file.addEventListener("change", (e) => {
let file = $file.files[0];
console.log(file);
$filename.value = file.name;
});
$button.addEventListener("click", (e) => {
let syntax = document.querySelector("input[name='content-type']:checked").value;
let file = $file.files[0];
var data = new FormData();
data.append("type", "image");
data.append("file", file);
data.append("filename", $filename.value);
data.append("_csrf", "{{ CSRFToken }}");
fetch("/admin/upload", {
method: "POST",
body: data,
credentials: "same-origin",
cache: "no-cache"
}).then(resp => resp.json()).then(resp => {
if (!resp.success) {
window.alert(resp.error);
return;
}
let filename = resp.filename;
let uri = resp.uri;
let insert = `![${filename}](${uri})\n`;
if (syntax === "html") {
insert = `<img alt="${filename}" src="${uri}" class="portrait">\n`;
}
document.querySelector("#body").value += insert;
$file.value = "";
$filename.value = "";
$form.style.display = "none";
$link.style.display = "inline";
});
});
})();
</script>
{{ end }}