Pārlūkot izejas kodu

Fix issues #1, #2, #3: admin panel, category posts, comments

- Issue #1: Category show page now lists published posts in that category
- Issue #2: Admin panel at /admin with posts and categories management tables;
  publish/unpublish buttons on posts table; Admin nav link
- Issue #3: Comments section on post show page with author/date display
  and submit-comment form; comments load approved-only on publish

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
pull/5/head
Nano pirms 6 dienas
vecāks
revīzija
934b6b3127
12 mainītis faili ar 456 papildinājumiem un 82 dzēšanām
  1. +119
    -0
      app/controllers/AdminController.asp
  2. +49
    -46
      app/controllers/CategoriesController.asp
  3. +3
    -0
      app/controllers/PostsController.asp
  4. +2
    -1
      app/controllers/autoload_controllers.asp
  5. +48
    -0
      app/views/Admin/categories.asp
  6. +25
    -0
      app/views/Admin/index.asp
  7. +68
    -0
      app/views/Admin/posts.asp
  8. +34
    -1
      app/views/Categories/show.asp
  9. +93
    -33
      app/views/Posts/show.asp
  10. +7
    -1
      app/views/shared/header.asp
  11. +1
    -0
      core/lib.ControllerRegistry.asp
  12. +7
    -0
      public/Default.asp

+ 119
- 0
app/controllers/AdminController.asp Parādīt failu

@@ -0,0 +1,119 @@
<%
Class AdminController_Class
Private m_useLayout
Private m_title

Private Sub Class_Initialize()
m_useLayout = True
m_title = "Admin"
End Sub

Public Property Get useLayout
useLayout = m_useLayout
End Property

Public Property Let useLayout(v)
m_useLayout = v
End Property

Public Property Get Title
Title = m_title
End Property

Public Property Let Title(v)
m_title = v
End Property

'---------------------------------------------------------------
' Action: Index
'---------------------------------------------------------------
Public Sub Index()
m_title = "Admin Dashboard"
%>
<!--#include file="../views/Admin/index.asp" -->
<%
End Sub

'---------------------------------------------------------------
' Action: Posts
'---------------------------------------------------------------
Public Sub Posts()
m_title = "Manage Posts"
Dim posts
Set posts = PostsRepository().FindAllWhere(Empty, "CreatedDate DESC", 0, 0)
%>
<!--#include file="../views/Admin/posts.asp" -->
<%
End Sub

'---------------------------------------------------------------
' Action: Categories
'---------------------------------------------------------------
Public Sub Categories()
m_title = "Manage Categories"
Dim categories
Set categories = CategoriesRepository().FindAll
%>
<!--#include file="../views/Admin/categories.asp" -->
<%
End Sub

'---------------------------------------------------------------
' Action: PublishPost
'---------------------------------------------------------------
Public Sub PublishPost(ByVal id)
Dim post
On Error Resume Next
Set post = PostsRepository().FindByID(id)
If Err.Number <> 0 Then
Err.Clear
On Error GoTo 0
Flash().AddError "Post not found."
Response.Redirect "/admin/posts"
Exit Sub
End If
On Error GoTo 0

post.IsPublished = 1
If Not IsDate(post.PublishedDate) Or CDate(post.PublishedDate) <= #1/1/1970# Then
post.PublishedDate = Now()
End If
post.UpdatedDate = Now()
PostsRepository().Update post
Flash().Success = "Post published."
Response.Redirect "/admin/posts"
End Sub

'---------------------------------------------------------------
' Action: UnpublishPost
'---------------------------------------------------------------
Public Sub UnpublishPost(ByVal id)
Dim post
On Error Resume Next
Set post = PostsRepository().FindByID(id)
If Err.Number <> 0 Then
Err.Clear
On Error GoTo 0
Flash().AddError "Post not found."
Response.Redirect "/admin/posts"
Exit Sub
End If
On Error GoTo 0

post.IsPublished = 0
post.UpdatedDate = Now()
PostsRepository().Update post
Flash().Success = "Post unpublished."
Response.Redirect "/admin/posts"
End Sub

End Class

Dim AdminController_Class__Singleton
Function AdminController()
If IsEmpty(AdminController_Class__Singleton) Then
Set AdminController_Class__Singleton = New AdminController_Class
End If
Set AdminController = AdminController_Class__Singleton
End Function
%>

