Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Resources/Views/Home/_info.leaf
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@
<div class="row pt-xl-2 pb-md-3">
<div class="col-lg-5 mb-4 mb-lg-0">
<div class="text-center text-lg-start">
<h2 class="h1 mb-4 themed-header">About</h2>
<h2 class="h1 mb-4 themed-header">#if(about):#(about.title)#else:About#endif</h2>
</div>
#if(about):
<p>Founded by <a href="#(about.founderTwitter)" target="_blank">#(about.founderName)</a> in #(about.foundedYear), SwiftLeeds has set out to bring a modern, inclusive conference to the north of the UK.</p>
<p>Ran by just a handful of community volunteers, SwiftLeeds is entirely non-profit with every penny going into delivering the best experience possible.</p>
<p class="pb-2 pb-lg-4 pb-xl-5 mb-3">In-person conferences are the best way to meet like-minded people who enjoy building apps with Swift. You can also learn from the best people in the industry and chat about all things Swift.</p>
#else:
<p>Founded by <a href="https://twitter.com/Adam9Rush" target="_blank">Adam Rush</a> in 2019, SwiftLeeds has set out to bring a modern, inclusive conference to the north of the UK.</p>
<p>Ran by just a handful of community volunteers, SwiftLeeds is entirely non-profit with every penny going into delivering the best experience possible.</p>
<p class="pb-2 pb-lg-4 pb-xl-5 mb-3">In-person conferences are the best way to meet like-minded people who enjoy building apps with Swift. You can also learn from the best people in the industry and chat about all things Swift.</p>
#endif
</div>
<div class="col-xl-6 col-lg-7 offset-xl-1 position-relative">

Expand Down
10 changes: 10 additions & 0 deletions Resources/Views/Shared/_footer.leaf
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@
</li>
</ul>
<div class="d-flex pt-2 pt-sm-3 pt-md-4">
#if(social):
#for(link in social.socialLinks):
#if(link.id != "spotify"):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is needed, we can add Spotify. There was no reason for it to be header only aside from I missed it.

<a href="#(link.url)" class="btn btn-icon btn-sm btn-secondary btn-#(link.id) rounded-circle me-3" #if(link.id == "mastodon"):rel="me"#endif>
<i class="#(link.icon)"></i>
</a>
#endif
#endfor
#else:
<a href="https://twitter.com/swift_leeds" class="btn btn-icon btn-sm btn-secondary btn-twitter rounded-circle me-3">
<i class="bx bxl-twitter"></i>
</a>
Expand All @@ -42,6 +51,7 @@
<a href="https://www.flickr.com/photos/196979204@N02/albums/72177720303878744" class="btn btn-icon btn-sm btn-secondary btn-flickr rounded-circle me-3">
<i class="bx bxl-flickr"></i>
</a>
#endif
</div>
</div>

Expand Down
10 changes: 10 additions & 0 deletions Resources/Views/Shared/_header.leaf
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@

<li class="nav-item d-none d-sm-none d-md-none d-lg-block mx-auto"></li>

#if(social):
#for(link in social.socialLinks):
<li class="nav-item">
<a href="#(link.url)" target="_blank" class="nav-link" #if(link.id == "mastodon"):rel="me"#endif>
<i class="#(link.icon)"></i> <span class="d-block d-sm-block d-md-block d-lg-none" style="margin-left: 6px;">#(link.name)</span>
</a>
</li>
#endfor
#else:
<li class="nav-item">
<a href="https://twitter.com/swift_leeds" target="_blank" class="nav-link">
<i class="bx bxl-twitter"></i> <span class="d-block d-sm-block d-md-block d-lg-none" style="margin-left: 6px;">Twitter</span>
Expand Down Expand Up @@ -76,6 +85,7 @@
<i class="bx bxl-spotify"></i> <span class="d-block d-sm-block d-md-block d-lg-none" style="margin-left: 6px;">Spotify</span>
</a>
</li>
#endif
</ul>
</div>
#if(false):
Expand Down
2 changes: 2 additions & 0 deletions Sources/App/Context/HomeContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ struct HomeContext: Content {
var schedule: [ScheduleDay] = []
var phase: PhaseContext? = nil
var event: EventContext? = nil
var about: AboutResponse? = nil
var social: SocialResponse? = nil
}

