Skip to content

Commit 0e5cc55

Browse files
authored
Merge pull request #303 from compscidr/jason/admin-updates
Split admin into a couple of sections
2 parents 4c263de + a33f0ed commit 0e5cc55

File tree

8 files changed

+401
-1
lines changed

8 files changed

+401
-1
lines changed

admin/admin.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,42 @@ func (a Admin) Admin(c *gin.Context) {
223223
})
224224
}
225225

226+
func (a Admin) AdminDashboard(c *gin.Context) {
227+
c.HTML(http.StatusOK, "admin_dashboard.html", gin.H{
228+
"posts": a.b.GetPosts(true),
229+
"logged_in": a.auth.IsLoggedIn(c),
230+
"is_admin": a.auth.IsAdmin(c),
231+
"version": a.version,
232+
})
233+
}
234+
235+
func (a Admin) AdminPosts(c *gin.Context) {
236+
c.HTML(http.StatusOK, "admin_all_posts.html", gin.H{
237+
"posts": a.b.GetPosts(true),
238+
"logged_in": a.auth.IsLoggedIn(c),
239+
"is_admin": a.auth.IsAdmin(c),
240+
"version": a.version,
241+
})
242+
}
243+
244+
func (a Admin) AdminNewPost(c *gin.Context) {
245+
c.HTML(http.StatusOK, "admin_new_post.html", gin.H{
246+
"posts": a.b.GetPosts(true),
247+
"logged_in": a.auth.IsLoggedIn(c),
248+
"is_admin": a.auth.IsAdmin(c),
249+
"version": a.version,
250+
})
251+
}
252+
253+
func (a Admin) AdminSettings(c *gin.Context) {
254+
c.HTML(http.StatusOK, "admin_settings.html", gin.H{
255+
"posts": a.b.GetPosts(true),
256+
"logged_in": a.auth.IsLoggedIn(c),
257+
"is_admin": a.auth.IsAdmin(c),
258+
"version": a.version,
259+
})
260+
}
261+
226262
func (a Admin) Post(c *gin.Context) {
227263
if !a.auth.IsAdmin(c) {
228264
log.Println("IS ADMIN RETURNED FALSE")

admin/admin_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,12 @@ func TestCreatePost(t *testing.T) {
5555
router.PATCH("/api/v1/posts", ad.UpdatePost)
5656
router.DELETE("/api/v1/posts", ad.DeletePost)
5757
router.POST("/api/v1/upload", ad.UploadFile)
58+
5859
router.GET("/admin", ad.Admin)
60+
router.GET("/admin/dashboard", ad.AdminDashboard)
61+
router.GET("/admin/posts", ad.AdminPosts)
62+
router.GET("/admin/newpost", ad.AdminNewPost)
63+
router.GET("/admin/settings", ad.AdminSettings)
5964

6065
//improper content-type
6166
testPost := blog.Post{

goblog.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func main() {
7070
setup_wizard()
7171
err := godotenv.Load(".env")
7272
if err != nil {
73-
log.Println("Failed to read the .env file after the wizard, can't procced")
73+
log.Println("Failed to read the .env file after the wizard, can't proceed")
7474
return
7575
}
7676
}
@@ -174,6 +174,10 @@ func main() {
174174
router.Use(static.Serve("/wp-content", static.LocalFile("www", false)))
175175

176176
router.GET("/admin", _admin.Admin)
177+
router.GET("/admin/dashboard", _admin.AdminDashboard)
178+
router.GET("/admin/posts", _admin.AdminPosts)
179+
router.GET("/admin/newpost", _admin.AdminNewPost)
180+
router.GET("/admin/settings", _admin.AdminSettings)
177181

178182
router.NoRoute(_blog.NoRoute)
179183

templates/admin.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@
3838
</script>
3939

4040
<div class="container">
41+
<div class="nav-scroller bg-body shadow-sm">
42+
43+
<!-- https://getbootstrap.com/docs/5.0/examples/offcanvas-navbar/ -->
44+
<nav class="nav nav-underline" aria-label="Secondary navigation">
45+
<a class="nav-link" href="/admin/dashboard">Dashboard</a>
46+
<a class="nav-link active" aria-current="page" href="/admin/posts">All Posts</a>
47+
<a class="nav-link" href="/admin/newpost">New Post</a>
48+
<a class="nav-link" href="/admin/settings">Settings</a>
49+
</nav>
50+
</div>
4151
<h1>All Posts</h1>
4252
<!-- <ul class="admin-posts"> -->
4353
<table>

templates/admin_all_posts.html

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
{{ template "header.html" .}}
2+
<script type="text/javascript">
3+
4+
function createPost(publish) {
5+
var tags = $("#tags").val().split(',')
6+
for (var i = 0; i < tags.length; i++) {
7+
tags[i] = {"name": tags[i].trim()}
8+
}
9+
10+
var time = $("#created_at").val();
11+
var vtime = moment.utc(time)
12+
13+
var post = {
14+
"title": $("#title").val(),
15+
"created_at": vtime,
16+
"content": simplemde.value(),
17+
"tags": tags,
18+
"draft": !publish,
19+
}
20+
console.log("POST: " + JSON.stringify(post));
21+
22+
$.ajax({
23+
url: "/api/v1/posts",
24+
type: "post",
25+
dataType: "json",
26+
contentType: "application/json",
27+
success: function(json) {
28+
var time = moment(json.created_at);
29+
var slug = json.slug;
30+
window.location.href="/posts/" + time.format("YYYY/MM/DD") + "/" + slug;
31+
},
32+
error: function(jqXHR, textStatus, errorThrown) {
33+
alert("ERROR: " + textStatus + " " + errorThrown);
34+
},
35+
data: JSON.stringify(post)
36+
});
37+
}
38+
</script>
39+
40+
<div class="container">
41+
<div class="nav-scroller bg-body shadow-sm">
42+
43+
<!-- https://getbootstrap.com/docs/5.0/examples/offcanvas-navbar/ -->
44+
<nav class="nav nav-underline" aria-label="Secondary navigation">
45+
<a class="nav-link" href="/admin/dashboard">Dashboard</a>
46+
<a class="nav-link active" aria-current="page" href="/admin/posts">All Posts</a>
47+
<a class="nav-link" href="/admin/newpost">New Post</a>
48+
<a class="nav-link" href="/admin/settings">Settings</a>
49+
</nav>
50+
</div>
51+
<h1>All Posts</h1>
52+
<!-- <ul class="admin-posts"> -->
53+
<table>
54+
{{ range .posts }}
55+
<tr class="striped--light-gray">
56+
<!-- <li> -->
57+
<td><a href="{{ .Permalink }}" title="{{ .Title }}">{{ .Title }}</a></td>
58+
<td>{{ .CreatedAt.Format "01/02/06" }}</td>
59+
<td>{{ range .Tags }}
60+
<a href="{{ .Permalink }}" title="{{ .Name}}">#{{ .Name }}</a>
61+
{{ end }}
62+
</td>
63+
<!-- </li> -->
64+
</tr>
65+
{{ end }}
66+
</table>
67+
<!--</ul>-->
68+
69+
</div> <!-- / container -->
70+
71+
<script>
72+
var simplemde = new SimpleMDE({ element: $("#content")[0] });
73+
74+
//https://github.com/sparksuite/simplemde-markdown-editor/issues/328
75+
inlineAttachment.editors.codemirror4.attach(simplemde.codemirror, {
76+
uploadUrl: "/api/v1/upload",
77+
onFileUploadResponse: function(xhr) {
78+
var result = JSON.parse(xhr.responseText);
79+
console.log(result);
80+
filename = result[this.settings.jsonFieldName];
81+
console.log(filename);
82+
console.log(this.filenameTag);
83+
if (result && filename) {
84+
var newValue;
85+
if (typeof this.settings.urlText === 'function') {
86+
newValue = this.settings.urlText.call(this, filename, result);
87+
} else {
88+
newValue = this.settings.urlText.replace(this.filenameTag, filename);
89+
}
90+
var text = this.editor.getValue().replace(this.lastValue, newValue);
91+
this.editor.setValue(text);
92+
this.settings.onFileUploaded.call(this, filename);
93+
}
94+
return false;
95+
}
96+
});
97+
98+
$(function () {
99+
$('#datetimepicker1').datetimepicker({timezone: "UTC"});
100+
});
101+
</script>
102+
103+
{{ template "footer.html" .}}

templates/admin_dashboard.html

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{{ template "header.html" .}}
2+
<script type="text/javascript">
3+
4+
function createPost(publish) {
5+
var tags = $("#tags").val().split(',')
6+
for (var i = 0; i < tags.length; i++) {
7+
tags[i] = {"name": tags[i].trim()}
8+
}
9+
10+
var time = $("#created_at").val();
11+
var vtime = moment.utc(time)
12+
13+
var post = {
14+
"title": $("#title").val(),
15+
"created_at": vtime,
16+
"content": simplemde.value(),
17+
"tags": tags,
18+
"draft": !publish,
19+
}
20+
console.log("POST: " + JSON.stringify(post));
21+
22+
$.ajax({
23+
url: "/api/v1/posts",
24+
type: "post",
25+
dataType: "json",
26+
contentType: "application/json",
27+
success: function(json) {
28+
var time = moment(json.created_at);
29+
var slug = json.slug;
30+
window.location.href="/posts/" + time.format("YYYY/MM/DD") + "/" + slug;
31+
},
32+
error: function(jqXHR, textStatus, errorThrown) {
33+
alert("ERROR: " + textStatus + " " + errorThrown);
34+
},
35+
data: JSON.stringify(post)
36+
});
37+
}
38+
</script>
39+
40+
<div class="container">
41+
<div class="nav-scroller bg-body shadow-sm">
42+
43+
<!-- https://getbootstrap.com/docs/5.0/examples/offcanvas-navbar/ -->
44+
<nav class="nav nav-underline" aria-label="Secondary navigation">
45+
<a class="nav-link active" aria-current="page" href="/admin/dashboard">Dashboard</a>
46+
<a class="nav-link" href="/admin/posts">All Posts</a>
47+
<a class="nav-link" href="/admin/newpost">New Post</a>
48+
<a class="nav-link" href="/admin/settings">Settings</a>
49+
</nav>
50+
</div>
51+
<h1>Dashboard</h1>
52+
<p>Welcome to the admin dashboard.</p>
53+
54+
</div> <!-- / container -->
55+
56+
{{ template "footer.html" .}}

templates/admin_new_post.html

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
{{ template "header.html" .}}
2+
<script type="text/javascript">
3+
4+
function createPost(publish) {
5+
var tags = $("#tags").val().split(',')
6+
for (var i = 0; i < tags.length; i++) {
7+
tags[i] = {"name": tags[i].trim()}
8+
}
9+
10+
var time = $("#created_at").val();
11+
var vtime = moment.utc(time)
12+
13+
var post = {
14+
"title": $("#title").val(),
15+
"created_at": vtime,
16+
"content": simplemde.value(),
17+
"tags": tags,
18+
"draft": !publish,
19+
}
20+
console.log("POST: " + JSON.stringify(post));
21+
22+
$.ajax({
23+
url: "/api/v1/posts",
24+
type: "post",
25+
dataType: "json",
26+
contentType: "application/json",
27+
success: function(json) {
28+
var time = moment(json.created_at);
29+
var slug = json.slug;
30+
window.location.href="/posts/" + time.format("YYYY/MM/DD") + "/" + slug;
31+
},
32+
error: function(jqXHR, textStatus, errorThrown) {
33+
alert("ERROR: " + textStatus + " " + errorThrown);
34+
},
35+
data: JSON.stringify(post)
36+
});
37+
}
38+
</script>
39+
40+
<div class="container">
41+
<div class="nav-scroller bg-body shadow-sm">
42+
<!-- https://getbootstrap.com/docs/5.0/examples/offcanvas-navbar/ -->
43+
<nav class="nav nav-underline" aria-label="Secondary navigation">
44+
<a class="nav-link" href="/admin/dashboard">Dashboard</a>
45+
<a class="nav-link" href="/admin/posts">All Posts</a>
46+
<a class="nav-link active" aria-current="page" href="/admin/newpost">New Post</a>
47+
<a class="nav-link" href="/admin/settings">Settings</a>
48+
</nav>
49+
</div>
50+
51+
<h1>Create post</h1>
52+
53+
<div class="form-group">
54+
<label for="title">Title <span class="require">*</span></label>
55+
<input type="text" class="form-control" name="title" id="title"/>
56+
</div>
57+
58+
<div class="form-group">
59+
<label for="slug">Tags <small>(comma-separated)</small></label>
60+
<input type="text" class="form-control" name="tags" id="tags"/>
61+
</div>
62+
63+
<div class="form-group">
64+
<label for="created_at">Date Created</label>
65+
<div class="input-group date" id="datetimepicker1" data-target-input="nearest">
66+
<input type="text" class="form-control datetimepicker-input" data-target="#datetimepicker1" id="created_at" name="created_at" value="{{ .post.CreatedAt.Format "01/02/2006 15:04:05 PM" }}"/>
67+
<div class="input-group-append" data-target="#datetimepicker1" data-toggle="datetimepicker">
68+
<div class="input-group-text"><i class="fa fa-calendar"></i></div>
69+
</div>
70+
</div>
71+
</div>
72+
73+
<div class="form-group">
74+
<label for="content">Content <span class="require">*</span></label>
75+
<div class="text-left">
76+
<textarea rows="5" class="form-control" name="content" id="content"></textarea>
77+
</div>
78+
</div>
79+
80+
<div class="form-group">
81+
<p><span class="require">*</span> - required fields</p>
82+
</div>
83+
84+
<div class="form-group">
85+
<button class="btn btn-primary" onclick="createPost(false);">
86+
Draft
87+
</button>
88+
<button class="btn btn-primary" onclick="createPost(true);">
89+
Publish
90+
</button>
91+
<button class="btn btn-default" onClick="window.location.reload();">
92+
Cancel
93+
</button>
94+
</div>
95+
96+
</div> <!-- / container -->
97+
98+
<script>
99+
var simplemde = new SimpleMDE({ element: $("#content")[0] });
100+
101+
//https://github.com/sparksuite/simplemde-markdown-editor/issues/328
102+
inlineAttachment.editors.codemirror4.attach(simplemde.codemirror, {
103+
uploadUrl: "/api/v1/upload",
104+
onFileUploadResponse: function(xhr) {
105+
var result = JSON.parse(xhr.responseText);
106+
console.log(result);
107+
filename = result[this.settings.jsonFieldName];
108+
console.log(filename);
109+
console.log(this.filenameTag);
110+
if (result && filename) {
111+
var newValue;
112+
if (typeof this.settings.urlText === 'function') {
113+
newValue = this.settings.urlText.call(this, filename, result);
114+
} else {
115+
newValue = this.settings.urlText.replace(this.filenameTag, filename);
116+
}
117+
var text = this.editor.getValue().replace(this.lastValue, newValue);
118+
this.editor.setValue(text);
119+
this.settings.onFileUploaded.call(this, filename);
120+
}
121+
return false;
122+
}
123+
});
124+
125+
$(function () {
126+
$('#datetimepicker1').datetimepicker({timezone: "UTC"});
127+
});
128+
</script>
129+
130+
{{ template "footer.html" .}}

0 commit comments

Comments
 (0)