add edit blog feature
This commit is contained in:
parent
e31a7fe09e
commit
7c294a5ecb
@ -223,6 +223,66 @@ pub fn delete(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
||||
}
|
||||
}
|
||||
|
||||
// blogs/:id/edit
|
||||
pub fn edit(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
||||
// check "session" cookie for authentication
|
||||
const cookies = try request.cookies();
|
||||
const session = cookies.get("session") orelse {
|
||||
return request.fail(.not_found);
|
||||
};
|
||||
|
||||
const session_query = jetzig.database.Query(.Session)
|
||||
.findBy(.{ .session_id = session.value });
|
||||
|
||||
_ = request.repo.execute(session_query) catch {
|
||||
return request.fail(.not_found);
|
||||
};
|
||||
|
||||
switch (request.method) {
|
||||
.GET => {
|
||||
// get blog
|
||||
const blog_query = jetzig.database.Query(.Blog)
|
||||
.find(try std.fmt.parseInt(i32, id, 10));
|
||||
|
||||
const blog = request.repo.execute(blog_query) catch {
|
||||
return request.fail(.not_found);
|
||||
};
|
||||
|
||||
const root = try request.data(.object);
|
||||
try root.put("allowed", true);
|
||||
try root.put("blog", blog);
|
||||
|
||||
return request.render(.ok);
|
||||
},
|
||||
.POST => {
|
||||
// make two queries for now
|
||||
const params = try request.params();
|
||||
|
||||
const blog_query_original = jetzig.database.Query(.Blog)
|
||||
.find(try std.fmt.parseInt(i32, id, 10));
|
||||
|
||||
if (try request.repo.execute(blog_query_original)) |blog| {
|
||||
const title = params.getT(.string, "title") orelse blog.title;
|
||||
const content = params.getT(.string, "content") orelse blog.content;
|
||||
const preview = params.getT(.string, "preview") orelse blog.blob;
|
||||
|
||||
// query the blogpost first
|
||||
const blog_query = jetzig.database.Query(.Blog)
|
||||
.update(.{ .title = title, .blob = preview, .content = content })
|
||||
.where(.{ .id = try std.fmt.parseInt(i32, id, 10) });
|
||||
|
||||
// update the blogpost
|
||||
try request.repo.execute(blog_query);
|
||||
|
||||
return request.redirect("/blogs", .moved_permanently);
|
||||
} else {
|
||||
return request.fail(.not_found);
|
||||
}
|
||||
},
|
||||
else => return request.fail(.not_found),
|
||||
}
|
||||
}
|
||||
|
||||
test "index" {
|
||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
||||
defer app.deinit();
|
||||
|
46
src/app/views/blogs/edit.zmpl
Normal file
46
src/app/views/blogs/edit.zmpl
Normal file
@ -0,0 +1,46 @@
|
||||
<div class="max-w-2xl mx-auto mt-10 p-6 bg-white border border-win7-border shadow-md rounded-2xl font-sans text-win7-text">
|
||||
<form action="/blogs/{{.blog.id}}/edit" method="POST" class="space-y-6">
|
||||
|
||||
<div>
|
||||
<label for="title" class="block text-sm font-medium mb-1">Title</label>
|
||||
<input
|
||||
type="text"
|
||||
name="title"
|
||||
id="title"
|
||||
value="{{.blog.title}}"
|
||||
required
|
||||
class="mt-1 w-full px-4 py-2 bg-white border border-win7-border rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-win7-hover focus:border-win7-hover transition"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="content" class="block text-sm font-medium mb-1">Content</label>
|
||||
<textarea
|
||||
name="content"
|
||||
id="content"
|
||||
rows="8"
|
||||
required
|
||||
class="mt-1 w-full px-4 py-2 bg-white border border-win7-border rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-win7-hover focus:border-win7-hover transition"
|
||||
>{{.blog.content}}</textarea>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="preview" class="block text-sm font-medium mb-1">Preview</label>
|
||||
<textarea
|
||||
name="preview"
|
||||
id="preview"
|
||||
rows="3"
|
||||
class="mt-1 w-full px-4 py-2 bg-white border border-win7-border rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-win7-hover focus:border-win7-hover transition"
|
||||
>{{.blog.blob}}</textarea>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input
|
||||
type="submit"
|
||||
value="Save Changes"
|
||||
class="px-4 py-2 bg-win7-link text-white font-semibold rounded-md shadow hover:bg-win7-hover transition"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -4,23 +4,25 @@
|
||||
@for (.blogs) |blog| {
|
||||
<div class="p4 bg-win7-bg border border-win7-border rounded-xl px-5 py-4 shadow-sm hover:shadow-md transition duration-150">
|
||||
<div class="flex justify-between items-center">
|
||||
<a href="/blogs/{{blog.id}}" class="text-xl font-semibold text-win7-link hover:underline transition">
|
||||
{{blog.title}}
|
||||
</a>
|
||||
<a href="/blogs/{{blog.id}}" class="text-xl font-semibold text-win7-link hover:underline transition">{{blog.title}}</a>
|
||||
|
||||
@if ($.allowed)
|
||||
<div class="flex items-center gap-4">
|
||||
<a href="/blogs/{{blog.id}}/edit"
|
||||
class="text-sm text-win7-link hover:underline transition"
|
||||
>
|
||||
Edit
|
||||
</a>
|
||||
<button
|
||||
id="delete-post-{{blog.id}}"
|
||||
class="text-sm text-win7-red hover:text-red-800 transition"
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
@end
|
||||
</div>
|
||||
|
||||
<p class="text-xs text-[#4a5c75] mt-2">
|
||||
{{zmpl.fmt.datetime(blog.get("created_at"), "%Y-%m-%d %H:%M")}}
|
||||
</p>
|
||||
<p class="text-xs text-[#4a5c75] mt-2">{{zmpl.fmt.datetime(blog.get("created_at"), "%Y-%m-%d %H:%M")}}</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
@ -35,8 +37,8 @@
|
||||
</div>
|
||||
|
||||
@if ($.allowed)
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
document.querySelectorAll('[id^="delete-post-"]').forEach(button => {
|
||||
button.addEventListener("click", () => {
|
||||
const id = button.id.replace("delete-post-", "");
|
||||
@ -50,7 +52,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
.catch(err => console.error("Failed to delete post:", err));
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
});
|
||||
</script>
|
||||
@end
|
||||
|
||||
|
@ -105,6 +105,8 @@ pub const jetzig_options = struct {
|
||||
|
||||
pub fn init(app: *jetzig.App) !void {
|
||||
app.route(.GET, "/rss.xml", @import("app/views/rss.zig"), .index);
|
||||
app.route(.GET, "/blogs/:id/edit" , @import("app/views/blogs.zig"), .edit);
|
||||
app.route(.POST, "/blogs/:id/edit" , @import("app/views/blogs.zig"), .edit);
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
|
Loading…
x
Reference in New Issue
Block a user