struct EventContext: Codable {
Expand Down
27 changes: 27 additions & 0 deletions Sources/App/Features/About/Controllers/AboutAPIController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Vapor

struct AboutAPIController: RouteCollection {
func boot(routes: RoutesBuilder) throws {
routes.get(use: onGet)
}

@Sendable func onGet(request: Request) async throws -> Response {
let aboutData = AboutResponse(
title: "About",
description: [
"Founded by Adam Rush in 2019, SwiftLeeds has set out to bring a modern, inclusive conference to the north of the UK.",
"Ran by just a handful of community volunteers, SwiftLeeds is entirely non-profit with every penny going into delivering the best experience possible.",
"In-person conferences are the best way to meet like-minded people who enjoy building apps with Swift. You can also learn from the best people in the industry and chat about all things Swift."
],
foundedYear: "2019",
founderName: "Adam Rush",
founderTwitter: "https://twitter.com/Adam9Rush"
)

let response = GenericResponse(
data: aboutData
)

return try await response.encodeResponse(for: request)
}
}
10 changes: 10 additions & 0 deletions Sources/App/Features/About/Models/AboutResponse.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Foundation
import Vapor

struct AboutResponse: Content {
let title: String
let description: [String]
let foundedYear: String
let founderName: String
let founderTwitter: String
Comment on lines +7 to +9
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of extracting these values? How can we leverage the new team API to prevent duplicating data?

}
40 changes: 39 additions & 1 deletion Sources/App/Features/Home/HomeRouteController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ struct HomeRouteController: RouteCollection {

let phase = try getPhase(req: req, event: event)

// Fetch About and Social data from API endpoints to maintain single source of truth
let aboutData: AboutResponse? = try await fetchAboutData(req: req)
let socialData: SocialResponse? = try await fetchSocialData(req: req)
Comment on lines +97 to +98
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're adding a lot of complexity to the views to handle the fact these are optional. Let's make them required, which will be easier when we address the other PR comment, and then simplify the UI to always use it.


let schedule = event.days
.map { day in
ScheduleDay(
Expand All @@ -118,7 +122,9 @@ struct HomeRouteController: RouteCollection {
dropInSessions: dropInSessions,
schedule: phase.showSchedule ? schedule : [],
phase: PhaseContext(phase: phase, event: event),
event: eventContext
event: eventContext,
about: aboutData,
social: socialData
)
}

Expand Down Expand Up @@ -188,6 +194,38 @@ struct HomeRouteController: RouteCollection {

return try await Event.getCurrent(on: req.db)
}

private func fetchAboutData(req: Request) async throws -> AboutResponse? {
do {
// Make internal request to the About API endpoint
let aboutRequest = Request(application: req.application, method: .GET, url: URI(string: "/api/v2/about"), on: req.eventLoop)
let aboutController = AboutAPIController()
let aboutResponse = try await aboutController.onGet(request: aboutRequest)

guard let data = aboutResponse.body.data else { return nil }
let genericResponse = try JSONDecoder().decode(GenericResponse<AboutResponse>.self, from: data)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave the teams API #159 a free pass because it wasn't decoding JSON, but we absolutely should not be calling our own internal APIs through the service and then parsing JSON responses - it's extremely wasteful on bandwidth, memory, and compute cycles.

I'd recommend pulling the data out into a more accessible location first, and accessing it from the API and HomeRouteController.

return genericResponse.data
} catch {
req.logger.warning("Failed to fetch about data from API: \(error)")
return nil
}
}

private func fetchSocialData(req: Request) async throws -> SocialResponse? {
do {
// Make internal request to the Social API endpoint
let socialRequest = Request(application: req.application, method: .GET, url: URI(string: "/api/v2/social"), on: req.eventLoop)
let socialController = SocialAPIController()
let socialResponse = try await socialController.onGet(request: socialRequest)

guard let data = socialResponse.body.data else { return nil }
let genericResponse = try JSONDecoder().decode(GenericResponse<SocialResponse>.self, from: data)
return genericResponse.data
} catch {
req.logger.warning("Failed to fetch social data from API: \(error)")
return nil
}
}
}

struct Phase {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Vapor

struct SocialAPIController: RouteCollection {
func boot(routes: RoutesBuilder) throws {
routes.get(use: onGet)
}

@Sendable func onGet(request: Request) async throws -> Response {
let socialData = SocialResponse(socialLinks: [
SocialLink(id: "twitter", name: "Twitter", url: "https://twitter.com/swift_leeds", icon: "bx bxl-twitter", displayName: "@Swift_Leeds", order: 1),
SocialLink(id: "mastodon", name: "Mastodon", url: "https://iosdev.space/@swiftleeds", icon: "bx bxl-mastodon", displayName: "@swiftleeds", order: 2),
SocialLink(id: "youtube", name: "YouTube", url: "https://www.youtube.com/channel/UCCq1K0eWKZFBCpqaC3n8V1g", icon: "bx bxl-youtube", displayName: nil, order: 3),
SocialLink(id: "slack", name: "Join Slack", url: "https://join.slack.com/t/swiftleedsworkspace/shared_invite/zt-wkmr6pif-ZDCdDeHM60jcBUy0BxHdCQ", icon: "bx bxl-slack", displayName: nil, order: 4),
SocialLink(id: "flickr", name: "Flickr", url: "https://www.flickr.com/photos/196979204@N02/albums/72177720303878744", icon: "bx bxl-flickr", displayName: nil, order: 5),
SocialLink(id: "spotify", name: "Spotify", url: "https://open.spotify.com/show/3pHsjVt54MDDHdzZce7ezl", icon: "bx bxl-spotify", displayName: nil, order: 6)
])

let response = GenericResponse(
data: socialData
)

return try await response.encodeResponse(for: request)
}
}
15 changes: 15 additions & 0 deletions Sources/App/Features/Social/Models/SocialResponse.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Foundation
import Vapor

struct SocialResponse: Content {
let socialLinks: [SocialLink]
}

struct SocialLink: Content {
let id: String
let name: String
let url: String
let icon: String
let displayName: String?
let order: Int
}
2 changes: 2 additions & 0 deletions Sources/App/routes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ func routes(_ app: Application) throws {

let apiV2Routes = app.grouped("api", "v2")
try apiV2Routes.grouped("schedule").register(collection: ScheduleAPIControllerV2())
try apiV2Routes.grouped("about").register(collection: AboutAPIController())
try apiV2Routes.grouped("social").register(collection: SocialAPIController())

// MARK: - Admin Routes
let adminRoutes = app.grouped("admin").grouped(AdminMiddleware())
Expand Down