Skip to content

Commit

Permalink
Add a feed page
Browse files Browse the repository at this point in the history
  • Loading branch information
mattesmohr committed Dec 3, 2023
1 parent 60afd35 commit adf65cd
Show file tree
Hide file tree
Showing 18 changed files with 492 additions and 11 deletions.
4 changes: 4 additions & 0 deletions Public/css/page.css
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,7 @@ body > footer {
.border\:electricblue {
--borderColor: 199, 44%, 93%;
}

.grid.ratio\:masonary {
grid-template-rows: masonry;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import HTMLKitVapor
import Vapor

// [/area/admin/feed]
final class FeedAdminController {

// [/index]
func getIndex(_ request: Request) async throws -> View {

let page: Int = request.query["page"] ?? 1

let pagination = try await FeedRepository(database: request.db)
.find()
.map(FeedModel.Output.init)
.page(page: page, per: 10)

let viewModel = FeedAdminPageModel.IndexView(pagination: pagination)

return try await request.htmlkit.render(FeedAdminPage.IndexView(viewModel: viewModel))
}

// [/create]
func getCreate(_ request: Request) async throws -> View {

let viewModel = FeedAdminPageModel.CreateView()

return try await request.htmlkit.render(FeedAdminPage.CreateView(viewModel: viewModel))
}

// [/create/:model]
func postCreate(_ request: Request) async throws -> Response {

try FeedModel.Input.validate(content: request)

let model = try request.content.decode(FeedModel.Input.self)

try await FeedRepository(database: request.db)
.insert(entity: FeedEntity(input: model))

return request.redirect(to: "/area/admin/feed/index")
}

// [/edit/:id]
func getEdit(_ request: Request) async throws -> View {

guard let id = request.parameters.get("id", as: UUID.self) else {
throw Abort(.badRequest)
}

guard let entity = try await FeedRepository(database: request.db)
.find(id: id) else {
throw Abort(.notFound)
}

let viewModel = FeedAdminPageModel.EditView(feed: FeedModel.Output(entity: entity))

return try await request.htmlkit.render(FeedAdminPage.EditView(viewModel: viewModel))
}

// [/edit/:model]
func postEdit(_ request: Request) async throws -> Response {

guard let id = request.parameters.get("id", as: UUID.self) else {
throw Abort(.badRequest)
}

try FeedModel.Input.validate(content: request)

let model = try request.content.decode(FeedModel.Input.self)

try await FeedRepository(database: request.db)
.update(entity: FeedEntity(input: model), on: id)

return request.redirect(to: "/area/admin/feed/index")
}

// [/delete/:id]
func getDelete(_ request: Request) async throws -> Response {

guard let id = request.parameters.get("id", as: UUID.self) else {
throw Abort(.badRequest)
}

try await FeedRepository(database: request.db)
.delete(id: id)

return request.redirect(to: "/area/admin/feed/index")
}
}

extension FeedAdminController: RouteCollection {

func boot(routes: RoutesBuilder) throws {

routes.group("feed") { routes in

routes.get("index", use: self.getIndex)
routes.get("create", use: self.getCreate)
routes.post("create", use: self.postCreate)
routes.get("edit", ":id", use: self.getEdit)
routes.post("edit", ":id", use: self.postEdit)
routes.get("delete", ":id", use: self.getDelete)
}
}
}
12 changes: 11 additions & 1 deletion Sources/Website/Controllers/FeedPageController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@ final class FeedPageController {

// [/index]
func getIndex(_ request: Request) async throws -> View {
return try await request.htmlkit.render(FeedPage.IndexView(viewModel: .init()))

let page: Int = request.query["page"] ?? 1

let feeds = try await FeedRepository(database: request.db)
.find()
.map(FeedModel.Output.init)
.page(page: page, per: 10)

let viewModel = FeedPageModel.IndexView(pagination: feeds)

return try await request.htmlkit.render(FeedPage.IndexView(viewModel: viewModel))
}
}

Expand Down
34 changes: 34 additions & 0 deletions Sources/Website/Entities/FeedEntity.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Fluent
import Foundation

final class FeedEntity: Model {

static let schema = "feeds"

@ID(key: "id")
var id: UUID?

@Field(key: "message")
var message: String

@Timestamp(key: "created_at", on: .create)
var createdAt: Date?

@Timestamp(key: "modified_at", on: .update)
var modifiedAt: Date?

init() {}

init(id: UUID? = nil, message: String, createdAt: Date? = nil, modifiedAt: Date? = nil) {

self.id = id
self.message = message
self.createdAt = createdAt
self.modifiedAt = modifiedAt
}

convenience init(input: FeedModel.Input) {

self.init(message: input.message)
}
}
1 change: 1 addition & 0 deletions Sources/Website/Localization/de/web.strings
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"menu.articles" = "Beiträge";
"menu.assets" = "Mediathek";
"menu.reports" = "Berichte";
"menu.feed" = "Texte";
"menu.users" = "Benutzer";
"menu.legal" = "Impressum";
"menu.privacy" = "Datenschutz";
Expand Down
1 change: 1 addition & 0 deletions Sources/Website/Localization/en-GB/web.strings
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"menu.articles" = "Articles";
"menu.assets" = "Assets";
"menu.reports" = "Reports";
"menu.feed" = "Feed";
"menu.users" = "Users";
"menu.legal" = "Legal";
"menu.privacy" = "Privacy";
Expand Down
20 changes: 20 additions & 0 deletions Sources/Website/Migrations/FeedMigration.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Fluent

struct FeedMigration: AsyncMigration {

func prepare(on database: Database) async throws {

try await database.schema("feeds")
.id()
.field("message", .string, .required)
.field("created_at", .datetime)
.field("modified_at", .datetime)
.create()
}

func revert(on database: Database) async throws {

try await database.schema("feeds")
.delete()
}
}
36 changes: 36 additions & 0 deletions Sources/Website/Models/FeedModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Vapor
import HTMLKitComponents

struct FeedModel {

struct Input: Content, Validatable {

var message: String

static func validations(_ validations: inout Validations) {

validations.add("message", as: String.self, is: !.empty)
}

static let validators = [
Validator(field: "message", rule: .value)
]
}

struct Output: Content {

var id: UUID
var message: String

init(id: UUID, message: String) {

self.id = id
self.message = message
}

init(entity: FeedEntity) {

self.init(id: entity.id!, message: entity.message)
}
}
}
19 changes: 19 additions & 0 deletions Sources/Website/Models/PageModels/FeedAdminPageModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import HTMLKitComponents

enum FeedAdminPageModel {

struct IndexView {
var title: String = "Show feed"
let pagination: Pagination<[FeedModel.Output]>
}

struct CreateView {
var title: String = "Create feed"
}

struct EditView {

var title: String = "Edit feed"
let feed: FeedModel.Output
}
}
1 change: 1 addition & 0 deletions Sources/Website/Models/PageModels/FeedPageModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ enum FeedPageModel {
struct IndexView {

var title: String = "Feed"
let pagination: Pagination<[FeedModel.Output]>
}
}
59 changes: 59 additions & 0 deletions Sources/Website/Repositories/FeedRepository.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import Fluent
import Foundation

final class FeedRepository {

let database: Database

init(database: Database) {

self.database = database
}

func find(id: UUID) async throws -> FeedEntity? {

return try await FeedEntity.query(on: database)
.filter(\.$id == id)
.first()
}

func find() async throws -> [FeedEntity] {

return try await FeedEntity.query(on: database)
.sort(\.$modifiedAt, .descending)
.all()
}

func insert(entity: FeedEntity) async throws {
try await entity.create(on: database)
}

func patch<Field: QueryableProperty>(field: KeyPath<FeedEntity, Field>, to value: Field.Value, on id: UUID) async throws where Field.Model == FeedEntity {

try await FeedEntity.query(on: database)
.filter(\.$id == id)
.set(field, to: value)
.update()
}

func update(entity: FeedEntity, on id: UUID) async throws {

try await FeedEntity.query(on: database)
.filter(\.$id == id)
.set(\.$message, to: entity.message)
.update()
}

func delete(id: UUID) async throws {

try await FeedEntity.query(on: database)
.filter(\.$id == id)
.delete()
}

func count() async throws -> Int {

return try await FeedEntity.query(on: database)
.count()
}
}
2 changes: 2 additions & 0 deletions Sources/Website/Setup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ struct Setup {
try group.register(collection: ArticleAdminController())
try group.register(collection: AssetAdminController())
try group.register(collection: UserAdminController())
try group.register(collection: FeedAdminController())
try group.register(collection: ReportAdminController())
}
}
Expand Down Expand Up @@ -94,6 +95,7 @@ struct Setup {
application.migrations.add(ContactMigration())
application.migrations.add(ReportMigration())
application.migrations.add(LinkMigration())
application.migrations.add(FeedMigration())

try await application.autoMigrate()
}
Expand Down
Loading

0 comments on commit adf65cd

Please sign in to comment.