diff --git a/app/controllers/AdminController.asp b/app/controllers/AdminController.asp new file mode 100644 index 0000000..9d6859a --- /dev/null +++ b/app/controllers/AdminController.asp @@ -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" + %> + + <% + End Sub + + '--------------------------------------------------------------- + ' Action: Posts + '--------------------------------------------------------------- + Public Sub Posts() + m_title = "Manage Posts" + Dim posts + Set posts = PostsRepository().FindAllWhere(Empty, "CreatedDate DESC", 0, 0) + %> + + <% + End Sub + + '--------------------------------------------------------------- + ' Action: Categories + '--------------------------------------------------------------- + Public Sub Categories() + m_title = "Manage Categories" + Dim categories + Set categories = CategoriesRepository().FindAll + %> + + <% + 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 +%> diff --git a/app/controllers/CategoriesController.asp b/app/controllers/CategoriesController.asp index f27c178..6ffc7a8 100644 --- a/app/controllers/CategoriesController.asp +++ b/app/controllers/CategoriesController.asp @@ -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") %> <% @@ -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 +%> diff --git a/app/controllers/PostsController.asp b/app/controllers/PostsController.asp index 2b43df4..f4e165e 100644 --- a/app/controllers/PostsController.asp +++ b/app/controllers/PostsController.asp @@ -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")) %> <% diff --git a/app/controllers/autoload_controllers.asp b/app/controllers/autoload_controllers.asp index aabd073..a9d83ec 100644 --- a/app/controllers/autoload_controllers.asp +++ b/app/controllers/autoload_controllers.asp @@ -2,4 +2,5 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/app/views/Admin/categories.asp b/app/views/Admin/categories.asp new file mode 100644 index 0000000..78b1adc --- /dev/null +++ b/app/views/Admin/categories.asp @@ -0,0 +1,48 @@ +
+
+

Manage Categories

+

All categories — edit or delete.

+
+ New Category +
+ +<% If categories.Count = 0 Then %> +
No categories yet. Create the first one.
+<% Else %> +
+ + + + + + + + + + <% + Dim adminCatIter, adminCatItem + Set adminCatIter = categories.Iterator() + Do While adminCatIter.HasNext + Set adminCatItem = adminCatIter.GetNext() + %> + + + + + + <% + Loop + %> + +
NameDescriptionActions
+ + <%= H(adminCatItem.Name) %> + + <%= H(adminCatItem.Description) %> + Edit +
+ +
+
+
+<% End If %> diff --git a/app/views/Admin/index.asp b/app/views/Admin/index.asp new file mode 100644 index 0000000..6f88aae --- /dev/null +++ b/app/views/Admin/index.asp @@ -0,0 +1,25 @@ +
+
+

Admin Dashboard

+

Manage your blog content.

+
+
+ +
+
+ +
+

Posts

+

Create, publish, and manage blog posts.

+
+
+
+
+ +
+

Categories

+

Organize posts into categories.

+
+
+
+
diff --git a/app/views/Admin/posts.asp b/app/views/Admin/posts.asp new file mode 100644 index 0000000..54a5e0c --- /dev/null +++ b/app/views/Admin/posts.asp @@ -0,0 +1,68 @@ +
+
+

Manage Posts

+

All posts — publish, edit, or delete.

+
+ New Post +
+ +<% If posts.Count = 0 Then %> +
No posts yet. Create the first one.
+<% Else %> +
+ + + + + + + + + + + <% + Dim adminPostIter, adminPostItem + Set adminPostIter = posts.Iterator() + Do While adminPostIter.HasNext + Set adminPostItem = adminPostIter.GetNext() + %> + + + + + + + <% + Loop + %> + +
TitleStatusCreatedActions
+ <%= H(adminPostItem.Title) %> + <% If Len(Trim(CStr(adminPostItem.Summary))) > 0 Then %> +
<%= H(adminPostItem.Summary) %>
+ <% End If %> +
+ <% If adminPostItem.IsPublished = 1 Then %> + Published + <% Else %> + Draft + <% End If %> + + <%= H(FormatDateTime(adminPostItem.CreatedDate, vbShortDate)) %> + + Edit + <% If adminPostItem.IsPublished = 1 Then %> +
+ +
+ <% Else %> +
+ +
+ <% End If %> +
+ +
+
+
+<% End If %> diff --git a/app/views/Categories/show.asp b/app/views/Categories/show.asp index 91a4ffa..cfa61fd 100644 --- a/app/views/Categories/show.asp +++ b/app/views/Categories/show.asp @@ -1,4 +1,4 @@ -
+
← Back to categories @@ -15,3 +15,36 @@
+ +

Posts in this category

+ +<% If categoryPosts.Count = 0 Then %> +
No published posts in this category yet.
+<% Else %> +
+ <% + Dim catPostIter, catPostItem + Set catPostIter = categoryPosts.Iterator() + Do While catPostIter.HasNext + Set catPostItem = catPostIter.GetNext() + %> +
+ +
+ <% + Loop + %> +
+<% End If %> diff --git a/app/views/Posts/show.asp b/app/views/Posts/show.asp index 653cbdb..fe61f7d 100644 --- a/app/views/Posts/show.asp +++ b/app/views/Posts/show.asp @@ -1,33 +1,93 @@ -
-
- - -

<%= H(post.Title) %>

- - <% - 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 - %> -

<%= H(publishedText) %>

- <% - End If - - Dim postBody - postBody = H(post.Body) - postBody = Replace(postBody, vbCrLf, "
") - postBody = Replace(postBody, vbCr, "
") - postBody = Replace(postBody, vbLf, "
") - %> - -
<%= postBody %>
-
-
+
+
+ + +

<%= H(post.Title) %>

+ + <% + 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 + %> +

<%= H(publishedText) %>

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

Comments (<%= comments.Count %>)

+ + <% If comments.Count = 0 Then %> +

No comments yet. Be the first to leave one below.

+ <% Else %> + <% + Dim commentIter, commentItem + Set commentIter = comments.Iterator() + Do While commentIter.HasNext + Set commentItem = commentIter.GetNext() + %> +
+
+
+ <%= H(commentItem.AuthorName) %> + <%= H(FormatDateTime(commentItem.CreatedDate, vbLongDate)) %> +
+ <% + Dim commentBody + commentBody = H(commentItem.Body) + commentBody = Replace(commentBody, vbCrLf, "
") + commentBody = Replace(commentBody, vbCr, "
") + commentBody = Replace(commentBody, vbLf, "
") + %> +

<%= commentBody %>

+
+
+ <% + Loop + %> + <% End If %> + + +
+
+

Leave a Comment

+
+ + +
+ + +
+
+ + +
+
+ + +
+ +

Comments are reviewed before appearing.

+
+
+
+
diff --git a/app/views/shared/header.asp b/app/views/shared/header.asp index ddf539b..d5c7ce9 100644 --- a/app/views/shared/header.asp +++ b/app/views/shared/header.asp @@ -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 + diff --git a/core/lib.ControllerRegistry.asp b/core/lib.ControllerRegistry.asp index 49955b8..0d9306f 100644 --- a/core/lib.ControllerRegistry.asp +++ b/core/lib.ControllerRegistry.asp @@ -18,6 +18,7 @@ Class ControllerRegistry_Class RegisterController "categoriescontroller" RegisterController "postscontroller" RegisterController "commentscontroller" + RegisterController "admincontroller" End Sub Private Sub Class_Terminate() diff --git a/public/Default.asp b/public/Default.asp index 1a5dea9..2eda254 100644 --- a/public/Default.asp +++ b/public/Default.asp @@ -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"))