+ 49
- 46
app/controllers/CategoriesController.asp Parādīt failu

@@ -1,39 +1,39 @@
<%
' Auto-generated Controller: Categories
' Generated on 5/2/2026 9:47:37 PM
' Generator: generateController.vbs v1.0
'
' Remember to:
' 1. Add to app/controllers/autoload_controllers.asp
' 2. Register in core/lib.ControllerRegistry.asp
' 3. Add routes in public/Default.asp
Class CategoriesController_Class
Private m_useLayout
Private m_title
Private Sub Class_Initialize()
m_useLayout = True
m_title = "Categories"
End Sub
Public Property Get useLayout
useLayout = m_useLayout
End Property
Public Property Let useLayout(v)
m_useLayout = v
End Property
Public Property Get Title
Title = m_title
End Property
Public Property Let Title(v)
m_title = v
End Property
<%
' Auto-generated Controller: Categories
' Generated on 5/2/2026 9:47:37 PM
' Generator: generateController.vbs v1.0
'
' Remember to:
' 1. Add to app/controllers/autoload_controllers.asp
' 2. Register in core/lib.ControllerRegistry.asp
' 3. Add routes in public/Default.asp
Class CategoriesController_Class
Private m_useLayout
Private m_title
Private Sub Class_Initialize()
m_useLayout = True
m_title = "Categories"
End Sub
Public Property Get useLayout
useLayout = m_useLayout
End Property
Public Property Let useLayout(v)
m_useLayout = v
End Property
Public Property Get Title
Title = m_title
End Property
Public Property Let Title(v)
m_title = v
End Property
'---------------------------------------------------------------
' Action: Index
'---------------------------------------------------------------
@@ -62,6 +62,9 @@ Class CategoriesController_Class
Exit Sub
End If
On Error GoTo 0

Dim categoryPosts
Set categoryPosts = PostsRepository().Find(Array("CategoryID", id, "IsPublished", 1), "PublishedDate DESC")
%>
<!--#include file="../views/Categories/show.asp" -->
<%
@@ -165,13 +168,13 @@ Class CategoriesController_Class
End Sub

End Class
' Singleton instance
Dim CategoriesController_Class__Singleton
Function CategoriesController()
If IsEmpty(CategoriesController_Class__Singleton) Then
Set CategoriesController_Class__Singleton = New CategoriesController_Class
End If
Set CategoriesController = CategoriesController_Class__Singleton
End Function
%>
' Singleton instance
Dim CategoriesController_Class__Singleton
Function CategoriesController()
If IsEmpty(CategoriesController_Class__Singleton) Then
Set CategoriesController_Class__Singleton = New CategoriesController_Class
End If
Set CategoriesController = CategoriesController_Class__Singleton
End Function
%>

+ 3
- 0
app/controllers/PostsController.asp Parādīt failu

@@ -62,6 +62,9 @@ Class PostsController_Class
Dim post
Set post = matches.Front()
Dim comments
Set comments = CommentsRepository().Find(Array("PostID", post.PostID, "IsApproved", 1), Array("CreatedDate"))
%>
<!--#include file="../views/Posts/show.asp" -->
<%


+ 2
- 1
app/controllers/autoload_controllers.asp Parādīt failu

@@ -2,4 +2,5 @@
<!--#include file="ErrorController.asp" -->
<!--#include file="CategoriesController.asp" -->
<!--#include file="PostsController.asp" -->
<!--#include file="CommentsController.asp" -->
<!--#include file="CommentsController.asp" -->
<!--#include file="AdminController.asp" -->

+ 48
- 0
app/views/Admin/categories.asp Parādīt failu

@@ -0,0 +1,48 @@
<div class="d-flex align-items-center justify-content-between mb-4">
<div>
<h1 class="h3 mb-1">Manage Categories</h1>
<p class="text-muted mb-0">All categories &mdash; edit or delete.</p>
</div>
<a class="btn btn-primary" href="/categories/new">New Category</a>
</div>

