diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index 9520406f..2c4cc80c 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -29,6 +29,7 @@ import Foundation public var errorMessage: String? public var errorTextColor: Color? public var enabled: Bool = true + public var readOnly: Bool = false public var showError: Bool? public var hideBorders = false public var locked: Bool? @@ -73,6 +74,7 @@ import Foundation case accessibilityIdentifier case title case enabled + case readOnly case feedback case errorMessage case errorTextColor @@ -134,6 +136,7 @@ import Foundation errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) errorTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .errorTextColor) enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true + readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false locked = try typeContainer.decodeIfPresent(Bool.self, forKey: .locked) selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) text = try typeContainer.decodeIfPresent(String.self, forKey: .text) @@ -145,8 +148,8 @@ import Foundation if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { self.groupName = groupName } - - //Setup the stateLabelModels + + //Setup the stateLabelModels if let titleLabel = titleLabel { self.titleStateLabel = StateLabelModel(model: titleLabel) } else { @@ -178,6 +181,7 @@ import Foundation try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(groupName, forKey: .groupName) + try container.encode(readOnly, forKey: .readOnly) try container.encode(enabled, forKey: .enabled) try container.encode(hideBorders, forKey: .hideBorders) } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift index 69f026ef..063c322a 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift @@ -23,7 +23,8 @@ public var backgroundColor: Color? public var accessibilityIdentifier: String? public var selected: Bool = false - public var enabled: Bool = true + public var enabled: Bool = true + public var readOnly: Bool = false public var animated: Bool = true public var inverted: Bool = false public var round: Bool = false @@ -54,6 +55,7 @@ case accessibilityIdentifier case checked case enabled + case readOnly case inverted case animated case round @@ -158,10 +160,8 @@ self.inverted = inverted } - if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { - self.enabled = enabled - } - + enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true + readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false action = try typeContainer.decodeModelIfPresent(codingKey: .action) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) @@ -191,7 +191,8 @@ try container.encodeIfPresent(disabledCheckColor, forKey: .disabledCheckColor) try container.encodeIfPresent(animated, forKey: .animated) try container.encodeIfPresent(round, forKey: .round) - try container.encodeIfPresent(enabled, forKey: .enabled) + try container.encode(enabled, forKey: .enabled) + try container.encode(readOnly, forKey: .readOnly) try container.encodeModelIfPresent(action, forKey: .action) try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeModelIfPresent(offAction, forKey: .offAction) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift index aea065ef..c03a7302 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift @@ -21,8 +21,8 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol { public var inActiveColor: Color = Color(uiColor: .clear) public var action: ActionModelProtocol = ActionNoopModel() public var enabled: Bool = true - - //-------------------------------------------------- + public var readOnly: Bool = false + // MARK: - Keys //-------------------------------------------------- @@ -35,6 +35,7 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol { case inActiveColor case action case enabled + case readOnly } //-------------------------------------------------- @@ -61,9 +62,8 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol { if let action: ActionModelProtocol = try typeContainer.decodeModelIfPresent(codingKey: .action) { self.action = action } - if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { - self.enabled = enabled - } + enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true + readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false } public func encode(to encoder: Encoder) throws { @@ -76,5 +76,6 @@ open class HeartModel: MoleculeModelProtocol, EnableableModelProtocol { try container.encode(inActiveColor, forKey: .inActiveColor) try container.encodeModel(action, forKey: .action) try container.encode(enabled, forKey: .enabled) + try container.encode(readOnly, forKey: .readOnly) } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift index f1b22dc3..fc299b50 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift @@ -19,6 +19,7 @@ public var selectedAccentColor: Color? public var selected: Bool = false public var enabled: Bool = true + public var readOnly: Bool = false public var strikethrough: Bool = false public var fieldValue: String? public var action: ActionModelProtocol? @@ -39,6 +40,7 @@ case strikethrough case fieldValue case action + case readOnly } //-------------------------------------------------- @@ -57,9 +59,8 @@ selected = isSelected } - if let isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { - enabled = isEnabled - } + enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true + readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false if let isStrikeTrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) { strikethrough = isStrikeTrough @@ -79,6 +80,7 @@ try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) try container.encode(selected, forKey: .selected) try container.encode(enabled, forKey: .enabled) + try container.encode(readOnly, forKey: .readOnly) try container.encode(strikethrough, forKey: .strikethrough) try container.encodeIfPresent(fieldValue, forKey: .fieldValue) try container.encodeModelIfPresent(action, forKey: .action) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index 1614f3ec..7e919553 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -21,7 +21,7 @@ public var groupName: String = FormValidator.defaultGroupName public var baseValue: AnyHashable? public var enabled: Bool = true - + public var readOnly: Bool = false //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- @@ -42,6 +42,7 @@ private enum CodingKeys: String, CodingKey { case moleculeName case enabled + case readOnly case selectedAccentColor case backgroundColor case accessibilityIdentifier @@ -66,9 +67,8 @@ if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { self.groupName = groupName } - if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { - self.enabled = enabled - } + enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true + readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false baseValue = formFieldValue() } @@ -81,5 +81,7 @@ try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encode(groupName, forKey: .groupName) + try container.encode(enabled, forKey: .enabled) + try container.encode(readOnly, forKey: .readOnly) } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift index 445fd2a3..79fcb9cb 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift @@ -19,6 +19,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { public var accessibilityIdentifier: String? public var state: Bool = false public var enabled: Bool = true + public var readOnly: Bool = false /// The specific value to send to server. TODO: update this to be more generic. public var fieldValue: String? @@ -42,6 +43,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { case fieldKey case groupName case action + case readOnly } //-------------------------------------------------- @@ -72,11 +74,9 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { self.state = state } - - if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { - self.enabled = enabled - } - + + enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true + readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) @@ -96,6 +96,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { try container.encode(moleculeName, forKey: .moleculeName) try container.encode(state, forKey: .state) try container.encode(enabled, forKey: .enabled) + try container.encode(readOnly, forKey: .readOnly) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(fieldValue, forKey: .fieldValue) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift index e80f8813..f927f7e9 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatch.swift @@ -39,6 +39,12 @@ open class RadioSwatch: Control, MFButtonProtocol { } } + public override var isReadOnly: Bool { + didSet { + updateAccessibility() + } + } + //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- @@ -65,6 +71,7 @@ open class RadioSwatch: Control, MFButtonProtocol { bottomText.text = model.text isSelected = model.selected isEnabled = model.enabled + isReadOnly = model.readOnly } public override func reset() { @@ -72,6 +79,7 @@ open class RadioSwatch: Control, MFButtonProtocol { bottomText.text = nil isSelected = false isEnabled = true + isReadOnly = false } //------------------------------------------------------ @@ -106,7 +114,7 @@ open class RadioSwatch: Control, MFButtonProtocol { //Handle Mask maskLayer?.removeFromSuperlayer() - if !isEnabled { + if !isEnabled || isReadOnly { let mask = getMaskLayer() layer.mask = mask maskLayer = mask @@ -120,7 +128,7 @@ open class RadioSwatch: Control, MFButtonProtocol { } @objc open func selectSwatch() { - guard isEnabled, !isSelected else { return } + guard isEnabled, !isReadOnly, !isSelected else { return } isSelected = true radioSwatchModel?.selected = isSelected if let radioSwatchModel = radioSwatchModel, let actionModel = radioSwatchModel.action { @@ -193,7 +201,7 @@ open class RadioSwatch: Control, MFButtonProtocol { if isSelected { accessibilityTraits.insert(.selected) } - if !isEnabled { + if !isEnabled || isReadOnly { accessibilityTraits.insert(.notEnabled) } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift index 100e2311..059dd2c8 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchModel.swift @@ -19,6 +19,7 @@ public var text: String? public var selected: Bool = false public var enabled: Bool = true + public var readOnly: Bool = false public var strikethrough: Bool = false public var fieldValue: String? public var action: ActionModelProtocol? @@ -38,6 +39,7 @@ case strikethrough case fieldValue case action + case readOnly } //-------------------------------------------------- @@ -58,17 +60,15 @@ if let selected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) { self.selected = selected } - - if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { - self.enabled = enabled - } - + if let strikethrough = try typeContainer.decodeIfPresent(Bool.self, forKey: .strikethrough) { self.strikethrough = strikethrough } fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) action = try typeContainer.decodeModelIfPresent(codingKey: .action) + enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true + readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false } public func encode(to encoder: Encoder) throws { @@ -83,5 +83,6 @@ try container.encode(strikethrough, forKey: .strikethrough) try container.encodeIfPresent(fieldValue, forKey: .fieldValue) try container.encodeModelIfPresent(action, forKey: .action) + try container.encode(readOnly, forKey: .readOnly) } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift index 3fb6ec19..7e475081 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioSwatchesModel.swift @@ -20,7 +20,8 @@ public var groupName: String = FormValidator.defaultGroupName public var baseValue: AnyHashable? public var enabled: Bool = true - + public var readOnly: Bool = false + //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- @@ -46,6 +47,7 @@ case fieldKey case groupName case enabled + case readOnly } //-------------------------------------------------- @@ -61,9 +63,8 @@ if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { self.groupName = groupName } - if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { - self.enabled = enabled - } + enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true + readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false baseValue = formFieldValue() } @@ -75,5 +76,7 @@ try container.encode(swatches, forKey: .swatches) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encode(groupName, forKey: .groupName) + try container.encode(enabled, forKey: .enabled) + try container.encode(readOnly, forKey: .readOnly) } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift index 22961e3f..4c860342 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift @@ -18,6 +18,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { public var selected: Bool = false public var animated: Bool = true public var enabled: Bool = true + public var readOnly: Bool = false public var action: ActionModelProtocol? public var alternateAction: ActionModelProtocol? public var accessibilityText: String? @@ -39,6 +40,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { case state case animated case enabled + case readOnly case action case backgroundColor case accessibilityIdentifier @@ -81,10 +83,6 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { self.selected = state } - if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { - self.enabled = enabled - } - if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) { self.animated = animated } @@ -117,6 +115,8 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { self.groupName = groupName } + enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true + readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false } public func encode(to encoder: Encoder) throws { @@ -136,5 +136,6 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(groupName, forKey: .groupName) + try container.encode(readOnly, forKey: .readOnly) } } diff --git a/MVMCoreUI/Atomic/Molecules/Items/CarouselItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/CarouselItemModel.swift index f2122901..9858190d 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/CarouselItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/CarouselItemModel.swift @@ -20,6 +20,7 @@ public var analyticsData: JSONValueDictionary? public var fieldValue: String? public var enabled: Bool = true + public var readOnly: Bool = false public var fieldKey: String? public var groupName: String = FormValidator.defaultGroupName public var baseValue: AnyHashable? @@ -40,6 +41,8 @@ case fieldValue case fieldKey case groupName + case enabled + case readOnly } //-------------------------------------------------- @@ -57,6 +60,12 @@ self.groupName = groupName } baseValue = fieldValue + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { + self.enabled = enabled + } + if let readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) { + self.readOnly = readOnly + } try super.init(from: decoder) } @@ -67,5 +76,7 @@ try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor) try container.encodeIfPresent(analyticsData, forKey: .analyticsData) try container.encodeIfPresent(fieldValue, forKey: .fieldValue) + try container.encode(enabled, forKey: .enabled) + try container.encode(readOnly, forKey: .readOnly) } } diff --git a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift index 35d29020..ed22696c 100644 --- a/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift +++ b/MVMCoreUI/Atomic/Organisms/Carousel/CarouselModel.swift @@ -38,7 +38,8 @@ import UIKit public var fieldKey: String? public var groupName: String = FormValidator.defaultGroupName public var enabled: Bool = true - + public var readOnly: Bool = false + public var selectable = false public var selectedIndex: Int? @@ -87,6 +88,8 @@ import UIKit case fieldKey case selectable case selectedIndex + case enabled + case readOnly } //-------------------------------------------------- @@ -120,10 +123,16 @@ import UIKit if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { self.groupName = groupName } + if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { + self.enabled = enabled + } + if let readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) { + self.readOnly = readOnly + } baseValue = formFieldValue() - } - - public func encode(to encoder: Encoder) throws { + } + + public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) @@ -145,6 +154,8 @@ import UIKit try container.encode(index, forKey: .index) try container.encode(selectable, forKey: .selectable) try container.encode(selectedIndex, forKey: .selectedIndex) + try container.encode(enabled, forKey: .enabled) + try container.encode(enabled, forKey: .enabled) } } diff --git a/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift index afdde887..0a501440 100644 --- a/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift @@ -16,11 +16,18 @@ public protocol FormFieldProtocol: FormItemProtocol { /// A place to store the initial value of the field for checking if the value has changed. var baseValue: AnyHashable? { get set } + ///Bool to determine a state that is different from disabled. Readonly values will be sent + ///to the server where disabled fields are not + var readOnly: Bool { get set } + /// Returns the value of the field. Used for validations and possibly for sending to server. func formFieldValue() -> AnyHashable? + } extension FormFieldProtocol { var baseValue: AnyHashable? { nil } + + var readOnly: Bool { false } }