First version
This commit is contained in:
41
CHDataManagement/Page Elements/FeedEntry.swift
Normal file
41
CHDataManagement/Page Elements/FeedEntry.swift
Normal file
@ -0,0 +1,41 @@
|
||||
import Foundation
|
||||
|
||||
struct FeedEntry {
|
||||
|
||||
let data: FeedEntryData
|
||||
|
||||
init(data: FeedEntryData) {
|
||||
self.data = data
|
||||
}
|
||||
|
||||
func addContent(to result: inout String) {
|
||||
#warning("TODO: Select CSS classes based on existence of link (hover effects, mouse pointer")
|
||||
result += "<div class='card'>"
|
||||
ImageGallery(id: data.entryId, images: data.images)
|
||||
.addContent(to: &result)
|
||||
|
||||
if let url = data.link?.url {
|
||||
result += "<div class=\"card-content\" onclick=\"window.location.href='\(url)'\">"
|
||||
} else {
|
||||
result += "<div class=\"card-content\">"
|
||||
}
|
||||
result += "<h3>\(data.textAboveTitle)</h3>"
|
||||
if let title = data.title {
|
||||
result += "<h2>\(title.htmlEscaped())</h2>"
|
||||
}
|
||||
if !data.tags.isEmpty {
|
||||
result += "<div class=\"tags\">"
|
||||
for tag in data.tags {
|
||||
result += "<a class=\"tag\" href=\"\(tag.url)\">\(tag.name)</a>"
|
||||
}
|
||||
result += "</div>"
|
||||
}
|
||||
for paragraph in data.text {
|
||||
result += "<p>\(paragraph)</p>"
|
||||
}
|
||||
if let url = data.link {
|
||||
result += "<div class=\"link-center\"><div class=\"link\">\(url.text)</div></div>"
|
||||
}
|
||||
result += "</div></div>" // Closes card-content and card
|
||||
}
|
||||
}
|
44
CHDataManagement/Page Elements/FeedEntryContent.swift
Normal file
44
CHDataManagement/Page Elements/FeedEntryContent.swift
Normal file
@ -0,0 +1,44 @@
|
||||
//import Elementary
|
||||
|
||||
struct FeedEntryContent<Content> {
|
||||
|
||||
let url: String?
|
||||
|
||||
let inner: Content
|
||||
|
||||
init(url: String?, inner: Content) {
|
||||
self.url = url
|
||||
self.inner = inner
|
||||
}
|
||||
|
||||
func addContent(to result: inout String, inner: () -> Void) -> Void {
|
||||
if let url {
|
||||
result += "<div class=\"card-content\" onclick=\"window.location.href='\(url)'\">"
|
||||
} else {
|
||||
result += "<div class=\"card-content\">"
|
||||
}
|
||||
inner()
|
||||
result += "</div>"
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
extension FeedEntryContent: HTML where Content: HTML {
|
||||
|
||||
init(url: String?, @HTMLBuilder content: () -> Content) {
|
||||
self.init(url: url, inner: content())
|
||||
}
|
||||
|
||||
var content: some HTML {
|
||||
if let url {
|
||||
div(.class("card-content"), .on(.click, "window.location.href='\(url)'")) {
|
||||
inner
|
||||
}
|
||||
} else {
|
||||
div(.class("card-content")) {
|
||||
inner
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
51
CHDataManagement/Page Elements/FeedEntryData.swift
Normal file
51
CHDataManagement/Page Elements/FeedEntryData.swift
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
struct FeedEntryData {
|
||||
|
||||
let entryId: String
|
||||
|
||||
let title: String?
|
||||
|
||||
let textAboveTitle: String
|
||||
|
||||
let link: Link?
|
||||
|
||||
let tags: [Tag]
|
||||
|
||||
let text: [String]
|
||||
|
||||
let images: [Image]
|
||||
|
||||
init(entryId: String, title: String?, textAboveTitle: String, link: Link?, tags: [Tag], text: [String], images: [Image]) {
|
||||
self.entryId = entryId
|
||||
self.title = title
|
||||
self.textAboveTitle = textAboveTitle
|
||||
self.link = link
|
||||
self.tags = tags
|
||||
self.text = text
|
||||
self.images = images
|
||||
}
|
||||
|
||||
struct Link {
|
||||
|
||||
let url: String
|
||||
|
||||
let text: String
|
||||
|
||||
}
|
||||
|
||||
struct Tag {
|
||||
|
||||
let name: String
|
||||
|
||||
let url: String
|
||||
|
||||
}
|
||||
|
||||
struct Image {
|
||||
|
||||
let mainImageUrl: String
|
||||
|
||||
let altText: String
|
||||
|
||||
}
|
||||
}
|
83
CHDataManagement/Page Elements/ImageGallery.swift
Normal file
83
CHDataManagement/Page Elements/ImageGallery.swift
Normal file
@ -0,0 +1,83 @@
|
||||
import Foundation
|
||||
|
||||
struct ImageGallery {
|
||||
|
||||
let id: String
|
||||
|
||||
let images: [FeedEntryData.Image]
|
||||
|
||||
init(id: String, images: [FeedEntryData.Image]) {
|
||||
self.id = id
|
||||
self.images = images
|
||||
}
|
||||
|
||||
func addContent(to result: inout String) {
|
||||
guard !images.isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
result += "<div id=\"s\(id)\" class=\"swiper\"><div class=\"swiper-wrapper\">"
|
||||
|
||||
guard images.count > 1 else {
|
||||
let image = images[0]
|
||||
result += "<div class=\"swiper-slide\"><img src=\(image.mainImageUrl) loading=\"lazy\" alt=\"\(image.altText.htmlEscaped())\"></div>"
|
||||
result += "</div></div>" // Close swiper, swiper-wrapper
|
||||
return
|
||||
}
|
||||
|
||||
for image in images {
|
||||
// TODO: Use different images based on device
|
||||
result += "<div class=\"swiper-slide\">"
|
||||
result += "<img src=\(image.mainImageUrl) loading=\"lazy\" alt=\"\(image.altText.htmlEscaped())\">"
|
||||
result += "<div class=\"swiper-lazy-preloader swiper-lazy-preloader-white\"></div>"
|
||||
result += "</div>" // Close swiper-slide
|
||||
}
|
||||
|
||||
result += "<div class=\"swiper-button-next\"></div>"
|
||||
result += "<div class=\"swiper-button-prev\"></div>"
|
||||
result += "<div class=\"swiper-pagination\"></div>"
|
||||
result += "</div></div>" // Close swiper, swiper-wrapper
|
||||
}
|
||||
|
||||
static func swiperInit(id: String) -> String {
|
||||
"""
|
||||
var swiper\(id) = new Swiper("#\(id)", {
|
||||
loop: true,
|
||||
slidesPerView: 1,
|
||||
spaceBetween: 30,
|
||||
centeredSlides: true,
|
||||
keyboard: { enabled: true },
|
||||
pagination: {
|
||||
el: "#\(id) .swiper-pagination",
|
||||
clickable: true
|
||||
},
|
||||
navigation: {
|
||||
nextEl: "#\(id) .swiper-button-next",
|
||||
prevEl: "#\(id) .swiper-button-prev"
|
||||
}
|
||||
});
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
extension ImageGallery: HTML {
|
||||
|
||||
var content: some HTML {
|
||||
div(.id(id), .class("swiper")) {
|
||||
div(.class("swiper-wrapper")) {
|
||||
for image in images {
|
||||
div(.class("swiper-slide")) {
|
||||
// TODO: Use different images based on device
|
||||
img(.src(image.mainImageUrl), .lazyLoad)
|
||||
div(.class("swiper-lazy-preloader"), .class("swiper-lazy-preloader-white")) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
div(.class("swiper-button-next")) { }
|
||||
div(.class("swiper-button-prev")) { }
|
||||
div(.class("swiper-pagination")) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
36
CHDataManagement/Page Elements/PageHead.swift
Normal file
36
CHDataManagement/Page Elements/PageHead.swift
Normal file
@ -0,0 +1,36 @@
|
||||
import Foundation
|
||||
//import Elementary
|
||||
|
||||
struct PageHead {
|
||||
|
||||
let title: String
|
||||
|
||||
let description: String
|
||||
|
||||
var content: String {
|
||||
"""
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>\(title)</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" />
|
||||
<meta name="description" content="\(description)">
|
||||
<link rel="stylesheet" href="/assets/swiper/swiper.css" />
|
||||
<link rel="stylesheet" href="/assets/css/style.css" />
|
||||
</head>
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
extension PageHead: HTML {
|
||||
|
||||
var content: some HTML {
|
||||
meta(.charset(.utf8))
|
||||
meta(.title(title))
|
||||
meta(.name(.viewport), .content("width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1"))
|
||||
meta(.name(.description), .content(description))
|
||||
link(.rel(.stylesheet), .href("style.css"))
|
||||
link(.rel(.stylesheet), .href("swiper.css"))
|
||||
}
|
||||
}
|
||||
*/
|
Reference in New Issue
Block a user