<% If categories.Count = 0 Then %>
<div class="alert alert-secondary">No categories yet. <a href="/categories/new">Create the first one.</a></div>
<% Else %>
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead class="table-light">
<tr>
<th>Name</th>
<th>Description</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
<%
Dim adminCatIter, adminCatItem
Set adminCatIter = categories.Iterator()
Do While adminCatIter.HasNext
Set adminCatItem = adminCatIter.GetNext()
%>
<tr>
<td>
<a href="/categories/<%= Server.URLEncode(CStr(adminCatItem.CategoryID)) %>" class="text-decoration-none fw-semibold">
<%= H(adminCatItem.Name) %>
</a>
</td>
<td class="text-muted small"><%= H(adminCatItem.Description) %></td>
<td class="text-end text-nowrap">
<a class="btn btn-sm btn-outline-secondary" href="/categories/<%= Server.URLEncode(CStr(adminCatItem.CategoryID)) %>/edit">Edit</a>
<form class="d-inline" method="post" action="/categories/<%= H(adminCatItem.CategoryID) %>/delete">
<button class="btn btn-sm btn-outline-danger" type="submit" onclick="return confirm('Delete this category?')">Delete</button>
</form>
</td>
</tr>
<%
Loop
%>
</tbody>
</table>
</div>
<% End If %>

+ 25
- 0
app/views/Admin/index.asp Parādīt failu

@@ -0,0 +1,25 @@
<div class="d-flex align-items-center justify-content-between mb-4">
<div>
<h1 class="h3 mb-1">Admin Dashboard</h1>
<p class="text-muted mb-0">Manage your blog content.</p>
</div>
</div>

<div class="row gy-3">
<div class="col-md-6">
<a class="card shadow-sm text-decoration-none h-100" href="/admin/posts">
<div class="card-body">
<h2 class="h5 mb-1">Posts</h2>
<p class="text-muted mb-0">Create, publish, and manage blog posts.</p>
</div>
</a>
</div>
<div class="col-md-6">
<a class="card shadow-sm text-decoration-none h-100" href="/admin/categories">
<div class="card-body">
<h2 class="h5 mb-1">Categories</h2>
<p class="text-muted mb-0">Organize posts into categories.</p>
</div>
</a>
</div>
</div>

+ 68
- 0
app/views/Admin/posts.asp Parādīt failu

@@ -0,0 +1,68 @@
<div class="d-flex align-items-center justify-content-between mb-4">
<div>
<h1 class="h3 mb-1">Manage Posts</h1>
<p class="text-muted mb-0">All posts &mdash; publish, edit, or delete.</p>
</div>
<a class="btn btn-primary" href="/posts/new">New Post</a>
</div>

<% If posts.Count = 0 Then %>
<div class="alert alert-secondary">No posts yet. <a href="/posts/new">Create the first one.</a></div>
<% Else %>
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead class="table-light">
<tr>
<th>Title</th>
<th>Status</th>
<th>Created</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
<%
Dim adminPostIter, adminPostItem
Set adminPostIter = posts.Iterator()
Do While adminPostIter.HasNext
Set adminPostItem = adminPostIter.GetNext()
%>
<tr>
<td>
<strong><%= H(adminPostItem.Title) %></strong>
<% If Len(Trim(CStr(adminPostItem.Summary))) > 0 Then %>
<div class="small text-muted"><%= H(adminPostItem.Summary) %></div>
<% End If %>
</td>
<td class="text-nowrap">
<% If adminPostItem.IsPublished = 1 Then %>
<span class="badge bg-success">Published</span>
<% Else %>
<span class="badge bg-secondary">Draft</span>
<% End If %>
</td>
<td class="small text-muted text-nowrap">
<%= H(FormatDateTime(adminPostItem.CreatedDate, vbShortDate)) %>
</td>
<td class="text-end text-nowrap">
<a class="btn btn-sm btn-outline-secondary" href="/posts/<%= Server.URLEncode(CStr(adminPostItem.PostID)) %>/edit">Edit</a>
<% If adminPostItem.IsPublished = 1 Then %>
<form class="d-inline" method="post" action="/admin/posts/<%= H(adminPostItem.PostID) %>/unpublish">
<button class="btn btn-sm btn-outline-warning" type="submit">Unpublish</button>
</form>
<% Else %>
<form class="d-inline" method="post" action="/admin/posts/<%= H(adminPostItem.PostID) %>/publish">
<button class="btn btn-sm btn-success" type="submit">Publish</button>
</form>
<% End If %>
<form class="d-inline" method="post" action="/posts/<%= H(adminPostItem.PostID) %>/delete">
<button class="btn btn-sm btn-outline-danger" type="submit" onclick="return confirm('Delete this post?')">Delete</button>
</form>
</td>
</tr>
<%
Loop
%>
</tbody>
</table>
</div>
<% End If %>

