Files
vapor-po/Sources/App/Views/HTMXExtensions.swift

205 lines
4.6 KiB
Swift

import Elementary
import ElementaryHTMX
import Fluent
import SharedModels
extension HTMLAttribute.hx {
static func get(route: SharedModels.ViewRoute) -> HTMLAttribute {
get(SharedModels.ViewRoute.router.path(for: route))
}
static func post(route: SharedModels.ViewRoute) -> HTMLAttribute {
post(SharedModels.ViewRoute.router.path(for: route))
}
static func put(route: SharedModels.ViewRoute) -> HTMLAttribute {
put(SharedModels.ViewRoute.router.path(for: route))
}
static func delete(route: SharedModels.ViewRoute) -> HTMLAttribute {
delete(SharedModels.ViewRoute.router.path(for: route))
}
}
extension HTMLAttribute.hx {
static func target(_ target: HXTarget) -> HTMLAttribute {
Self.target(target.selector)
}
}
extension HTMLAttribute.hx where Tag: HTMLTrait.Attributes.Global {
static func on(_ event: HXOnEvent, value: String) -> HTMLAttribute {
HTMLAttribute.custom(name: "hx-on::\(event.rawValue)", value: value)
}
static func on(_ event: HXOnEvent, _ value: HXOnValue) -> HTMLAttribute {
on(event, value: value.value)
}
static func on(_ event: HXOnEvent, _ values: HXOnValue...) -> HTMLAttribute {
on(event, value: values.value)
}
}
enum HXOnEvent: String {
case afterRequest = "after-request"
}
indirect enum HXOnValue {
case ifSuccessful([Self])
case resetForm
case setWindowLocation(String)
case toggleContent(id: String)
static func toggleContent(_ toggle: Toggle) -> Self {
toggleContent(id: toggle.rawValue)
}
static func setWindowLocation(to route: ViewRoute) -> Self {
setWindowLocation(ViewRoute.router.path(for: route))
}
static func ifSuccessful(_ values: Self...) -> Self {
.ifSuccessful(values)
}
fileprivate var value: String {
switch self {
case .resetForm:
return "this.reset();"
case let .toggleContent(toggle):
return "toggleContent('\(toggle)');"
case let .setWindowLocation(string):
return "window.location.href='\(string)';"
case let .ifSuccessful(values):
return "if(event.detail.successful) \(values.value)"
}
}
enum Toggle: String {
case float
}
}
extension Array where Element == HXOnValue {
var value: String {
return map(\.value).joined(separator: " ")
}
}
extension HTMLAttribute where Tag: HTMLTrait.Attributes.Global {
static func id(_ key: IDKey) -> Self {
id(key.description)
}
}
enum IDKey: CustomStringConvertible {
case branch(Branch)
case employee(Employee)
case float
case purchaseOrder(PurchaseOrder? = nil)
case user(User)
case vendor(Vendor)
var description: String {
switch self {
case let .branch(key): return "branch-\(key)"
case let .employee(key): return "employee-\(key)"
case .float: return "float"
case let .purchaseOrder(key):
guard let key else { return "purchase-order" }
return "purchase-order-\(key)"
case let .user(key): return "user-\(key)"
case let .vendor(key): return "vendor-\(key)"
}
}
enum Branch: CustomStringConvertible {
case list
case form
case row(id: VendorBranch.ID)
var description: String {
switch self {
case .list: return "list"
case .form: return "form"
case let .row(id): return id.uuidString
}
}
}
enum Employee: CustomStringConvertible {
case table
case row(id: SharedModels.Employee.ID)
var description: String {
switch self {
case .table: return "table"
case let .row(id): return "\(id)"
}
}
}
enum PurchaseOrder: CustomStringConvertible {
case content
case row(id: SharedModels.PurchaseOrder.ID)
case search
case table
var description: String {
switch self {
case .content: return "content"
case let .row(id): return "\(id)"
case .search: return "search"
case .table: return "table"
}
}
}
enum User: CustomStringConvertible {
case form
case row(id: SharedModels.User.ID)
case table
var description: String {
switch self {
case .form: return "form"
case .table: return "table"
case let .row(id): return "\(id)"
}
}
}
enum Vendor: CustomStringConvertible {
case form
case row(id: SharedModels.Vendor.ID)
var description: String {
switch self {
case .form: return "form"
case let .row(id): return "\(id)"
}
}
}
}
enum HXTarget: CustomStringConvertible {
case body
case id(IDKey)
case this
var selector: String {
switch self {
case .body: return "body"
case let .id(key): return "#\(key)"
case .this: return "this"
}
}
var description: String { selector }
}