Compare commits
2 Commits
1663c0a514
...
69e8acc5d8
| Author | SHA1 | Date | |
|---|---|---|---|
|
69e8acc5d8
|
|||
|
066b3003d0
|
@@ -41,7 +41,17 @@ extension DatabaseClient.Projects: TestDependencyKey {
|
|||||||
.with(\.$equipment)
|
.with(\.$equipment)
|
||||||
.with(\.$equivalentLengths)
|
.with(\.$equivalentLengths)
|
||||||
.with(\.$rooms)
|
.with(\.$rooms)
|
||||||
.with(\.$trunks, { $0.with(\.$rooms) })
|
.with(
|
||||||
|
\.$trunks,
|
||||||
|
{ trunk in
|
||||||
|
trunk.with(
|
||||||
|
\.$rooms,
|
||||||
|
{
|
||||||
|
$0.with(\.$room)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
.filter(\.$id == id)
|
.filter(\.$id == id)
|
||||||
.first()
|
.first()
|
||||||
else {
|
else {
|
||||||
@@ -51,7 +61,7 @@ extension DatabaseClient.Projects: TestDependencyKey {
|
|||||||
// TODO: Different error ??
|
// TODO: Different error ??
|
||||||
guard let equipmentInfo = model.equipment else { return nil }
|
guard let equipmentInfo = model.equipment else { return nil }
|
||||||
|
|
||||||
let trunks = try await model.trunks.toDTO(on: database)
|
let trunks = try model.trunks.toDTO()
|
||||||
|
|
||||||
return try .init(
|
return try .init(
|
||||||
project: model.toDTO(),
|
project: model.toDTO(),
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ extension DatabaseClient.TrunkSizes: TestDependencyKey {
|
|||||||
type: request.type
|
type: request.type
|
||||||
)
|
)
|
||||||
try await model.save(on: database)
|
try await model.save(on: database)
|
||||||
try await roomProxies.append(model.toDTO(on: database))
|
roomProxies.append(
|
||||||
|
.init(room: try room.toDTO(), registers: registers)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return try .init(
|
return try .init(
|
||||||
@@ -60,23 +62,30 @@ extension DatabaseClient.TrunkSizes: TestDependencyKey {
|
|||||||
fetch: { projectID in
|
fetch: { projectID in
|
||||||
try await TrunkModel.query(on: database)
|
try await TrunkModel.query(on: database)
|
||||||
.with(\.$project)
|
.with(\.$project)
|
||||||
.with(\.$rooms)
|
.with(\.$rooms, { $0.with(\.$room) })
|
||||||
.filter(\.$project.$id == projectID)
|
.filter(\.$project.$id == projectID)
|
||||||
.all()
|
.all()
|
||||||
.toDTO(on: database)
|
.toDTO()
|
||||||
},
|
},
|
||||||
get: { id in
|
get: { id in
|
||||||
guard let model = try await TrunkModel.find(id, on: database) else {
|
guard
|
||||||
|
let model =
|
||||||
|
try await TrunkModel
|
||||||
|
.query(on: database)
|
||||||
|
.with(\.$rooms, { $0.with(\.$room) })
|
||||||
|
.filter(\.$id == id)
|
||||||
|
.first()
|
||||||
|
else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return try await model.toDTO(on: database)
|
return try model.toDTO()
|
||||||
},
|
},
|
||||||
update: { id, updates in
|
update: { id, updates in
|
||||||
guard
|
guard
|
||||||
let model =
|
let model =
|
||||||
try await TrunkModel
|
try await TrunkModel
|
||||||
.query(on: database)
|
.query(on: database)
|
||||||
.with(\.$rooms)
|
.with(\.$rooms, { $0.with(\.$room) })
|
||||||
.filter(\.$id == id)
|
.filter(\.$id == id)
|
||||||
.first()
|
.first()
|
||||||
else {
|
else {
|
||||||
@@ -84,7 +93,7 @@ extension DatabaseClient.TrunkSizes: TestDependencyKey {
|
|||||||
}
|
}
|
||||||
try updates.validate()
|
try updates.validate()
|
||||||
try await model.applyUpdates(updates, on: database)
|
try await model.applyUpdates(updates, on: database)
|
||||||
return try await model.toDTO(on: database)
|
return try model.toDTO()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -201,10 +210,10 @@ final class TrunkRoomModel: Model, @unchecked Sendable {
|
|||||||
self.type = type.rawValue
|
self.type = type.rawValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func toDTO(on database: any Database) async throws -> TrunkSize.RoomProxy {
|
func toDTO() throws -> TrunkSize.RoomProxy {
|
||||||
guard let room = try await RoomModel.find($room.id, on: database) else {
|
// guard let room = try await RoomModel.find($room.id, on: database) else {
|
||||||
throw NotFoundError()
|
// throw NotFoundError()
|
||||||
}
|
// }
|
||||||
return .init(
|
return .init(
|
||||||
room: try room.toDTO(),
|
room: try room.toDTO(),
|
||||||
registers: registers
|
registers: registers
|
||||||
@@ -251,18 +260,22 @@ final class TrunkModel: Model, @unchecked Sendable {
|
|||||||
self.name = name
|
self.name = name
|
||||||
}
|
}
|
||||||
|
|
||||||
func toDTO(on database: any Database) async throws -> TrunkSize {
|
func toDTO() throws -> TrunkSize {
|
||||||
let rooms = try await withThrowingTaskGroup(of: TrunkSize.RoomProxy.self) { group in
|
// let rooms = try await withThrowingTaskGroup(of: TrunkSize.RoomProxy.self) { group in
|
||||||
for room in self.rooms {
|
// for room in self.rooms {
|
||||||
group.addTask {
|
// group.addTask {
|
||||||
try await room.toDTO(on: database)
|
// try await room.toDTO(on: database)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return try await group.reduce(into: [TrunkSize.RoomProxy]()) {
|
// return try await group.reduce(into: [TrunkSize.RoomProxy]()) {
|
||||||
$0.append($1)
|
// $0.append($1)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
let rooms = try rooms.reduce(into: [TrunkSize.RoomProxy]()) {
|
||||||
|
$0.append(try $1.toDTO())
|
||||||
}
|
}
|
||||||
|
|
||||||
return try .init(
|
return try .init(
|
||||||
@@ -340,17 +353,17 @@ final class TrunkModel: Model, @unchecked Sendable {
|
|||||||
|
|
||||||
extension Array where Element == TrunkModel {
|
extension Array where Element == TrunkModel {
|
||||||
|
|
||||||
func toDTO(on database: any Database) async throws -> [TrunkSize] {
|
func toDTO() throws -> [TrunkSize] {
|
||||||
try await withThrowingTaskGroup(of: TrunkSize.self) { group in
|
// try await withThrowingTaskGroup(of: TrunkSize.self) { group in
|
||||||
for model in self {
|
// for model in self {
|
||||||
group.addTask {
|
// group.addTask {
|
||||||
try await model.toDTO(on: database)
|
// try await model.toDTO(on: database)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return try await group.reduce(into: [TrunkSize]()) {
|
return try reduce(into: [TrunkSize]()) {
|
||||||
$0.append($1)
|
$0.append(try $1.toDTO())
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,14 @@ import ManualDCore
|
|||||||
|
|
||||||
extension DatabaseClient {
|
extension DatabaseClient {
|
||||||
|
|
||||||
|
func calculateDuctSizes(
|
||||||
|
details: Project.Detail
|
||||||
|
) async throws -> (DuctSizes, DuctSizeSharedRequest) {
|
||||||
|
let (rooms, shared) = try await calculateRoomDuctSizes(details: details)
|
||||||
|
let (trunks, _) = try await calculateTrunkDuctSizes(details: details)
|
||||||
|
return (.init(rooms: rooms, trunks: trunks), shared)
|
||||||
|
}
|
||||||
|
|
||||||
func calculateDuctSizes(
|
func calculateDuctSizes(
|
||||||
projectID: Project.ID
|
projectID: Project.ID
|
||||||
) async throws -> (DuctSizes, DuctSizeSharedRequest, [Room]) {
|
) async throws -> (DuctSizes, DuctSizeSharedRequest, [Room]) {
|
||||||
@@ -24,6 +32,16 @@ extension DatabaseClient {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func calculateRoomDuctSizes(
|
||||||
|
details: Project.Detail
|
||||||
|
) async throws -> ([DuctSizes.RoomContainer], DuctSizeSharedRequest) {
|
||||||
|
@Dependency(\.manualD) var manualD
|
||||||
|
|
||||||
|
let shared = try sharedDuctRequest(details: details)
|
||||||
|
let rooms = try await manualD.calculateRoomSizes(rooms: details.rooms, sharedRequest: shared)
|
||||||
|
return (rooms, shared)
|
||||||
|
}
|
||||||
|
|
||||||
func calculateRoomDuctSizes(
|
func calculateRoomDuctSizes(
|
||||||
projectID: Project.ID
|
projectID: Project.ID
|
||||||
) async throws -> ([DuctSizes.RoomContainer], DuctSizeSharedRequest) {
|
) async throws -> ([DuctSizes.RoomContainer], DuctSizeSharedRequest) {
|
||||||
@@ -40,6 +58,20 @@ extension DatabaseClient {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func calculateTrunkDuctSizes(
|
||||||
|
details: Project.Detail
|
||||||
|
) async throws -> ([DuctSizes.TrunkContainer], DuctSizeSharedRequest) {
|
||||||
|
@Dependency(\.manualD) var manualD
|
||||||
|
|
||||||
|
let shared = try sharedDuctRequest(details: details)
|
||||||
|
let trunks = try await manualD.calculateTrunkSizes(
|
||||||
|
rooms: details.rooms,
|
||||||
|
trunks: details.trunks,
|
||||||
|
sharedRequest: shared
|
||||||
|
)
|
||||||
|
return (trunks, shared)
|
||||||
|
}
|
||||||
|
|
||||||
func calculateTrunkDuctSizes(
|
func calculateTrunkDuctSizes(
|
||||||
projectID: Project.ID
|
projectID: Project.ID
|
||||||
) async throws -> ([DuctSizes.TrunkContainer], DuctSizeSharedRequest) {
|
) async throws -> ([DuctSizes.TrunkContainer], DuctSizeSharedRequest) {
|
||||||
@@ -57,6 +89,32 @@ extension DatabaseClient {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sharedDuctRequest(details: Project.Detail) throws -> DuctSizeSharedRequest {
|
||||||
|
guard
|
||||||
|
let dfrResponse = designFrictionRate(
|
||||||
|
componentLosses: details.componentLosses,
|
||||||
|
equipmentInfo: details.equipmentInfo,
|
||||||
|
equivalentLengths: details.maxContainer
|
||||||
|
)
|
||||||
|
else {
|
||||||
|
throw ProjectClientError("Project not complete.")
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let projectSHR = details.project.sensibleHeatRatio else {
|
||||||
|
throw ProjectClientError("Project sensible heat ratio not set.")
|
||||||
|
}
|
||||||
|
|
||||||
|
let ensuredTEL = try dfrResponse.ensureMaxContainer()
|
||||||
|
|
||||||
|
return .init(
|
||||||
|
equipmentInfo: dfrResponse.equipmentInfo,
|
||||||
|
maxSupplyLength: ensuredTEL.supply,
|
||||||
|
maxReturnLenght: ensuredTEL.return,
|
||||||
|
designFrictionRate: dfrResponse.designFrictionRate,
|
||||||
|
projectSHR: projectSHR
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func sharedDuctRequest(_ projectID: Project.ID) async throws -> DuctSizeSharedRequest {
|
func sharedDuctRequest(_ projectID: Project.ID) async throws -> DuctSizeSharedRequest {
|
||||||
|
|
||||||
guard let dfrResponse = try await designFrictionRate(projectID: projectID) else {
|
guard let dfrResponse = try await designFrictionRate(projectID: projectID) else {
|
||||||
@@ -107,25 +165,36 @@ extension DatabaseClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func designFrictionRate(
|
func designFrictionRate(
|
||||||
projectID: Project.ID
|
componentLosses: [ComponentPressureLoss],
|
||||||
) async throws -> DesignFrictionRateResponse? {
|
equipmentInfo: EquipmentInfo,
|
||||||
guard let equipmentInfo = try await equipment.fetch(projectID) else {
|
equivalentLengths: EffectiveLength.MaxContainer
|
||||||
return nil
|
) -> DesignFrictionRateResponse? {
|
||||||
}
|
guard let tel = equivalentLengths.total,
|
||||||
|
componentLosses.count > 0
|
||||||
|
else { return nil }
|
||||||
|
|
||||||
let equivalentLengths = try await effectiveLength.fetchMax(projectID)
|
let availableStaticPressure = equipmentInfo.staticPressure - componentLosses.total
|
||||||
guard let tel = equivalentLengths.total else { return nil }
|
|
||||||
|
|
||||||
let componentLosses = try await componentLoss.fetch(projectID)
|
|
||||||
guard componentLosses.count > 0 else { return nil }
|
|
||||||
|
|
||||||
let availableStaticPressure =
|
|
||||||
equipmentInfo.staticPressure - componentLosses.total
|
|
||||||
|
|
||||||
return .init(
|
return .init(
|
||||||
designFrictionRate: (availableStaticPressure * 100) / tel,
|
designFrictionRate: (availableStaticPressure * 100) / tel,
|
||||||
equipmentInfo: equipmentInfo,
|
equipmentInfo: equipmentInfo,
|
||||||
telMaxContainer: equivalentLengths
|
telMaxContainer: equivalentLengths
|
||||||
)
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func designFrictionRate(
|
||||||
|
projectID: Project.ID
|
||||||
|
) async throws -> DesignFrictionRateResponse? {
|
||||||
|
|
||||||
|
guard let equipmentInfo = try await equipment.fetch(projectID) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return try await designFrictionRate(
|
||||||
|
componentLosses: componentLoss.fetch(projectID),
|
||||||
|
equipmentInfo: equipmentInfo,
|
||||||
|
equivalentLengths: effectiveLength.fetchMax(projectID)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,29 +48,72 @@ extension ProjectClient: DependencyKey {
|
|||||||
|
|
||||||
extension DatabaseClient {
|
extension DatabaseClient {
|
||||||
|
|
||||||
|
// fileprivate func makePdfRequest(_ projectID: Project.ID) async throws -> PdfClient.Request {
|
||||||
|
// @Dependency(\.manualD) var manualD
|
||||||
|
//
|
||||||
|
// guard let project = try await projects.get(projectID) else {
|
||||||
|
// throw ProjectClientError("Project not found. id: \(projectID)")
|
||||||
|
// }
|
||||||
|
// let frictionRateResponse = try await manualD.frictionRate(projectID: projectID)
|
||||||
|
// guard let frictionRate = frictionRateResponse.frictionRate else {
|
||||||
|
// throw ProjectClientError("Friction rate not found. id: \(projectID)")
|
||||||
|
// }
|
||||||
|
// let (ductSizes, sharedInfo, rooms) = try await calculateDuctSizes(projectID: projectID)
|
||||||
|
//
|
||||||
|
// return .init(
|
||||||
|
// project: project,
|
||||||
|
// rooms: rooms,
|
||||||
|
// componentLosses: frictionRateResponse.componentLosses,
|
||||||
|
// ductSizes: ductSizes,
|
||||||
|
// equipmentInfo: sharedInfo.equipmentInfo,
|
||||||
|
// maxSupplyTEL: sharedInfo.maxSupplyLength,
|
||||||
|
// maxReturnTEL: sharedInfo.maxReturnLenght,
|
||||||
|
// frictionRate: frictionRate,
|
||||||
|
// projectSHR: sharedInfo.projectSHR
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
|
||||||
fileprivate func makePdfRequest(_ projectID: Project.ID) async throws -> PdfClient.Request {
|
fileprivate func makePdfRequest(_ projectID: Project.ID) async throws -> PdfClient.Request {
|
||||||
@Dependency(\.manualD) var manualD
|
@Dependency(\.manualD) var manualD
|
||||||
|
|
||||||
guard let project = try await projects.get(projectID) else {
|
guard let projectDetails = try await projects.detail(projectID) else {
|
||||||
throw ProjectClientError("Project not found. id: \(projectID)")
|
throw ProjectClientError("Project not found. id: \(projectID)")
|
||||||
}
|
}
|
||||||
let frictionRateResponse = try await manualD.frictionRate(projectID: projectID)
|
|
||||||
|
let (ductSizes, shared) = try await calculateDuctSizes(details: projectDetails)
|
||||||
|
|
||||||
|
let frictionRateResponse = try await manualD.frictionRate(details: projectDetails)
|
||||||
guard let frictionRate = frictionRateResponse.frictionRate else {
|
guard let frictionRate = frictionRateResponse.frictionRate else {
|
||||||
throw ProjectClientError("Friction rate not found. id: \(projectID)")
|
throw ProjectClientError("Friction rate not found. id: \(projectID)")
|
||||||
}
|
}
|
||||||
let (ductSizes, sharedInfo, rooms) = try await calculateDuctSizes(projectID: projectID)
|
|
||||||
|
|
||||||
return .init(
|
return .init(
|
||||||
project: project,
|
details: projectDetails,
|
||||||
rooms: rooms,
|
|
||||||
componentLosses: frictionRateResponse.componentLosses,
|
|
||||||
ductSizes: ductSizes,
|
ductSizes: ductSizes,
|
||||||
equipmentInfo: sharedInfo.equipmentInfo,
|
shared: shared,
|
||||||
maxSupplyTEL: sharedInfo.maxSupplyLength,
|
frictionRate: frictionRate
|
||||||
maxReturnTEL: sharedInfo.maxReturnLenght,
|
|
||||||
frictionRate: frictionRate,
|
|
||||||
projectSHR: sharedInfo.projectSHR
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension PdfClient.Request {
|
||||||
|
init(
|
||||||
|
details: Project.Detail,
|
||||||
|
ductSizes: DuctSizes,
|
||||||
|
shared: DuctSizeSharedRequest,
|
||||||
|
frictionRate: FrictionRate
|
||||||
|
) {
|
||||||
|
self.init(
|
||||||
|
project: details.project,
|
||||||
|
rooms: details.rooms,
|
||||||
|
componentLosses: details.componentLosses,
|
||||||
|
ductSizes: ductSizes,
|
||||||
|
equipmentInfo: details.equipmentInfo,
|
||||||
|
maxSupplyTEL: shared.maxSupplyLength,
|
||||||
|
maxReturnTEL: shared.maxReturnLenght,
|
||||||
|
frictionRate: frictionRate,
|
||||||
|
projectSHR: shared.projectSHR
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,102 +1,76 @@
|
|||||||
import Elementary
|
import Elementary
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public struct ResultView<
|
public struct ResultView<ValueView, ErrorView>: HTML where ValueView: HTML, ErrorView: HTML {
|
||||||
V: Sendable,
|
|
||||||
E: Error,
|
|
||||||
ValueView: HTML,
|
|
||||||
ErrorView: HTML
|
|
||||||
>: HTML {
|
|
||||||
|
|
||||||
let onSuccess: @Sendable (V) -> ValueView
|
let result: Result<ValueView, any Error>
|
||||||
let onError: @Sendable (E) -> ErrorView
|
let errorView: @Sendable (any Error) -> ErrorView
|
||||||
let result: Result<V, E>
|
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
result: Result<V, E>,
|
_ content: @escaping @Sendable () async throws -> ValueView,
|
||||||
@HTMLBuilder onSuccess: @escaping @Sendable (V) -> ValueView,
|
onError: @escaping @Sendable (any Error) -> ErrorView
|
||||||
@HTMLBuilder onError: @escaping @Sendable (E) -> ErrorView
|
) async {
|
||||||
) {
|
self.result = await Result(catching: content)
|
||||||
self.result = result
|
self.errorView = onError
|
||||||
self.onError = onError
|
|
||||||
self.onSuccess = onSuccess
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: some HTML {
|
public var body: some HTML {
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let value):
|
case .success(let view):
|
||||||
onSuccess(value)
|
view
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
onError(error)
|
errorView(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ResultView {
|
extension ResultView where ErrorView == Styleguide.ErrorView {
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
result: Result<V, E>,
|
_ content: @escaping @Sendable () async throws -> ValueView
|
||||||
@HTMLBuilder onSuccess: @escaping @Sendable (V) -> ValueView
|
) async {
|
||||||
) where ErrorView == Styleguide.ErrorView<E> {
|
await self.init(
|
||||||
self.init(result: result, onSuccess: onSuccess) { error in
|
content,
|
||||||
Styleguide.ErrorView(error: error)
|
onError: { Styleguide.ErrorView(error: $0) }
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init<V: Sendable>(
|
||||||
|
catching: @escaping @Sendable () async throws -> V,
|
||||||
|
onSuccess content: @escaping @Sendable (V) -> ValueView
|
||||||
|
) async where ValueView: Sendable {
|
||||||
|
await self.init(
|
||||||
|
{
|
||||||
|
try await content(catching())
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
catching: @escaping @Sendable () async throws(E) -> V,
|
catching: @escaping @Sendable () async throws -> Void
|
||||||
@HTMLBuilder onSuccess: @escaping @Sendable (V) -> ValueView
|
) async where ValueView == EmptyHTML {
|
||||||
) async where ErrorView == Styleguide.ErrorView<E> {
|
|
||||||
await self.init(
|
await self.init(
|
||||||
result: .init(catching: catching),
|
catching: catching,
|
||||||
onSuccess: onSuccess
|
|
||||||
) { error in
|
|
||||||
Styleguide.ErrorView(error: error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(
|
|
||||||
catching: @escaping @Sendable () async throws(E) -> V,
|
|
||||||
) async where ErrorView == Styleguide.ErrorView<E>, V == Void, ValueView == EmptyHTML {
|
|
||||||
await self.init(
|
|
||||||
result: .init(catching: catching),
|
|
||||||
onSuccess: { EmptyHTML() }
|
onSuccess: { EmptyHTML() }
|
||||||
) { error in
|
)
|
||||||
Styleguide.ErrorView(error: error)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ResultView where V == ValueView {
|
extension ResultView: Sendable where ValueView: Sendable, ErrorView: Sendable {}
|
||||||
|
|
||||||
public init(
|
public struct ErrorView: HTML, Sendable {
|
||||||
catching: @escaping @Sendable () async throws(E) -> V
|
let error: any Error
|
||||||
) async where ErrorView == Styleguide.ErrorView<E> {
|
|
||||||
await self.init(result: .init(catching: catching)) {
|
|
||||||
$0
|
|
||||||
} onError: { error in
|
|
||||||
Styleguide.ErrorView(error: error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension ResultView: Sendable where Error: Sendable, ValueView: Sendable, ErrorView: Sendable {}
|
public init(error: any Error) {
|
||||||
|
|
||||||
public struct ErrorView<E: Error>: HTML, Sendable where Error: Sendable {
|
|
||||||
|
|
||||||
let error: E
|
|
||||||
|
|
||||||
public init(error: E) {
|
|
||||||
self.error = error
|
self.error = error
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: some HTML<HTMLTag.div> {
|
public var body: some HTML<HTMLTag.div> {
|
||||||
div {
|
div {
|
||||||
h1(.class("text-2xl font-bold text-error")) { "Oops: Error" }
|
h1(.class("text-xl font-bold text-error")) { "Oops: Error" }
|
||||||
p {
|
p {
|
||||||
"\(error)"
|
"\(error)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -193,9 +193,14 @@ extension SiteRoute.View.ProjectRoute {
|
|||||||
case .frictionRate(let route):
|
case .frictionRate(let route):
|
||||||
return await route.renderView(on: request, projectID: projectID)
|
return await route.renderView(on: request, projectID: projectID)
|
||||||
case .pdf:
|
case .pdf:
|
||||||
return await ResultView {
|
// return await ResultView2 {
|
||||||
try await projectClient.toHTML(projectID)
|
// try await projectClient.toHTML(projectID)
|
||||||
}
|
// } onError: {
|
||||||
|
// ErrorView2(error: $0)
|
||||||
|
// }
|
||||||
|
// return await ResultView {
|
||||||
|
return try! await projectClient.toHTML(projectID)
|
||||||
|
// }
|
||||||
// fatalError()
|
// fatalError()
|
||||||
case .rooms(let route):
|
case .rooms(let route):
|
||||||
return await route.renderView(on: request, projectID: projectID)
|
return await route.renderView(on: request, projectID: projectID)
|
||||||
|
|||||||
Reference in New Issue
Block a user