+ 34
- 1
app/views/Categories/show.asp Parādīt failu

@@ -1,4 +1,4 @@
<article class="card shadow-sm">
<article class="card shadow-sm mb-4">
<div class="card-body">
<div class="mb-3">
<a href="/categories" class="small text-decoration-none">&larr; Back to categories</a>
@@ -15,3 +15,36 @@
</div>
</div>
</article>

<h2 class="h4 mb-3">Posts in this category</h2>

<% If categoryPosts.Count = 0 Then %>
<div class="alert alert-secondary">No published posts in this category yet.</div>
<% Else %>
<div class="row gy-3">
<%
Dim catPostIter, catPostItem
Set catPostIter = categoryPosts.Iterator()
Do While catPostIter.HasNext
Set catPostItem = catPostIter.GetNext()
%>
<div class="col-12">
<article class="card shadow-sm">
<div class="card-body">
<h3 class="h5 mb-1">
<a href="/posts/<%= Server.URLEncode(CStr(catPostItem.Slug)) %>" class="text-decoration-none">
<%= H(catPostItem.Title) %>
</a>
</h3>
<% If Len(Trim(CStr(catPostItem.Summary))) > 0 Then %>
<p class="text-muted mb-2 small"><%= H(catPostItem.Summary) %></p>
<% End If %>
<a class="btn btn-sm btn-outline-primary" href="/posts/<%= Server.URLEncode(CStr(catPostItem.Slug)) %>">Read</a>
</div>
</article>
</div>
<%
Loop
%>
</div>
<% End If %>

+ 93
- 33
app/views/Posts/show.asp Parādīt failu

@@ -1,33 +1,93 @@
<article class="card shadow-sm">
<div class="card-body">
<div class="mb-3">
<a href="/posts" class="small text-decoration-none">&larr; Back to posts</a>
</div>
<h1 class="h2 mb-2"><%= H(post.Title) %></h1>
<%
Dim publishedText
publishedText = ""
If IsDate(post.PublishedDate) Then
If CDate(post.PublishedDate) > #1/1/1970# Then
publishedText = FormatDateTime(post.PublishedDate, vbLongDate)
End If
End If
If Len(publishedText) > 0 Then
%>
<p class="text-muted"><%= H(publishedText) %></p>
<%
End If
Dim postBody
postBody = H(post.Body)
postBody = Replace(postBody, vbCrLf, "<br>")
postBody = Replace(postBody, vbCr, "<br>")
postBody = Replace(postBody, vbLf, "<br>")
%>
<div class="fs-5 lh-lg"><%= postBody %></div>
</div>
</article>
<article class="card shadow-sm mb-4">
<div class="card-body">
<div class="mb-3">
<a href="/posts" class="small text-decoration-none">&larr; Back to posts</a>
</div>

<h1 class="h2 mb-2"><%= H(post.Title) %></h1>

<%
Dim publishedText
publishedText = ""
If IsDate(post.PublishedDate) Then
If CDate(post.PublishedDate) > #1/1/1970# Then
publishedText = FormatDateTime(post.PublishedDate, vbLongDate)
End If
End If

If Len(publishedText) > 0 Then
%>
<p class="text-muted"><%= H(publishedText) %></p>
<%
End If

Dim postBody
postBody = H(post.Body)
postBody = Replace(postBody, vbCrLf, "<br>")
postBody = Replace(postBody, vbCr, "<br>")
postBody = Replace(postBody, vbLf, "<br>")
%>

<div class="fs-5 lh-lg"><%= postBody %></div>
</div>
</article>

<!-- Comments -->
<section class="mt-2">
<h2 class="h4 mb-3">Comments (<%= comments.Count %>)</h2>

<% If comments.Count = 0 Then %>
<p class="text-muted mb-4">No comments yet. Be the first to leave one below.</p>
<% Else %>
<%
Dim commentIter, commentItem
Set commentIter = comments.Iterator()
Do While commentIter.HasNext
Set commentItem = commentIter.GetNext()
%>
<div class="card shadow-sm mb-3">
<div class="card-body">
<div class="d-flex justify-content-between mb-2">
<strong class="small"><%= H(commentItem.AuthorName) %></strong>
<span class="small text-muted"><%= H(FormatDateTime(commentItem.CreatedDate, vbLongDate)) %></span>
</div>
<%
Dim commentBody
commentBody = H(commentItem.Body)
commentBody = Replace(commentBody, vbCrLf, "<br>")
commentBody = Replace(commentBody, vbCr, "<br>")
commentBody = Replace(commentBody, vbLf, "<br>")
%>
<p class="mb-0"><%= commentBody %></p>
</div>
</div>
<%
Loop
%>
<% End If %>

