feat: Reverts static pressure.
This commit is contained in:
@@ -5,7 +5,6 @@ import SharedModels
|
|||||||
import Styleguide
|
import Styleguide
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
#warning("Revert rated static pressures section.")
|
|
||||||
@Reducer
|
@Reducer
|
||||||
public struct EquipmentSettingsForm {
|
public struct EquipmentSettingsForm {
|
||||||
|
|
||||||
@@ -24,23 +23,24 @@ public struct EquipmentSettingsForm {
|
|||||||
@ObservableState
|
@ObservableState
|
||||||
public struct State: Equatable {
|
public struct State: Equatable {
|
||||||
@Presents public var destination: Destination.State?
|
@Presents public var destination: Destination.State?
|
||||||
public var includesFilterDrop: Bool
|
|
||||||
public var equipmentType: EquipmentMeasurement.EquipmentType
|
public var equipmentType: EquipmentMeasurement.EquipmentType
|
||||||
public var focusedField: Field? = nil
|
public var focusedField: Field? = nil
|
||||||
@Shared public var sharedSettings: SharedPressureEstimationState
|
@Shared public var sharedSettings: SharedPressureEstimationState
|
||||||
public var ratedStaticPressures: RatedStaticPressuresSection.State
|
public var maxStaticPressure: Double?
|
||||||
|
public var minStaticPressure: Double?
|
||||||
|
public var ratedStaticPressure: Double?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
destination: Destination.State? = nil,
|
destination: Destination.State? = nil,
|
||||||
includesFilterDrop: Bool = false,
|
|
||||||
equipmentType: EquipmentMeasurement.EquipmentType = .airHandler,
|
equipmentType: EquipmentMeasurement.EquipmentType = .airHandler,
|
||||||
sharedSettings: Shared<SharedPressureEstimationState>
|
sharedSettings: Shared<SharedPressureEstimationState>
|
||||||
) {
|
) {
|
||||||
self.destination = destination
|
self.destination = destination
|
||||||
self.includesFilterDrop = includesFilterDrop
|
|
||||||
self.equipmentType = equipmentType
|
self.equipmentType = equipmentType
|
||||||
self._sharedSettings = sharedSettings
|
self._sharedSettings = sharedSettings
|
||||||
self.ratedStaticPressures = .init(staticPressures: sharedSettings.equipmentMetadata.ratedStaticPressures)
|
self.maxStaticPressure = sharedSettings.ratedStaticPressures.maximum.wrappedValue
|
||||||
|
self.minStaticPressure = sharedSettings.ratedStaticPressures.minimum.wrappedValue
|
||||||
|
self.ratedStaticPressure = sharedSettings.ratedStaticPressures.rated.wrappedValue
|
||||||
}
|
}
|
||||||
|
|
||||||
private var equipmentTypeValidation: Bool {
|
private var equipmentTypeValidation: Bool {
|
||||||
@@ -48,33 +48,26 @@ public struct EquipmentSettingsForm {
|
|||||||
return sharedSettings.heatingCapacity != nil
|
return sharedSettings.heatingCapacity != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
private var filterDropValidation: Bool {
|
|
||||||
guard includesFilterDrop else { return true }
|
private var staticPressuresValidation: Bool {
|
||||||
return sharedSettings.manufacturersIncludedFilterPressureDrop != nil
|
maxStaticPressure != nil
|
||||||
|
&& minStaticPressure != nil
|
||||||
|
&& ratedStaticPressure != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
public var isValid: Bool {
|
public var isValid: Bool {
|
||||||
ratedStaticPressures.isValid
|
equipmentTypeValidation
|
||||||
&& equipmentTypeValidation
|
&& staticPressuresValidation
|
||||||
&& filterDropValidation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: These need to be in display order.
|
// Note: These need to be in display order.
|
||||||
public enum Field: Hashable, CaseIterable, FocusableField, Identifiable {
|
public enum Field: Hashable, CaseIterable, FocusableField, Identifiable {
|
||||||
case heatingCapacity
|
case heatingCapacity
|
||||||
case ratedStaticPressure(RatedStaticPressuresSection.State.FocusedField)
|
case maxStaticPressure
|
||||||
|
case minStaticPressure
|
||||||
|
case ratedStaticPressure
|
||||||
case manufacturersIncludedFilterPressureDrop
|
case manufacturersIncludedFilterPressureDrop
|
||||||
|
|
||||||
public static var allCases: [EquipmentSettingsForm.State.Field] {
|
|
||||||
[
|
|
||||||
.heatingCapacity,
|
|
||||||
.ratedStaticPressure(.maximum),
|
|
||||||
.ratedStaticPressure(.minimum),
|
|
||||||
.ratedStaticPressure(.rated),
|
|
||||||
.manufacturersIncludedFilterPressureDrop
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
public var id: Self { self }
|
public var id: Self { self }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +75,6 @@ public struct EquipmentSettingsForm {
|
|||||||
public enum Action: BindableAction, ViewAction {
|
public enum Action: BindableAction, ViewAction {
|
||||||
case binding(BindingAction<State>)
|
case binding(BindingAction<State>)
|
||||||
case destination(PresentationAction<Destination.Action>)
|
case destination(PresentationAction<Destination.Action>)
|
||||||
case ratedStaticPressures(RatedStaticPressuresSection.Action)
|
|
||||||
case view(View)
|
case view(View)
|
||||||
|
|
||||||
@CasePathable
|
@CasePathable
|
||||||
@@ -95,21 +87,19 @@ public struct EquipmentSettingsForm {
|
|||||||
|
|
||||||
public var body: some Reducer<State, Action> {
|
public var body: some Reducer<State, Action> {
|
||||||
BindingReducer()
|
BindingReducer()
|
||||||
Scope(state: \.ratedStaticPressures, action: \.ratedStaticPressures) {
|
|
||||||
RatedStaticPressuresSection()
|
|
||||||
}
|
|
||||||
Reduce<State, Action> { state, action in
|
Reduce<State, Action> { state, action in
|
||||||
switch action {
|
switch action {
|
||||||
|
|
||||||
case .binding(\.includesFilterDrop):
|
case .binding(\.maxStaticPressure):
|
||||||
guard state.includesFilterDrop else {
|
handleStaticPressure(\.maximum, \.maxStaticPressure, &state)
|
||||||
state.sharedSettings.manufacturersIncludedFilterPressureDrop = nil
|
return .none
|
||||||
return .none
|
|
||||||
}
|
case .binding(\.minStaticPressure):
|
||||||
guard state.sharedSettings.manufacturersIncludedFilterPressureDrop != nil else {
|
handleStaticPressure(\.minimum, \.minStaticPressure, &state)
|
||||||
return .none
|
return .none
|
||||||
}
|
|
||||||
state.sharedSettings.manufacturersIncludedFilterPressureDrop = 0.1
|
case .binding(\.ratedStaticPressure):
|
||||||
|
handleStaticPressure(\.rated, \.ratedStaticPressure, &state)
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .binding:
|
case .binding:
|
||||||
@@ -122,14 +112,6 @@ public struct EquipmentSettingsForm {
|
|||||||
case .destination:
|
case .destination:
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
|
|
||||||
case .ratedStaticPressures(.delegate(.infoButtonTapped)):
|
|
||||||
state.destination = .infoView(.init(view: .ratedStaticPressures))
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case .ratedStaticPressures:
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case let .view(action):
|
case let .view(action):
|
||||||
switch action {
|
switch action {
|
||||||
|
|
||||||
@@ -150,6 +132,17 @@ public struct EquipmentSettingsForm {
|
|||||||
}
|
}
|
||||||
.ifLet(\.$destination, action: \.destination)
|
.ifLet(\.$destination, action: \.destination)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func handleStaticPressure(
|
||||||
|
_ staticKeyPath: WritableKeyPath<RatedStaticPressures, Double>,
|
||||||
|
_ stateKeyPath: KeyPath<State, Double?>,
|
||||||
|
_ state: inout State
|
||||||
|
) {
|
||||||
|
let value = state[keyPath: stateKeyPath]
|
||||||
|
state.sharedSettings.equipmentMetadata.ratedStaticPressures[keyPath: staticKeyPath] = value ?? 0
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewAction(for: EquipmentSettingsForm.self)
|
@ViewAction(for: EquipmentSettingsForm.self)
|
||||||
@@ -219,30 +212,68 @@ public struct EquipmentSettingsFormView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RatedStaticPressuresSectionView(
|
Section {
|
||||||
store: store.scope(state: \.ratedStaticPressures, action: \.ratedStaticPressures)
|
Grid(alignment: .leading, horizontalSpacing: 40) {
|
||||||
)
|
GridRow {
|
||||||
|
TextLabel("Maximum")
|
||||||
|
TextField(
|
||||||
|
"Maximum",
|
||||||
|
value: $store.maxStaticPressure,
|
||||||
|
fractionLength: 2,
|
||||||
|
prompt: Text("Maximum Pressure")
|
||||||
|
)
|
||||||
|
.decimalPad()
|
||||||
|
.focused($focusedField, equals: .maxStaticPressure)
|
||||||
|
}
|
||||||
|
GridRow {
|
||||||
|
TextLabel("Minimum")
|
||||||
|
TextField(
|
||||||
|
"Minimum",
|
||||||
|
value: $store.minStaticPressure,
|
||||||
|
fractionLength: 2,
|
||||||
|
prompt: Text("Minimum Pressure")
|
||||||
|
)
|
||||||
|
.decimalPad()
|
||||||
|
.focused($focusedField, equals: .minStaticPressure)
|
||||||
|
}
|
||||||
|
GridRow {
|
||||||
|
TextLabel("Rated")
|
||||||
|
TextField(
|
||||||
|
"Rated",
|
||||||
|
value: $store.ratedStaticPressure,
|
||||||
|
fractionLength: 2,
|
||||||
|
prompt: Text("Rated Pressure")
|
||||||
|
)
|
||||||
|
.decimalPad()
|
||||||
|
.focused($focusedField, equals: .ratedStaticPressure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.dynamicBottomPadding()
|
||||||
|
|
||||||
|
} header: {
|
||||||
|
header("Rated Static Pressures", infoView: .ratedStaticPressures)
|
||||||
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
HStack {
|
// HStack {
|
||||||
TextLabel("Includes Filter Drop")
|
// TextLabel("Includes Filter Drop")
|
||||||
Spacer()
|
// Spacer()
|
||||||
Toggle("Includes Filter Drop", isOn: $store.includesFilterDrop)
|
// Toggle("Includes Filter Drop", isOn: $store.includesFilterDrop)
|
||||||
}
|
// }
|
||||||
if store.includesFilterDrop {
|
// if store.includesFilterDrop {
|
||||||
HStack {
|
HStack {
|
||||||
TextLabel("Filter Drop")
|
TextLabel("Filter Drop")
|
||||||
Spacer()
|
Spacer()
|
||||||
textField(
|
textField(
|
||||||
"Filter Drop",
|
"Optional",
|
||||||
value: $store.sharedSettings.manufacturersIncludedFilterPressureDrop
|
value: $store.sharedSettings.manufacturersIncludedFilterPressureDrop
|
||||||
)
|
)
|
||||||
.focused($focusedField, equals: .manufacturersIncludedFilterPressureDrop)
|
.focused($focusedField, equals: .manufacturersIncludedFilterPressureDrop)
|
||||||
.decimalPad()
|
.decimalPad()
|
||||||
.padding(.leading, 40)
|
.padding(.leading, 40)
|
||||||
}
|
}
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
} header: {
|
} header: {
|
||||||
header(infoView: .manufacturersIncludedFilterPressureDrop) {
|
header(infoView: .manufacturersIncludedFilterPressureDrop) {
|
||||||
|
|||||||
@@ -1,147 +0,0 @@
|
|||||||
import ComposableArchitecture
|
|
||||||
import SharedModels
|
|
||||||
import Styleguide
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
/// Allows for rated static pressure fields to be optional values, setting their corresponding shared state values to zero when they're nilled out.
|
|
||||||
///
|
|
||||||
@Reducer
|
|
||||||
public struct RatedStaticPressuresSection {
|
|
||||||
|
|
||||||
public init() { }
|
|
||||||
|
|
||||||
@ObservableState
|
|
||||||
public struct State: Equatable {
|
|
||||||
|
|
||||||
@Shared public var staticPressures: RatedStaticPressures
|
|
||||||
public var focusedField: FocusedField?
|
|
||||||
public var maxPressure: Double?
|
|
||||||
public var minPressure: Double?
|
|
||||||
public var ratedPressure: Double?
|
|
||||||
|
|
||||||
public init(
|
|
||||||
staticPressures: Shared<RatedStaticPressures>
|
|
||||||
) {
|
|
||||||
self._staticPressures = staticPressures
|
|
||||||
self.maxPressure = staticPressures.maximum.wrappedValue
|
|
||||||
self.minPressure = staticPressures.minimum.wrappedValue
|
|
||||||
self.ratedPressure = staticPressures.rated.wrappedValue
|
|
||||||
}
|
|
||||||
|
|
||||||
public var isValid: Bool {
|
|
||||||
maxPressure != nil
|
|
||||||
&& minPressure != nil
|
|
||||||
&& ratedPressure != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum FocusedField: String, Hashable, CaseIterable, FocusableField {
|
|
||||||
case maximum
|
|
||||||
case minimum
|
|
||||||
case rated
|
|
||||||
|
|
||||||
public var label: String { rawValue.capitalized }
|
|
||||||
public var prompt: String { "\(label) Pressure"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Action: BindableAction {
|
|
||||||
case binding(BindingAction<State>)
|
|
||||||
case delegate(DelegateAction)
|
|
||||||
|
|
||||||
public enum DelegateAction {
|
|
||||||
case infoButtonTapped
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public var body: some Reducer<State, Action> {
|
|
||||||
BindingReducer()
|
|
||||||
Reduce<State, Action> { state, action in
|
|
||||||
switch action {
|
|
||||||
case .binding(\.maxPressure):
|
|
||||||
state.staticPressures.maximum = state.maxPressure ?? 0
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case .binding(\.minPressure):
|
|
||||||
state.staticPressures.minimum = state.minPressure ?? 0
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case .binding(\.ratedPressure):
|
|
||||||
state.staticPressures.rated = state.ratedPressure ?? 0
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case .binding:
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case .delegate:
|
|
||||||
return .none
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct RatedStaticPressuresSectionView: View {
|
|
||||||
|
|
||||||
@FocusState private var focusedField: RatedStaticPressuresSection.State.FocusedField?
|
|
||||||
@Bindable var store: StoreOf<RatedStaticPressuresSection>
|
|
||||||
|
|
||||||
public init(store: StoreOf<RatedStaticPressuresSection>) {
|
|
||||||
self.store = store
|
|
||||||
}
|
|
||||||
|
|
||||||
public var body: some View {
|
|
||||||
Section {
|
|
||||||
Grid(alignment: .leading, horizontalSpacing: 40) {
|
|
||||||
GridRow {
|
|
||||||
label(for: .maximum)
|
|
||||||
TextField(
|
|
||||||
"Maximum",
|
|
||||||
value: $store.maxPressure,
|
|
||||||
fractionLength: 2,
|
|
||||||
prompt: prompt(for: .maximum)
|
|
||||||
)
|
|
||||||
.decimalPad()
|
|
||||||
.focused($focusedField, equals: .maximum)
|
|
||||||
}
|
|
||||||
GridRow {
|
|
||||||
label(for: .minimum)
|
|
||||||
TextField(
|
|
||||||
"Minimum",
|
|
||||||
value: $store.minPressure,
|
|
||||||
fractionLength: 2,
|
|
||||||
prompt: prompt(for: .minimum)
|
|
||||||
)
|
|
||||||
.decimalPad()
|
|
||||||
.focused($focusedField, equals: .minimum)
|
|
||||||
}
|
|
||||||
GridRow {
|
|
||||||
label(for: .rated)
|
|
||||||
TextField(
|
|
||||||
"Rated",
|
|
||||||
value: $store.ratedPressure,
|
|
||||||
fractionLength: 2,
|
|
||||||
prompt: prompt(for: .rated)
|
|
||||||
)
|
|
||||||
.decimalPad()
|
|
||||||
.focused($focusedField, equals: .rated)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.dynamicBottomPadding()
|
|
||||||
|
|
||||||
} header: {
|
|
||||||
HStack {
|
|
||||||
SectionHeaderLabel("Rated Static Pressures")
|
|
||||||
Spacer()
|
|
||||||
InfoButton { store.send(.delegate(.infoButtonTapped)) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.bind($focusedField, to: $store.focusedField)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func label(for field: RatedStaticPressuresSection.State.FocusedField) -> some View {
|
|
||||||
TextLabel(field.label)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func prompt(for field: RatedStaticPressuresSection.State.FocusedField) -> Text {
|
|
||||||
Text(field.prompt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -173,6 +173,39 @@ final class FlaggedMeasurementListReducerTests: XCTestCase {
|
|||||||
await store.finish()
|
await store.finish()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @MainActor
|
||||||
|
// func testBindingsSetSharedState() async {
|
||||||
|
// let store = TestStore(
|
||||||
|
// initialState: FlaggedMeasurementsList.State(
|
||||||
|
// sharedSettings: Shared(SharedPressureEstimationState(
|
||||||
|
// budgets: nil,
|
||||||
|
// equipmentMeasurement: .mock(type: .airHandler),
|
||||||
|
// equipmentMetadata: .init(
|
||||||
|
// coolingCapacity: .three,
|
||||||
|
// fanType: .constantSpeed,
|
||||||
|
// ratedStaticPressures: .init()
|
||||||
|
// )
|
||||||
|
// ))
|
||||||
|
// )
|
||||||
|
// ) {
|
||||||
|
// FlaggedMeasurementsList()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// await store.send(.binding(.set(\.maxStaticPressure, nil))) {
|
||||||
|
// $0.maxStaticPressure = nil
|
||||||
|
// $0.sharedSettings.ratedStaticPressures.maximum = 0
|
||||||
|
// }
|
||||||
|
// await store.send(.binding(.set(\.minStaticPressure, nil))) {
|
||||||
|
// $0.minStaticPressure = nil
|
||||||
|
// $0.sharedSettings.ratedStaticPressures.minimum = 0
|
||||||
|
// }
|
||||||
|
// await store.send(.binding(.set(\.ratedStaticPressure, nil))) {
|
||||||
|
// $0.ratedStaticPressure = nil
|
||||||
|
// $0.sharedSettings.ratedStaticPressures.rated = 0
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Tag {
|
extension Tag {
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
import ComposableArchitecture
|
|
||||||
import PressureEstimationsFeature
|
|
||||||
import SharedModels
|
|
||||||
import Testing
|
|
||||||
import XCTest
|
|
||||||
|
|
||||||
struct RatedStaticPressureStateTests {
|
|
||||||
|
|
||||||
@Test(
|
|
||||||
"Rated static pressure validation",
|
|
||||||
.tags(.ratedStaticPressuresSection)
|
|
||||||
)
|
|
||||||
func validation() {
|
|
||||||
var state = RatedStaticPressuresSection.State(
|
|
||||||
staticPressures: Shared(RatedStaticPressures())
|
|
||||||
)
|
|
||||||
#expect(state.isValid)
|
|
||||||
|
|
||||||
state.maxPressure = nil
|
|
||||||
#expect(!state.isValid)
|
|
||||||
|
|
||||||
state.maxPressure = 1
|
|
||||||
state.minPressure = nil
|
|
||||||
#expect(!state.isValid)
|
|
||||||
|
|
||||||
state.minPressure = 1
|
|
||||||
state.ratedPressure = nil
|
|
||||||
#expect(!state.isValid)
|
|
||||||
|
|
||||||
state.ratedPressure = 1
|
|
||||||
#expect(state.isValid)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(
|
|
||||||
"Focused field label",
|
|
||||||
.tags(.ratedStaticPressuresSection),
|
|
||||||
arguments: RatedStaticPressuresSection.State.FocusedField.allCases
|
|
||||||
)
|
|
||||||
func label(field: RatedStaticPressuresSection.State.FocusedField) {
|
|
||||||
#expect(field.label == "\(field.rawValue.capitalized)")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(
|
|
||||||
"Focused field prompt",
|
|
||||||
.tags(.ratedStaticPressuresSection),
|
|
||||||
arguments: RatedStaticPressuresSection.State.FocusedField.allCases
|
|
||||||
)
|
|
||||||
func prompt(field: RatedStaticPressuresSection.State.FocusedField) {
|
|
||||||
#expect(field.prompt == "\(field.rawValue.capitalized) Pressure")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
final class RatedStaticPressureReducerTests: XCTestCase {
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
func testBindingsSetSharedState() async {
|
|
||||||
let store = TestStore(
|
|
||||||
initialState: RatedStaticPressuresSection.State(
|
|
||||||
staticPressures: Shared(RatedStaticPressures())
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
RatedStaticPressuresSection()
|
|
||||||
}
|
|
||||||
|
|
||||||
await store.send(.binding(.set(\.maxPressure, nil))) {
|
|
||||||
$0.maxPressure = nil
|
|
||||||
$0.staticPressures.maximum = 0
|
|
||||||
}
|
|
||||||
await store.send(.binding(.set(\.minPressure, nil))) {
|
|
||||||
$0.minPressure = nil
|
|
||||||
$0.staticPressures.minimum = 0
|
|
||||||
}
|
|
||||||
await store.send(.binding(.set(\.ratedPressure, nil))) {
|
|
||||||
$0.ratedPressure = nil
|
|
||||||
$0.staticPressures.rated = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Tag {
|
|
||||||
|
|
||||||
@Tag static var ratedStaticPressuresSection: Self
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user