<!-- Comment form -->
<div class="card shadow-sm mt-4">
<div class="card-body">
<h3 class="h5 mb-3">Leave a Comment</h3>
<form method="post" action="/comments">
<input type="hidden" name="PostID" value="<%= H(post.PostID) %>">
<input type="hidden" name="PostSlug" value="<%= H(post.Slug) %>">
<div class="mb-3">
<label class="form-label" for="AuthorName">Name <span class="text-danger">*</span></label>
<input class="form-control" type="text" id="AuthorName" name="AuthorName" required>
</div>
<div class="mb-3">
<label class="form-label" for="AuthorEmail">Email <span class="text-muted small">(optional, not displayed)</span></label>
<input class="form-control" type="email" id="AuthorEmail" name="AuthorEmail">
</div>
<div class="mb-3">
<label class="form-label" for="Body">Comment <span class="text-danger">*</span></label>
<textarea class="form-control" id="Body" name="Body" rows="4" required></textarea>
</div>
<button class="btn btn-primary" type="submit">Submit Comment</button>
<p class="small text-muted mt-2 mb-0">Comments are reviewed before appearing.</p>
</form>
</div>
</div>
</section>

+ 7
- 1
app/views/shared/header.asp Parādīt failu

@@ -19,13 +19,16 @@ Dim hdr_path
hdr_path = LCase(Request.ServerVariables("HTTP_X_ORIGINAL_URL"))
If InStr(hdr_path, "?") > 0 Then hdr_path = Left(hdr_path, InStr(hdr_path, "?") - 1)

Dim hdr_navHome, hdr_navPosts, hdr_navCats
Dim hdr_navHome, hdr_navPosts, hdr_navCats, hdr_navAdmin
hdr_navHome = "nav-link"
hdr_navPosts = "nav-link"
hdr_navCats = "nav-link"
hdr_navAdmin = "nav-link"

If hdr_path = "/" Or hdr_path = "" Or Left(hdr_path, 5) = "/home" Then
hdr_navHome = "nav-link active"
ElseIf Left(hdr_path, 6) = "/admin" Then
hdr_navAdmin = "nav-link active"
ElseIf Left(hdr_path, 6) = "/posts" Then
hdr_navPosts = "nav-link active"
ElseIf Left(hdr_path, 11) = "/categories" Then
@@ -64,6 +67,9 @@ End If
<li class="nav-item">
<a class="<%= hdr_navCats %>" href="/categories">Categories</a>
</li>
<li class="nav-item">
<a class="<%= hdr_navAdmin %>" href="/admin">Admin</a>
</li>
</ul>
</div>
</div>


+ 1
- 0
core/lib.ControllerRegistry.asp Parādīt failu

@@ -18,6 +18,7 @@ Class ControllerRegistry_Class
RegisterController "categoriescontroller"
RegisterController "postscontroller"
RegisterController "commentscontroller"
RegisterController "admincontroller"
End Sub

Private Sub Class_Terminate()


+ 7
- 0
public/Default.asp Parādīt failu

@@ -29,6 +29,13 @@
router.AddRoute "POST", "/comments", "CommentsController", "Create"
router.AddRoute "POST", "/comments/{id}/delete", "CommentsController", "Delete"

' Admin routes
router.AddRoute "GET", "/admin", "AdminController", "Index"
router.AddRoute "GET", "/admin/posts", "AdminController", "Posts"
router.AddRoute "GET", "/admin/categories", "AdminController", "Categories"
router.AddRoute "POST", "/admin/posts/{id}/publish", "AdminController", "PublishPost"
router.AddRoute "POST", "/admin/posts/{id}/unpublish", "AdminController", "UnpublishPost"

' Dispatch the request (resolves route and executes controller action)
MVC.DispatchRequest Request.ServerVariables("REQUEST_METHOD"), _
TrimQueryParams(Request.ServerVariables("HTTP_X_ORIGINAL_URL"))


Notiek ielāde…
Atcelt
Saglabāt

Powered by TurnKey Linux.