From 13f9776a4f7793742ef0027294ce852789560408 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 08:45:04 -0500 Subject: [PATCH 01/46] new Checkboxes/RadioButtons Signed-off-by: Matt Bruce --- MVMCoreUI.xcodeproj/project.pbxproj | 16 ++++ .../Atomic/Atoms/Selectors/Checkboxes.swift | 55 ++++++++++++ .../Atoms/Selectors/CheckboxesModel.swift | 85 +++++++++++++++++++ .../Atomic/Atoms/Selectors/RadioButtons.swift | 54 ++++++++++++ .../Atoms/Selectors/RadioButtonsModel.swift | 72 ++++++++++++++++ 5 files changed, 282 insertions(+) create mode 100644 MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index f7f5870b..e8c458bd 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -594,6 +594,10 @@ EA6642932BCDA97D00D81DC4 /* TileContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */; }; EA6E8B952B504A43000139B4 /* ButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B942B504A43000139B4 /* ButtonGroup.swift */; }; EA6E8B972B504A4D000139B4 /* ButtonGroupModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */; }; + EA7AE5472C73C01A00107C74 /* CheckboxesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5462C73C01A00107C74 /* CheckboxesModel.swift */; }; + EA7AE5492C7403DC00107C74 /* Checkboxes.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5482C7403DC00107C74 /* Checkboxes.swift */; }; + EA7AE54B2C74CACA00107C74 /* RadioButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE54A2C74CACA00107C74 /* RadioButtons.swift */; }; + EA7AE54D2C74CAD700107C74 /* RadioButtonsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE54C2C74CAD700107C74 /* RadioButtonsModel.swift */; }; EA7D81602B2B6E6800D29F9E /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D815F2B2B6E6800D29F9E /* Icon.swift */; }; EA7D81622B2B6E7F00D29F9E /* IconModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81612B2B6E7F00D29F9E /* IconModel.swift */; }; EA7D81642B2BABCB00D29F9E /* TooltipModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */; }; @@ -1223,6 +1227,10 @@ EA6642922BCDA97D00D81DC4 /* TileContainerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TileContainerModel.swift; sourceTree = ""; }; EA6E8B942B504A43000139B4 /* ButtonGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroup.swift; sourceTree = ""; }; EA6E8B962B504A4D000139B4 /* ButtonGroupModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupModel.swift; sourceTree = ""; }; + EA7AE5462C73C01A00107C74 /* CheckboxesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxesModel.swift; sourceTree = ""; }; + EA7AE5482C7403DC00107C74 /* Checkboxes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkboxes.swift; sourceTree = ""; }; + EA7AE54A2C74CACA00107C74 /* RadioButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtons.swift; sourceTree = ""; }; + EA7AE54C2C74CAD700107C74 /* RadioButtonsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonsModel.swift; sourceTree = ""; }; EA7D815F2B2B6E6800D29F9E /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = ""; }; EA7D81612B2B6E7F00D29F9E /* IconModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconModel.swift; sourceTree = ""; }; EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TooltipModel.swift; sourceTree = ""; }; @@ -2031,8 +2039,12 @@ BBAA4F00243D8E3B005AAD5F /* RadioBoxModel.swift */, D264FAA6243FE13B00D98315 /* RadioBox.swift */, 0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */, + EA7AE54C2C74CAD700107C74 /* RadioButtonsModel.swift */, + EA7AE54A2C74CACA00107C74 /* RadioButtons.swift */, 011D95AE2407266E000E3791 /* RadioButtonModel.swift */, 01004F2F22721C3800991ECC /* RadioButton.swift */, + EA7AE5462C73C01A00107C74 /* CheckboxesModel.swift */, + EA7AE5482C7403DC00107C74 /* Checkboxes.swift */, 31BE15CA23D8924C00452370 /* CheckboxModel.swift */, 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, AAC6F166243332E400F295C1 /* RadioSwatchesModel.swift */, @@ -2848,6 +2860,7 @@ AA7F32AD246C0F8C00C965BA /* ListLeftVariableRadioButtonAllTextAndLinks.swift in Sources */, EAA482CE2B45F2F300978105 /* MFLoadingSpinner+VDS.swift in Sources */, D272F5F92473163100BD1A8F /* BarButtonItem.swift in Sources */, + EA7AE54D2C74CAD700107C74 /* RadioButtonsModel.swift in Sources */, D2D2FCF3252B72CF0033EAAA /* MoleculeSectionFooter.swift in Sources */, 0A9D09202433796500D2E6C0 /* BarsIndicatorView.swift in Sources */, D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */, @@ -3108,6 +3121,7 @@ AA69AAF62445BF5700AF3D3B /* ListLeftVariableCheckboxBodyText.swift in Sources */, AFA4935729EE3DCC001A9663 /* AlertDelegateProtocol.swift in Sources */, 58A9DD7D2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift in Sources */, + EA7AE54B2C74CACA00107C74 /* RadioButtons.swift in Sources */, D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, 27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */, @@ -3265,6 +3279,7 @@ 01F2C20327C81F9700DC3D36 /* SubNavManagerNavigationController.swift in Sources */, EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */, AA997252247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift in Sources */, + EA7AE5492C7403DC00107C74 /* Checkboxes.swift in Sources */, D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */, D23EA7FB2475F09800D60C34 /* CarouselItemProtocol.swift in Sources */, D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */, @@ -3315,6 +3330,7 @@ D2D3957D252FDBCD00047B11 /* ModalSectionListTemplateModel.swift in Sources */, D2B9D0E4265EEE9D0084735C /* MoleculeListProtocol.swift in Sources */, D29C559625C099630082E7D6 /* VideoDataManager.swift in Sources */, + EA7AE5472C73C01A00107C74 /* CheckboxesModel.swift in Sources */, 8D4687E2242E2DE400802879 /* ListFourColumnDataUsageListItemModel.swift in Sources */, D29E28DD23D7404C00ACEA85 /* ContainerHelper.swift in Sources */, EA6642912BCDA97300D81DC4 /* TileContainer.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift b/MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift new file mode 100644 index 00000000..3cd6cd1d --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift @@ -0,0 +1,55 @@ +// +// Checkboxes.swift +// MVMCoreUI +// +// Created by Matt Bruce on 8/19/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +open class Checkboxes: VDS.CheckboxGroup, VDSMoleculeViewProtocol { + + //------------------------------------------------------ + // MARK: - Properties + //------------------------------------------------------ + open var viewModel: CheckboxesModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? + + // Form Validation + var fieldKey: String? + var fieldValue: JSONValue? + var groupName: String? + + /// The models for the molecules. + public var checkboxes: [CheckboxLabelModel]? + + // MARK: - MoleculeViewProtocol + public func viewModelDidUpdate() { + surface = viewModel.surface + showError = viewModel.showError + isEnabled = viewModel.enabled && !viewModel.readOnly + checkboxes = viewModel.checkboxes + checkboxes?.forEach { + FormValidator.setupValidation(for: $0.checkbox, delegate: delegateObject?.formHolderDelegate) + } + + selectorModels = viewModel.checkboxes.toVDSCheckboxItemModel(surface: surface, + delegateObject: delegateObject, + additionalData: additionalData) + } + + open func updateView(_ size: CGFloat) {} + + open override func didSelect(_ selectedControl: CheckboxItem) { + super.didSelect(selectedControl) + + // since the boxes has the state being tracked, we need to update the values here. + if let index = items.firstIndex(where: {$0 === selectedControl}), let selectedBox = checkboxes?[index] { + selectedBox.checkbox.selected = true + } + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift new file mode 100644 index 00000000..9ffbc20a --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift @@ -0,0 +1,85 @@ +// +// CheckboxesModel.swift +// MVMCoreUI +// +// Created by Matt Bruce on 8/19/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation +import MVMCore +import VDS + +@objcMembers public class CheckboxesModel: MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public static var identifier: String { "checkboxes" } + public var id: String = UUID().uuidString + + public var backgroundColor: Color? + public var accessibilityIdentifier: String? + + public var enabled: Bool = true + public var required: Bool = true + public var readOnly: Bool = false + public var showError: Bool = false + public var inverted: Bool = false + public var surface: Surface { inverted ? .dark : .light } + + public var checkboxes: [CheckboxLabelModel] + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case id + case moleculeName + case accessibilityIdentifier + case inverted + case enabled + case readOnly + case showError + case checkboxes + } + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + + public init(with checkboxes: [CheckboxLabelModel]){ + self.checkboxes = checkboxes + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + + id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) + showError = try typeContainer.decodeIfPresent(Bool.self, forKey: .showError) ?? false + enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true + readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false + + if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { + self.inverted = inverted + } + checkboxes = try typeContainer.decode([CheckboxLabelModel].self, forKey: .checkboxes) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) + try container.encodeIfPresent(moleculeName, forKey: .moleculeName) + try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) + try container.encode(readOnly, forKey: .readOnly) + try container.encode(enabled, forKey: .enabled) + try container.encode(inverted, forKey: .inverted) + try container.encode(checkboxes, forKey: .checkboxes) + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift new file mode 100644 index 00000000..24d1dee7 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift @@ -0,0 +1,54 @@ +// +// RadioButtons.swift +// MVMCoreUI +// +// Created by Matt Bruce on 8/20/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +open class RadioButtons: VDS.RadioButtonGroup, VDSMoleculeViewProtocol { + + //------------------------------------------------------ + // MARK: - Properties + //------------------------------------------------------ + open var viewModel: RadioButtonsModel! + open var delegateObject: MVMCoreUIDelegateObject? + open var additionalData: [AnyHashable : Any]? + + // Form Validation + var fieldKey: String? + var fieldValue: JSONValue? + var groupName: String? + + /// The models for the molecules. + public var radioButtons: [RadioButtonLabelModel]? + + // MARK: - MoleculeViewProtocol + public func viewModelDidUpdate() { + showError = viewModel.showError + isEnabled = viewModel.enabled && !viewModel.readOnly + surface = viewModel.surface + + radioButtons = viewModel.radioButtons + selectorModels = viewModel.radioButtons.toVDSRadioButtonItemModel(surface: surface, + delegateObject: delegateObject, + additionalData: additionalData) + FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate) + } + + open func updateView(_ size: CGFloat) {} + + open override func didSelect(_ selectedControl: RadioButtonItem) { + super.didSelect(selectedControl) + + // since the boxes has the state being tracked, we need to update the values here. + if let index = items.firstIndex(where: {$0 === selectedControl}), let selectedBox = radioButtons?[index] { + radioButtons?.forEach { $0.radioButton.state = false } + selectedBox.radioButton.state = true + } + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift new file mode 100644 index 00000000..b1277d08 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift @@ -0,0 +1,72 @@ +// +// RadioButtonsModel.swift +// MVMCoreUI +// +// Created by Matt Bruce on 8/20/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation +import MVMCore +import VDS + +@objcMembers public class RadioButtonsModel: FormFieldModel { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public override static var identifier: String { "radioButtons" } + + public var radioButtons: [RadioButtonLabelModel] + + //-------------------------------------------------- + // MARK: - Form Validation + //-------------------------------------------------- + + /// Returns the fieldValue of the selected box, otherwise the text of the selected box. + public override func formFieldValue() -> AnyHashable? { + guard enabled else { return nil } + let selectedBox = radioButtons.first { $0.radioButton.state } + return selectedBox?.radioButton.formFieldValue() + } + + //-------------------------------------------------- + // MARK: - Server Value + //-------------------------------------------------- + open override func formFieldServerValue() -> AnyHashable? { + return formFieldValue() + } + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case radioButtons + } + + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + + public init(with radioButtons: [RadioButtonLabelModel]){ + self.radioButtons = radioButtons + super.init() + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + radioButtons = try typeContainer.decode([RadioButtonLabelModel].self, forKey: .radioButtons) + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(radioButtons, forKey: .radioButtons) + } +} From 6b608b4a8aaffd317a869cf341826184e6dd393c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 08:45:23 -0500 Subject: [PATCH 02/46] added showError Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift index c96a8266..6bf8c0be 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift @@ -23,7 +23,7 @@ import VDS public var enabled: Bool = true public var required: Bool = true public var readOnly: Bool = false - public var showError: Bool? + public var showError: Bool = false public var errorMessage: String? public var initialErrorMessage: String? @@ -66,6 +66,7 @@ import VDS case moleculeName case accessibilityIdentifier case errorMessage + case showError case enabled case readOnly case required @@ -107,6 +108,7 @@ import VDS accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) initialErrorMessage = errorMessage + showError = try typeContainer.decodeIfPresent(Bool.self, forKey: .showError) ?? false enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required) ?? true readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false @@ -126,6 +128,7 @@ import VDS try container.encodeIfPresent(errorMessage, forKey: .errorMessage) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(groupName, forKey: .groupName) + try container.encode(showError, forKey: .showError) try container.encode(readOnly, forKey: .readOnly) try container.encode(enabled, forKey: .enabled) try container.encode(required, forKey: .required) From d8c83f9230c456f9a6b92e4a19aee6ac2a534bb3 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 08:45:38 -0500 Subject: [PATCH 03/46] removed delegate that isn't used anywhere. Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift index 6701f2c6..7216ef54 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift @@ -9,10 +9,6 @@ import Foundation import VDS -public protocol RadioBoxSelectionDelegate: AnyObject { - func selected(radioBox: RadioBoxModel) -} - open class RadioBoxes: VDS.RadioBoxGroup, VDSMoleculeViewProtocol { //------------------------------------------------------ @@ -29,13 +25,12 @@ open class RadioBoxes: VDS.RadioBoxGroup, VDSMoleculeViewProtocol { /// The models for the molecules. public var boxes: [RadioBoxModel]? - public weak var radioDelegate: RadioBoxSelectionDelegate? // MARK: - MoleculeViewProtocol public func viewModelDidUpdate() { boxes = viewModel.boxes surface = viewModel.surface - selectorModels = viewModel.selectorModels + selectorModels = viewModel.boxes.toVDSRadioBoxModel(surface: surface) FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate) } @@ -50,7 +45,8 @@ open class RadioBoxes: VDS.RadioBoxGroup, VDSMoleculeViewProtocol { boxes?.forEach { $0.selected = false } selectedBox.selected = true _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) - radioDelegate?.selected(radioBox: selectedBox) } } } + + From aeabee2666ef466260686b62ea082f3e7c47de6f Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 08:49:12 -0500 Subject: [PATCH 04/46] refactored to convertToXXXModel Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Selectors/Checkboxes.swift | 2 +- .../Atomic/Atoms/Selectors/RadioBoxes.swift | 2 +- .../Atoms/Selectors/RadioBoxesModel.swift | 31 ++++++++++--------- .../Atomic/Atoms/Selectors/RadioButtons.swift | 2 +- .../Atoms/Views/CheckboxLabelModel.swift | 24 +++++++++++++- 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift b/MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift index 3cd6cd1d..87a755a6 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift @@ -36,7 +36,7 @@ open class Checkboxes: VDS.CheckboxGroup, VDSMoleculeViewProtocol { FormValidator.setupValidation(for: $0.checkbox, delegate: delegateObject?.formHolderDelegate) } - selectorModels = viewModel.checkboxes.toVDSCheckboxItemModel(surface: surface, + selectorModels = viewModel.checkboxes.convertToVDSCheckboxItemModel(surface: surface, delegateObject: delegateObject, additionalData: additionalData) } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift index 7216ef54..88a0fb34 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxes.swift @@ -30,7 +30,7 @@ open class RadioBoxes: VDS.RadioBoxGroup, VDSMoleculeViewProtocol { public func viewModelDidUpdate() { boxes = viewModel.boxes surface = viewModel.surface - selectorModels = viewModel.boxes.toVDSRadioBoxModel(surface: surface) + selectorModels = viewModel.boxes.convertToVDSRadioBoxModel(surface: surface) FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate) } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index 463afde3..f86d595f 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -16,20 +16,7 @@ import VDS public override static var identifier: String { "radioBoxes" } public var boxes: [RadioBoxModel] - - public var selectorModels: [VDS.RadioBoxGroup.RadioBoxItemModel] { - boxes.compactMap({ item in - var radioBox = RadioBoxGroup.RadioBoxItemModel() - radioBox.text = item.text - radioBox.subText = item.subText - radioBox.subTextRight = item.subTextRight - radioBox.surface = surface - radioBox.selected = item.selected - radioBox.strikethrough = item.strikethrough - radioBox.disabled = !(item.enabled && !item.readOnly) - return radioBox - }) - } + //-------------------------------------------------- // MARK: - Form Validation //-------------------------------------------------- @@ -83,3 +70,19 @@ import VDS try container.encode(boxes, forKey: .boxes) } } + +extension Array where Element == RadioBoxModel { + internal func convertToVDSRadioBoxModel(surface: Surface) -> [RadioBoxGroup.RadioBoxItemModel] { + compactMap({ item in + var radioBox = RadioBoxGroup.RadioBoxItemModel() + radioBox.text = item.text + radioBox.subText = item.subText + radioBox.subTextRight = item.subTextRight + radioBox.surface = surface + radioBox.selected = item.selected + radioBox.strikethrough = item.strikethrough + radioBox.disabled = !(item.enabled && !item.readOnly) + return radioBox + }) + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift index 24d1dee7..3e1d9204 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift @@ -33,7 +33,7 @@ open class RadioButtons: VDS.RadioButtonGroup, VDSMoleculeViewProtocol { surface = viewModel.surface radioButtons = viewModel.radioButtons - selectorModels = viewModel.radioButtons.toVDSRadioButtonItemModel(surface: surface, + selectorModels = viewModel.radioButtons.convertToVDSRadioButtonItemModel(surface: surface, delegateObject: delegateObject, additionalData: additionalData) FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate) diff --git a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift index faa13e60..0d09a97f 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift @@ -36,5 +36,27 @@ import VDS self.label = label self.subTitle = subTitle } - +} + +extension Array where Element == CheckboxLabelModel { + internal func convertToVDSCheckboxItemModel(surface: Surface, + delegateObject: MVMCoreUIDelegateObject?, + additionalData: [AnyHashable: Any]?) -> [CheckboxGroup.CheckboxItemModel] { + return compactMap({ model in + var item = CheckboxGroup.CheckboxItemModel() + item.inputId = model.checkbox.fieldKey + item.labelText = model.label.text + if let attributes = model.label.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) { + item.labelTextAttributes = attributes + } + item.childText = model.subTitle?.text + if let attributes = model.subTitle?.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) { + item.childTextAttributes = attributes + } + item.surface = surface + item.selected = model.checkbox.selected + item.disabled = !(model.checkbox.enabled && !model.checkbox.readOnly) + return item + }) + } } From 3fd10bf199563f733b77c5c3ca5c904314eaa8eb Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 08:49:20 -0500 Subject: [PATCH 05/46] added registration Signed-off-by: Matt Bruce --- MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index c45936cf..dbaefc49 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -50,8 +50,10 @@ open class CoreUIModelMapping: ModelMapping { // MARK:- Selectors ModelRegistry.register(handler: RadioButton.self, for: RadioButtonModel.self) + ModelRegistry.register(handler: RadioButtons.self, for: RadioButtonsModel.self) ModelRegistry.register(handler: RadioBoxes.self, for: RadioBoxesModel.self) ModelRegistry.register(handler: Checkbox.self, for: CheckboxModel.self) + ModelRegistry.register(handler: Checkboxes.self, for: CheckboxesModel.self) ModelRegistry.register(handler: RadioSwatches.self, for: RadioSwatchesModel.self) ModelRegistry.register(handler: Tags.self, for: TagsModel.self) ModelRegistry.register(handler: Tag.self, for: TagModel.self) From b71a4c5b257cdb17d3ff48677488ca5c4be12bd8 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 08:49:36 -0500 Subject: [PATCH 06/46] refactored to convertTo Signed-off-by: Matt Bruce --- .../RadioButtonLabelModel.swift | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift index 0f4a4be6..294dd14b 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift @@ -40,5 +40,27 @@ import VDS self.label = label self.subTitle = subTitle } - +} + +extension Array where Element == RadioButtonLabelModel { + internal func convertToVDSRadioButtonItemModel(surface: Surface, + delegateObject: MVMCoreUIDelegateObject?, + additionalData: [AnyHashable: Any]?) -> [RadioButtonGroup.RadioButtonItemModel] { + return compactMap({ model in + var item = RadioButtonGroup.RadioButtonItemModel() + item.inputId = model.radioButton.fieldKey + item.labelText = model.label.text + if let attributes = model.label.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) { + item.labelTextAttributes = attributes + } + item.childText = model.subTitle?.text + if let attributes = model.subTitle?.attributes?.toVDSLabelAttributeModel(delegateObject: delegateObject, additionalData: additionalData) { + item.childTextAttributes = attributes + } + item.surface = surface + item.selected = model.radioButton.state + item.disabled = !(model.radioButton.enabled && !model.radioButton.readOnly) + return item + }) + } } From e3f22efb1297a3c6326122c6b42b14ad397da319 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 08:49:51 -0500 Subject: [PATCH 07/46] updated to convertTo Signed-off-by: Matt Bruce --- .../Extensions/VDS-LabelAttributeModel.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Atomic/Extensions/VDS-LabelAttributeModel.swift b/MVMCoreUI/Atomic/Extensions/VDS-LabelAttributeModel.swift index 4eab03b2..6b31175c 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-LabelAttributeModel.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-LabelAttributeModel.swift @@ -16,7 +16,7 @@ extension Array where Element: MVMCoreUI.LabelAttributeModel { var attributes: [any VDS.LabelAttributeModel] = [] forEach { atomicLabelAttribute in if let attr = atomicLabelAttribute as? (any VDSLabelAttributeConvertable), - let vds = attr.convertToVDSLabelAttirbute(delegateObject: delegateObject, + let vds = attr.convertToVDSLabelAttribute(delegateObject: delegateObject, additionalData: additionalData){ attributes.append(vds) } @@ -28,12 +28,12 @@ extension Array where Element: MVMCoreUI.LabelAttributeModel { //VDS Convertable Protocol and Extensions public protocol VDSLabelAttributeConvertable { associatedtype LabelAttributeType: VDS.LabelAttributeModel - func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> LabelAttributeType? + func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> LabelAttributeType? } extension LabelAttributeUnderlineModel: VDSLabelAttributeConvertable { - public func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> UnderlineLabelAttribute? { + public func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> UnderlineLabelAttribute? { guard let style = UnderlineLabelAttribute.Style(rawValue: style.rawValue) else { return nil } var pattern: UnderlineLabelAttribute.Pattern? @@ -50,7 +50,7 @@ extension LabelAttributeUnderlineModel: VDSLabelAttributeConvertable { } extension LabelAttributeActionModel: VDSLabelAttributeConvertable { - public func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> ActionLabelAttribute? { + public func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> ActionLabelAttribute? { var vdsAttribute = VDS.ActionLabelAttribute(location: location, length: length) vdsAttribute.subscriber = vdsAttribute.action.sink { [weak self] in guard let self else { return } @@ -64,7 +64,7 @@ extension LabelAttributeActionModel: VDSLabelAttributeConvertable { } extension LabelAttributeFontModel: VDSLabelAttributeConvertable { - public func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> TextStyleLabelAttribute? { + public func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> TextStyleLabelAttribute? { var textStyle: TextStyle? if let found = style?.vdsTextStyle() { @@ -82,7 +82,7 @@ extension LabelAttributeFontModel: VDSLabelAttributeConvertable { } extension LabelAttributeColorModel: VDSLabelAttributeConvertable { - public func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> ColorLabelAttribute? { + public func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> ColorLabelAttribute? { guard let textColor else { return nil } return ColorLabelAttribute(location: location, length: length, @@ -91,14 +91,14 @@ extension LabelAttributeColorModel: VDSLabelAttributeConvertable { } extension LabelAttributeStrikeThroughModel: VDSLabelAttributeConvertable { - public func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> StrikeThroughLabelAttribute? { + public func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> StrikeThroughLabelAttribute? { return StrikeThroughLabelAttribute(location: location, length: length) } } extension LabelAttributeImageModel: VDSLabelAttributeConvertable { - public func convertToVDSLabelAttirbute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> AtomicImageLabelAttribute? { + public func convertToVDSLabelAttribute(delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> AtomicImageLabelAttribute? { var frame: CGRect? if let size { frame = CGRect(x: 0, y: 0, width: size, height: size) From 94ace3d49ae41f5bdff1121a67dbeebc75d7c9e6 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 13:59:07 -0500 Subject: [PATCH 08/46] added new models/views Signed-off-by: Matt Bruce --- MVMCoreUI.xcodeproj/project.pbxproj | 16 +++ .../FormFields/DatePickerEntryField.swift | 44 ++++++ .../DatePickerEntryFieldModel.swift | 82 +++++++++++ MVMCoreUI/Atomic/Atoms/Views/Calendar.swift | 12 ++ .../Atomic/Atoms/Views/CalendarView.swift | 62 +++++++++ .../Atoms/Views/CalendarViewModel.swift | 131 ++++++++++++++++++ 6 files changed, 347 insertions(+) create mode 100644 MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift create mode 100644 MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Views/Calendar.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Views/CalendarView.swift create mode 100644 MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index e8c458bd..fbb120aa 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -598,6 +598,10 @@ EA7AE5492C7403DC00107C74 /* Checkboxes.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5482C7403DC00107C74 /* Checkboxes.swift */; }; EA7AE54B2C74CACA00107C74 /* RadioButtons.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE54A2C74CACA00107C74 /* RadioButtons.swift */; }; EA7AE54D2C74CAD700107C74 /* RadioButtonsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE54C2C74CAD700107C74 /* RadioButtonsModel.swift */; }; + EA7AE54F2C74EB3700107C74 /* CalendarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE54E2C74EB3700107C74 /* CalendarView.swift */; }; + EA7AE5512C74EB4500107C74 /* CalendarViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5502C74EB4500107C74 /* CalendarViewModel.swift */; }; + EA7AE5532C74F1F600107C74 /* DatePickerEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5522C74F1F600107C74 /* DatePickerEntryField.swift */; }; + EA7AE5552C74F20600107C74 /* DatePickerEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7AE5542C74F20600107C74 /* DatePickerEntryFieldModel.swift */; }; EA7D81602B2B6E6800D29F9E /* Icon.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D815F2B2B6E6800D29F9E /* Icon.swift */; }; EA7D81622B2B6E7F00D29F9E /* IconModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81612B2B6E7F00D29F9E /* IconModel.swift */; }; EA7D81642B2BABCB00D29F9E /* TooltipModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */; }; @@ -1231,6 +1235,10 @@ EA7AE5482C7403DC00107C74 /* Checkboxes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkboxes.swift; sourceTree = ""; }; EA7AE54A2C74CACA00107C74 /* RadioButtons.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtons.swift; sourceTree = ""; }; EA7AE54C2C74CAD700107C74 /* RadioButtonsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonsModel.swift; sourceTree = ""; }; + EA7AE54E2C74EB3700107C74 /* CalendarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarView.swift; sourceTree = ""; }; + EA7AE5502C74EB4500107C74 /* CalendarViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarViewModel.swift; sourceTree = ""; }; + EA7AE5522C74F1F600107C74 /* DatePickerEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatePickerEntryField.swift; sourceTree = ""; }; + EA7AE5542C74F20600107C74 /* DatePickerEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatePickerEntryFieldModel.swift; sourceTree = ""; }; EA7D815F2B2B6E6800D29F9E /* Icon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Icon.swift; sourceTree = ""; }; EA7D81612B2B6E7F00D29F9E /* IconModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconModel.swift; sourceTree = ""; }; EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TooltipModel.swift; sourceTree = ""; }; @@ -2374,6 +2382,8 @@ EA7D815F2B2B6E6800D29F9E /* Icon.swift */, EA7D81632B2BABCB00D29F9E /* TooltipModel.swift */, EA7D81652B2BABD200D29F9E /* Tooltip.swift */, + EA7AE5502C74EB4500107C74 /* CalendarViewModel.swift */, + EA7AE54E2C74EB3700107C74 /* CalendarView.swift */, ); path = Views; sourceTree = ""; @@ -2525,6 +2535,8 @@ D2BEFEF5248A954C00FAB3A9 /* FormFields */ = { isa = PBXGroup; children = ( + EA7AE5542C74F20600107C74 /* DatePickerEntryFieldModel.swift */, + EA7AE5522C74F1F600107C74 /* DatePickerEntryField.swift */, EA5DBDAA2C35B6C500290DF8 /* FormFieldModel.swift */, D2BEFEF6248A957A00FAB3A9 /* Tags */, D29DF22B21E6A0FA003B2FB9 /* TextFields */, @@ -2875,6 +2887,7 @@ EAB14BC127D935F00012AB2C /* RuleCompareModelProtocol.swift in Sources */, 011D95A924057AC7000E3791 /* FormGroupWatcherFieldProtocol.swift in Sources */, EA1B02DE2C41BFD200F0758B /* RuleVDSModel.swift in Sources */, + EA7AE5532C74F1F600107C74 /* DatePickerEntryField.swift in Sources */, EA985C892981AB7100F2FF2E /* VDS-TextStyle.swift in Sources */, BB2BF0EA2452A9BB001D0FC2 /* ListDeviceComplexButtonSmall.swift in Sources */, D20C700B250BFDE40095B21C /* NotificationContainerView.swift in Sources */, @@ -3123,6 +3136,7 @@ 58A9DD7D2AC2103300F5E0B0 /* ReplaceableMoleculeBehaviorModel.swift in Sources */, EA7AE54B2C74CACA00107C74 /* RadioButtons.swift in Sources */, D264FAA3243E632F00D98315 /* ProgrammaticCollectionViewController.swift in Sources */, + EA7AE5552C74F20600107C74 /* DatePickerEntryFieldModel.swift in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, 27F9736A246750BE00CAB5C5 /* ScreenBrightnessModifierBehavior.swift in Sources */, EA6E8B972B504A4D000139B4 /* ButtonGroupModel.swift in Sources */, @@ -3310,6 +3324,7 @@ BB6C6AC824225290005F7224 /* ListOneColumnTextWithWhitespaceDividerShort.swift in Sources */, 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */, D21B7F73243BAC6800051ABF /* CollectionItemModelProtocol.swift in Sources */, + EA7AE5512C74EB4500107C74 /* CalendarViewModel.swift in Sources */, AA104B1A24474A66004D2810 /* HeadersH2Buttons.swift in Sources */, C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */, D2D2FCF0252B72AF0033EAAA /* MoleculeSectionFooterModel.swift in Sources */, @@ -3371,6 +3386,7 @@ D2169301251E51E7002A6324 /* SectionListTemplate.swift in Sources */, 0A6682AA2435125F00AD3CA1 /* Styler.swift in Sources */, D264FAA7243FE13B00D98315 /* RadioBox.swift in Sources */, + EA7AE54F2C74EB3700107C74 /* CalendarView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift new file mode 100644 index 00000000..b798b068 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift @@ -0,0 +1,44 @@ +// +// DatePickerEntryField.swift +// MVMCoreUI +// +// Created by Matt Bruce on 8/20/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +open class DatePickerEntryField: VDS.DatePicker, VDSMoleculeViewProtocol { + //-------------------------------------------------- + // MARK: - Public Properties + //-------------------------------------------------- + public var viewModel: DatePickerEntryFieldModel! + public var delegateObject: MVMCoreUIDelegateObject? + public var additionalData: [AnyHashable : Any]? + + //-------------------------------------------------- + // MARK: - Public Methods + //-------------------------------------------------- + + public func viewModelDidUpdate() { + surface = viewModel.surface + labelText = "Date" + helperText = "Pick a date" + selectedDate = viewModel.selectedDate + calendarModel = viewModel.calendar.convertToVDSCalendarModel() + FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate) + } + + open override func setDefaults() { + super.setDefaults() + onChange = { [weak self] control in + guard let self, let viewModel, isEnabled else { return } + viewModel.selectedDate = control.selectedDate + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) + } + } + + public func updateView(_ size: CGFloat) {} + +} diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift new file mode 100644 index 00000000..68b63309 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift @@ -0,0 +1,82 @@ +// +// DatePickerEntryFieldModel.swift +// MVMCoreUI +// +// Created by Matt Bruce on 8/20/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +open class DatePickerEntryFieldModel: FormFieldModel { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public override static var identifier: String { "datePicker" } + + public var dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateStyle = .medium + formatter.timeZone = NSTimeZone.system + formatter.locale = .current + formatter.formatterBehavior = .default + return formatter + }() + + /// Update the property value to alter the format of how the date is presented. + public var dateFormat: String = "MMM d, y" { + didSet { dateFormatter.dateFormat = dateFormat } + } + + public var selectedDate: Date? + public var calendar: CalendarViewModel = .init() + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { + case dateFormat + case selectedDate + case calendar + } + + //-------------------------------------------------- + // MARK: - Form Validation + //-------------------------------------------------- + + /// Returns the fieldValue of the selected box, otherwise the text of the selected box. + public override func formFieldValue() -> AnyHashable? { + guard let selectedDate, enabled else { return nil } + return dateFormatter.string(from: selectedDate) + } + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + if let dateFormat = try container.decodeIfPresent(String.self, forKey: .dateFormat) { + self.dateFormat = dateFormat + dateFormatter.dateFormat = dateFormat + } + + if let date = try container.decodeIfPresent(String.self, forKey: .selectedDate) { + selectedDate = calendar.dateFormatter.date(from: date) + } + + if let calendar = try container.decodeIfPresent(CalendarViewModel.self, forKey: .calendar) { + self.calendar = calendar + } + + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(selectedDate, forKey: .selectedDate) + try container.encode(calendar, forKey: .calendar) + } +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/Calendar.swift b/MVMCoreUI/Atomic/Atoms/Views/Calendar.swift new file mode 100644 index 00000000..e6e8bb28 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/Calendar.swift @@ -0,0 +1,12 @@ +// +// Calendar.swift +// MVMCoreUI +// +// Created by Matt Bruce on 8/20/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +open class CalendarView: VDS.CalendarBase, VDSMoleculeViewProtocol diff --git a/MVMCoreUI/Atomic/Atoms/Views/CalendarView.swift b/MVMCoreUI/Atomic/Atoms/Views/CalendarView.swift new file mode 100644 index 00000000..9a0850e8 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/CalendarView.swift @@ -0,0 +1,62 @@ +// +// Calendar.swift +// MVMCoreUI +// +// Created by Matt Bruce on 8/20/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +open class CalendarView: VDS.CalendarBase, VDSMoleculeViewProtocol { + //-------------------------------------------------- + // MARK: - Public Properties + //-------------------------------------------------- + public var viewModel: CalendarViewModel! + public var delegateObject: MVMCoreUIDelegateObject? + public var additionalData: [AnyHashable : Any]? + + //-------------------------------------------------- + // MARK: - Public Methods + //-------------------------------------------------- + + public func viewModelDidUpdate() { + if let _selectedDate = viewModel.selectedDate { + selectedDate = _selectedDate + } + + if let _activeDates = viewModel.activeDates { + activeDates = _activeDates + } + + if let _hideContainerBorder = viewModel.hideContainerBorder { + hideContainerBorder = _hideContainerBorder + } + + if let _hideCurrentDateIndicator = viewModel.hideCurrentDateIndicator { + hideCurrentDateIndicator = _hideCurrentDateIndicator + } + + if let _inactiveDates = viewModel.inactiveDates { + inactiveDates = _inactiveDates + } + + if let _indicators = viewModel.indicators { + indicators = _indicators + } + + if let _maxDate = viewModel.maxDate { + maxDate = _maxDate + } + + if let _minDate = viewModel.minDate { + minDate = _minDate + } + + surface = viewModel.surface + } + + public func updateView(_ size: CGFloat) {} + +} diff --git a/MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift new file mode 100644 index 00000000..16e9b425 --- /dev/null +++ b/MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift @@ -0,0 +1,131 @@ +// +// CalendarModel.swift +// MVMCoreUI +// +// Created by Matt Bruce on 8/20/24. +// Copyright © 2024 Verizon Wireless. All rights reserved. +// + +import Foundation +import VDS + +open class CalendarViewModel: MoleculeModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "calendar" + public var id: String = UUID().uuidString + public var backgroundColor: Color? + + public var dateFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateStyle = .medium + formatter.timeZone = NSTimeZone.system + formatter.locale = .current + formatter.formatterBehavior = .default + return formatter + }() + + /// Update the property value to alter the format of how the date is presented. + public var dateFormat: String = "MMM d, y" { + didSet { dateFormatter.dateFormat = dateFormat } + } + + public var hideContainerBorder: Bool? + public var hideCurrentDateIndicator: Bool? + public var activeDates: [Date]? + public var inactiveDates: [Date]? + public var selectedDate: Date? + public var minDate: Date? + public var maxDate: Date? + public var indicators: [CalendarBase.CalendarIndicatorModel]? + + //-------------------------------------------------- + // MARK: - VDS Properties + //-------------------------------------------------- + public var surface: Surface { inverted ? .dark : .light } + public var inverted: Bool = false + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + private enum CodingKeys: String, CodingKey { + case id + case inverted + case dateFormat + case hideContainerBorder + case hideCurrentDateIndicator + case activeDates + case inactiveDates + case selectedDate + case minDate + case maxDate + case indicators + + } + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + public init() {} + + //-------------------------------------------------- + // MARK: - Codec + //-------------------------------------------------- + required public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + id = try container.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString + inverted = try container.decodeIfPresent(Bool.self, forKey: .inverted) ?? false + + hideContainerBorder = try container.decodeIfPresent(Bool.self, forKey: .hideContainerBorder) + hideCurrentDateIndicator = try container.decodeIfPresent(Bool.self, forKey: .hideCurrentDateIndicator) + + if let dateFormat = try container.decodeIfPresent(String.self, forKey: .dateFormat) { + self.dateFormat = dateFormat + dateFormatter.dateFormat = dateFormat + } + + if let dates = try container.decodeIfPresent([String].self, forKey: .activeDates) { + activeDates = dates.compactMap { dateFormatter.date(from: $0) } + } + + if let dates = try container.decodeIfPresent([String].self, forKey: .inactiveDates) { + inactiveDates = dates.compactMap { dateFormatter.date(from: $0) } + } + + if let date = try container.decodeIfPresent(String.self, forKey: .selectedDate) { + selectedDate = dateFormatter.date(from: date) + } + + if let date = try container.decodeIfPresent(String.self, forKey: .minDate) { + minDate = dateFormatter.date(from: date) + } + + if let date = try container.decodeIfPresent(String.self, forKey: .maxDate) { + maxDate = dateFormatter.date(from: date) + } + + indicators = try container.decodeIfPresent([CalendarBase.CalendarIndicatorModel].self, forKey: .indicators) + + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(id, forKey: .id) + try container.encode(inverted, forKey: .inverted) + } +} + +extension CalendarViewModel { + public func convertToVDSCalendarModel() -> DatePicker.CalendarModel { + let defaults = DatePicker.CalendarModel() + return .init(hideContainerBorder: hideContainerBorder ?? defaults.hideContainerBorder , + hideCurrentDateIndicator: hideCurrentDateIndicator ?? defaults.hideCurrentDateIndicator, + activeDates: activeDates ?? defaults.activeDates, + inactiveDates: inactiveDates ?? defaults.inactiveDates, + selectedDate: selectedDate ?? defaults.selectedDate, + minDate: minDate ?? defaults.minDate, + maxDate: maxDate ?? defaults.maxDate, + indicators: indicators ?? defaults.indicators) + } +} From 478f2b6083ff322181a67cf19dfb4bead2756bec Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 13:59:19 -0500 Subject: [PATCH 09/46] added codable for VDS Signed-off-by: Matt Bruce --- .../Atomic/Extensions/VDS-Enums+Codable.swift | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index 8f565216..fa95360e 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -57,6 +57,40 @@ extension VDS.Button.Size: RawRepresentableCodable { public static var defaultValue: VDS.Button.Size? { nil } } +extension VDS.CalendarBase.CalendarIndicatorModel: Codable { + + enum CodingKeys: String, CodingKey { + case label + case date + case dateFormat + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let label = try container.decode(String.self, forKey: .label) + let formatter = Self.formatter() + formatter.dateFormat = try container.decodeIfPresent(String.self, forKey: .dateFormat) ?? "MMM d, y" + let foundDate = try container.decode(String.self, forKey: .date) + let date = formatter.date(from: foundDate)! + self = .init(label: label, date: date) + } + + public func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(label, forKey: .label) + try container.encode(Self.formatter().string(from: date), forKey: .date) + } + + static func formatter() -> DateFormatter { + let formatter = DateFormatter() + formatter.dateStyle = .medium + formatter.timeZone = NSTimeZone.system + formatter.locale = .current + formatter.formatterBehavior = .default + return formatter + } +} + //-------------------------------------------------- // MARK: - Decodable Defaults //-------------------------------------------------- From 8829bd7457ffad85eff0482ab04fd02904b2401f Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 13:59:27 -0500 Subject: [PATCH 10/46] added new mapping Signed-off-by: Matt Bruce --- MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift index dbaefc49..68494d90 100644 --- a/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift +++ b/MVMCoreUI/OtherHandlers/CoreUIModelMapping.swift @@ -41,6 +41,7 @@ open class CoreUIModelMapping: ModelMapping { ModelRegistry.register(handler: ButtonGroup.self, for: ButtonGroupModel.self) // MARK:- Entry Field + ModelRegistry.register(handler: DatePickerEntryField.self, for: DatePickerEntryFieldModel.self) ModelRegistry.register(handler: InputEntryField.self, for: TextEntryFieldModel.self) ModelRegistry.register(handler: MdnEntryField.self, for: MdnEntryFieldModel.self) ModelRegistry.register(handler: DigitEntryField.self, for: DigitEntryFieldModel.self) @@ -62,6 +63,7 @@ open class CoreUIModelMapping: ModelMapping { ModelRegistry.register(handler: Star.self, for: StarModel.self) // MARK:- Other Atoms + ModelRegistry.register(handler: CalendarView.self, for: CalendarViewModel.self) ModelRegistry.register(handler: ProgressBar.self, for: ProgressBarModel.self) ModelRegistry.register(handler: MultiProgress.self, for: MultiProgressBarModel.self) ModelRegistry.register(handler: CaretView.self, for: CaretViewModel.self) From 7b0f4e43289bfecbab310bb3c63df585f8925a70 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 13:59:52 -0500 Subject: [PATCH 11/46] update only after the model sets the properties Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift b/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift index 2bb95c43..8dfb9ae3 100644 --- a/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/VDSMoleculeViewProtocol.swift @@ -14,10 +14,12 @@ import MVMCore ///----------------------------------------------------------------------------- public protocol VDSMoleculeViewProtocol: MoleculeViewProtocol, MVMCoreViewProtocol { associatedtype ViewModel: MoleculeModelProtocol + var shouldUpdateView: Bool { get set } var viewModel: ViewModel! { get set } var delegateObject: MVMCoreUIDelegateObject? { get set } var additionalData: [AnyHashable: Any]? { get set } func viewModelDidUpdate() + func setNeedsUpdate() } extension VDSMoleculeViewProtocol { @@ -32,7 +34,10 @@ extension VDSMoleculeViewProtocol { self.delegateObject = delegateObject self.additionalData = additionalData viewModel = castedModel + shouldUpdateView = false viewModelDidUpdate() + shouldUpdateView = true + setNeedsUpdate() } public func update(viewModel: ViewModel){ From 25dce9e88cde184921f101c0878ce1ceffbe7256 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 14:19:15 -0500 Subject: [PATCH 12/46] refactored naming of method Signed-off-by: Matt Bruce --- .../Dropdown Fields/Item Dropdown/ItemDropdownEntryField.swift | 2 +- .../Atomic/Atoms/FormFields/TextFields/InputEntryField.swift | 2 +- .../Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Item Dropdown/ItemDropdownEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Item Dropdown/ItemDropdownEntryField.swift index 7025d18e..8861b50a 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Item Dropdown/ItemDropdownEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Item Dropdown/ItemDropdownEntryField.swift @@ -146,7 +146,7 @@ open class ItemDropdownEntryField: VDS.DropdownSelect, VDSMoleculeViewProtocol, isEnabled = viewModel.enabled isReadOnly = viewModel.readOnly isRequired = viewModel.required - tooltipModel = viewModel.tooltip?.toVDSTooltipModel() + tooltipModel = viewModel.tooltip?.convertToVDSTooltipModel() width = viewModel.width transparentBackground = viewModel.transparentBackground diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/InputEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/InputEntryField.swift index fb99a10a..476ee550 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/InputEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/InputEntryField.swift @@ -173,7 +173,7 @@ import VDS isEnabled = viewModel.enabled isReadOnly = viewModel.readOnly isRequired = viewModel.required - tooltipModel = viewModel.tooltip?.toVDSTooltipModel() + tooltipModel = viewModel.tooltip?.convertToVDSTooltipModel() width = viewModel.width transparentBackground = viewModel.transparentBackground diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift index bce7eb7b..e023df5d 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryField.swift @@ -126,7 +126,7 @@ open class TextViewEntryField: VDS.TextArea, VDSMoleculeViewProtocol, ObservingT isEnabled = viewModel.enabled isReadOnly = viewModel.readOnly isRequired = viewModel.required - tooltipModel = viewModel.tooltip?.toVDSTooltipModel() + tooltipModel = viewModel.tooltip?.convertToVDSTooltipModel() width = viewModel.width transparentBackground = viewModel.transparentBackground diff --git a/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift b/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift index 974cca8c..0c9886d7 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/TooltipModel.swift @@ -98,7 +98,7 @@ open class TooltipModel: MoleculeModelProtocol { } extension TooltipModel { - public func toVDSTooltipModel() -> Tooltip.TooltipModel { + public func convertToVDSTooltipModel() -> Tooltip.TooltipModel { var moleculeView: MoleculeViewProtocol? if let molecule, let view = ModelRegistry.createMolecule(molecule) { moleculeView = view From e030b460cea8dc6fdc95ae2b124267c55d409ec4 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 14:19:22 -0500 Subject: [PATCH 13/46] added final properties --- .../FormFields/DatePickerEntryField.swift | 8 +++++-- .../DatePickerEntryFieldModel.swift | 22 ++++++++++++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift index b798b068..5c1086df 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift @@ -23,8 +23,12 @@ open class DatePickerEntryField: VDS.DatePicker, VDSMoleculeViewProtocol { public func viewModelDidUpdate() { surface = viewModel.surface - labelText = "Date" - helperText = "Pick a date" + labelText = viewModel.title + helperText = viewModel.feedback + helperTextPlacement = viewModel.feedbackTextPlacement + tooltipModel = viewModel.tooltip?.convertToVDSTooltipModel() + transparentBackground = viewModel.transparentBackground + width = viewModel.width selectedDate = viewModel.selectedDate calendarModel = viewModel.calendar.convertToVDSCalendarModel() FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift index 68b63309..3ce2773a 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift @@ -31,7 +31,13 @@ open class DatePickerEntryFieldModel: FormFieldModel { public var selectedDate: Date? public var calendar: CalendarViewModel = .init() - + public var title: String? + public var feedback: String? + public var feedbackTextPlacement: VDS.DatePicker.HelperTextPlacement = .bottom + public var tooltip: TooltipModel? + public var transparentBackground: Bool = false + public var width: CGFloat? + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- @@ -39,6 +45,12 @@ open class DatePickerEntryFieldModel: FormFieldModel { case dateFormat case selectedDate case calendar + case title + case feedback + case feedbackTextPlacement + case tooltip + case transparentBackground + case width } //-------------------------------------------------- @@ -70,6 +82,14 @@ open class DatePickerEntryFieldModel: FormFieldModel { self.calendar = calendar } + title = try container.decodeIfPresent(String.self, forKey: .title) + feedback = try container.decodeIfPresent(String.self, forKey: .feedback) + feedbackTextPlacement = try container.decodeIfPresent(VDS.EntryFieldBase.HelperTextPlacement.self, forKey: .feedbackTextPlacement) ?? .bottom + + tooltip = try container.decodeIfPresent(TooltipModel.self, forKey: .tooltip) + transparentBackground = try container.decodeIfPresent(Bool.self, forKey: .transparentBackground) ?? false + width = try container.decodeIfPresent(CGFloat.self, forKey: .width) + try super.init(from: decoder) } From 29b56bf63b9b97b874820d56e8d962a6657ef645 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Tue, 20 Aug 2024 15:41:53 -0500 Subject: [PATCH 14/46] updated field Signed-off-by: Matt Bruce --- .../FormFields/DatePickerEntryField.swift | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift index 5c1086df..fd65ae92 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryField.swift @@ -20,6 +20,18 @@ open class DatePickerEntryField: VDS.DatePicker, VDSMoleculeViewProtocol { //-------------------------------------------------- // MARK: - Public Methods //-------------------------------------------------- + open override func setup() { + super.setup() + //turn off internal required rule + useRequiredRule = false + + publisher(for: .valueChanged) + .sink { [weak self] control in + guard let self, let viewModel, isEnabled else { return } + viewModel.selectedDate = control.selectedDate + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) + }.store(in: &subscribers) + } public func viewModelDidUpdate() { surface = viewModel.surface @@ -33,16 +45,7 @@ open class DatePickerEntryField: VDS.DatePicker, VDSMoleculeViewProtocol { calendarModel = viewModel.calendar.convertToVDSCalendarModel() FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate) } - - open override func setDefaults() { - super.setDefaults() - onChange = { [weak self] control in - guard let self, let viewModel, isEnabled else { return } - viewModel.selectedDate = control.selectedDate - _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) - } - } - + public func updateView(_ size: CGFloat) {} } From e7bcd32588aafbea29a9a52d8a46bb20c306c042 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 13:07:51 -0500 Subject: [PATCH 15/46] put the moleculeName in the base Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift index 6bf8c0be..8b68fb0a 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift @@ -15,6 +15,8 @@ import VDS // MARK: - Properties //-------------------------------------------------- public class var identifier: String { "" } + public var moleculeName: String { Self.identifier } + public var id: String = UUID().uuidString public var backgroundColor: Color? From 56b4142c14833a77e6770b352648d159ce767125 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 14:07:59 -0500 Subject: [PATCH 16/46] added isEnabled Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift index 8b68fb0a..7f43b8bb 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift @@ -137,3 +137,7 @@ import VDS try container.encode(inverted, forKey: .inverted) } } + +extension FormFieldModel { + public var isEnabled: Bool { enabled && !readOnly } +} From c41cf3f18e4820000e9608658ba76bfc77b3ba2e Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 14:08:57 -0500 Subject: [PATCH 17/46] converted to use FormFieldModel subclass Signed-off-by: Matt Bruce --- .../Atoms/Selectors/RadioBoxModel.swift | 55 +++++++------------ 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift index cd7623c2..8b9282a9 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift @@ -8,47 +8,34 @@ import MVMCore import VDS -@objcMembers public class RadioBoxModel: MoleculeModelProtocol, EnableableModelProtocol { +@objcMembers public class RadioBoxModel: FormFieldModel { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public static var identifier: String = "radioBox" - public var id: String = UUID().uuidString + public override static var identifier: String { "radioBox" } public var text: String public var subText: String? public var subTextRight: String? - public var backgroundColor: Color? - public var accessibilityIdentifier: 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? - public var inverted: Bool = false - public var surface: Surface { inverted ? .dark : .light } - + public var fieldValue: String? + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- private enum CodingKeys: String, CodingKey { - case id - case moleculeName case text case subText case subTextRight case backgroundColor - case accessibilityIdentifier case selected - case enabled case strikethrough - case fieldValue case action - case readOnly - case inverted + case fieldValue } //-------------------------------------------------- @@ -57,8 +44,19 @@ import VDS public init(text: String) { self.text = text + super.init() } + //-------------------------------------------------- + // MARK: - Form Validation + //-------------------------------------------------- + + /// Returns the fieldValue of the selected box, otherwise the text of the selected box. + public override func formFieldValue() -> AnyHashable? { + guard enabled else { return nil } + return fieldValue + } + //-------------------------------------------------- // MARK: - Codec //-------------------------------------------------- @@ -66,45 +64,30 @@ import VDS required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString text = try typeContainer.decode(String.self, forKey: .text) subText = try typeContainer.decodeIfPresent(String.self, forKey: .subText) subTextRight = try typeContainer.decodeIfPresent(String.self, forKey: .subTextRight) - accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) if let isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) { selected = isSelected } - 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 } - - if let inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) { - self.inverted = inverted - } - fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) action = try typeContainer.decodeModelIfPresent(codingKey: .action) + try super.init(from: decoder) } - public func encode(to encoder: Encoder) throws { + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(id, forKey: .id) - try container.encode(moleculeName, forKey: .moleculeName) try container.encode(text, forKey: .text) try container.encodeIfPresent(subText, forKey: .subText) try container.encodeIfPresent(subTextRight, forKey: .subTextRight) - 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) - try container.encode(inverted, forKey: .inverted) } } From c3290f83ba57577553fea0eaad4cd651f82e4649 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 14:09:24 -0500 Subject: [PATCH 18/46] updated for change in RadioBoxModel Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index f86d595f..9301a932 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -27,7 +27,7 @@ import VDS let selectedBox = boxes.first { (box) -> Bool in return box.selected } - return selectedBox?.fieldValue ?? selectedBox?.text + return selectedBox?.formFieldValue() ?? selectedBox?.text } //-------------------------------------------------- From 315eac1dacfbcb4102eb9536b49c7b4bcc9d2bcd Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 14:09:57 -0500 Subject: [PATCH 19/46] used new isEnabled in model Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/Checkbox.swift | 2 +- MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift | 2 +- MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift | 2 +- MVMCoreUI/Atomic/Atoms/Selectors/Toggle.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/Checkbox.swift b/MVMCoreUI/Atomic/Atoms/Selectors/Checkbox.swift index 3e6e2a84..728a295b 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/Checkbox.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/Checkbox.swift @@ -131,7 +131,7 @@ import VDS } //properties - isEnabled = viewModel.enabled && !viewModel.readOnly + isEnabled = viewModel.isEnabled isAnimated = viewModel.animated //call super here to go around the didSet diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift index 0ecd920b..fdb98deb 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButton.swift @@ -101,7 +101,7 @@ import VDS } isSelected = viewModel.state - isEnabled = viewModel.enabled && !viewModel.readOnly + isEnabled = viewModel.isEnabled RadioButtonSelectionHelper.setupForRadioButtonGroup(viewModel, self, delegateObject: delegateObject) } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift index 3e1d9204..683d28b3 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift @@ -29,7 +29,7 @@ open class RadioButtons: VDS.RadioButtonGroup, VDSMoleculeViewProtocol { // MARK: - MoleculeViewProtocol public func viewModelDidUpdate() { showError = viewModel.showError - isEnabled = viewModel.enabled && !viewModel.readOnly + isEnabled = viewModel.isEnabled surface = viewModel.surface radioButtons = viewModel.radioButtons diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Selectors/Toggle.swift index b229d12e..feaf3399 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/Toggle.swift @@ -108,7 +108,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) isOn = viewModel.selected surface = viewModel.surface isAnimated = viewModel.animated - isEnabled = viewModel.enabled && !viewModel.readOnly + isEnabled = viewModel.isEnabled showText = viewModel.showText if let onText = viewModel.onText { self.onText = onText diff --git a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift index b4825ee6..919cd953 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabel.swift @@ -64,7 +64,7 @@ import VDS //properties isAnimated = viewModel.checkbox.animated - isEnabled = viewModel.checkbox.enabled && !viewModel.checkbox.readOnly + isEnabled = viewModel.checkbox.isEnabled //call super here to go around the didSet //in this class @@ -78,7 +78,7 @@ import VDS //TODO: Fix issue with default state //showError = !isValid errorText = viewModel.checkbox.errorMessage - isEnabled = viewModel.checkbox.enabled + isEnabled = viewModel.checkbox.isEnabled }) } From 3270f21951532a5c1d5fb3003c6e2c14e0f0f9e6 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 14:10:09 -0500 Subject: [PATCH 20/46] used new isEnabled in model Signed-off-by: Matt Bruce --- .../Molecules/HorizontalCombinationViews/RadioButtonLabel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift index 39a578ba..5d2c10bb 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabel.swift @@ -106,7 +106,7 @@ import VDS } //properties - isEnabled = viewModel.radioButton.enabled && !viewModel.radioButton.readOnly + isEnabled = viewModel.radioButton.isEnabled isSelected = viewModel.radioButton.state //forms From 698f7b55205c2d6ec448a2d83e65da5f3be08257 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 14:10:23 -0500 Subject: [PATCH 21/46] subclass to formFieldModel Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Selectors/ToggleModel.swift | 66 +++---------------- 1 file changed, 10 insertions(+), 56 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift index c310e47c..7f937168 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift @@ -7,26 +7,18 @@ // import VDS -public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { +public class ToggleModel: FormFieldModel { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- - public static var identifier: String = "toggle" - public var id: String = UUID().uuidString - - public var accessibilityIdentifier: String? - public var backgroundColor: Color? + public override static var identifier: String { "toggle" } 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? - public var surface: Surface { inverted ? .dark : .light } - public var inverted: Bool = false public var showText: Bool = false public var onText: String? public var offText: String? @@ -34,61 +26,41 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { public var textWeight: VDS.Toggle.TextWeight = .regular public var textPosition: VDS.Toggle.TextPosition = .left - public var fieldKey: String? - public var groupName: String = FormValidator.defaultGroupName - public var baseValue: AnyHashable? - //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- private enum CodingKeys: String, CodingKey { - case id - case moleculeName case state case animated - case enabled - case readOnly case action - case backgroundColor - case accessibilityIdentifier case alternateAction case accessibilityText - case inverted case showText case onText case offText case textSize case textWeight case textPosition - - case fieldKey - case groupName } //-------------------------------------------------- // MARK: - Form Valdiation //-------------------------------------------------- - public func formFieldValue() -> AnyHashable? { + public override func formFieldValue() -> AnyHashable? { guard enabled else { return nil } return selected } - //-------------------------------------------------- - // MARK: - Server Value - //-------------------------------------------------- - open func formFieldServerValue() -> AnyHashable? { - return formFieldValue() - } - //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- public init(_ state: Bool, id: String = UUID().uuidString) { - self.selected = state + selected = state + super.init() baseValue = state self.id = id } @@ -100,8 +72,6 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - id = try typeContainer.decodeIfPresent(String.self, forKey: .id) ?? UUID().uuidString - if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { self.selected = state } @@ -112,44 +82,28 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { action = try typeContainer.decodeModelIfPresent(codingKey: .action) alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction) - accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) - baseValue = selected - fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) - 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 - - inverted = try typeContainer.decodeIfPresent(Bool.self, forKey: .inverted) ?? false showText = try typeContainer.decodeIfPresent(Bool.self, forKey: .showText) ?? false onText = try typeContainer.decodeIfPresent(String.self, forKey: .onText) offText = try typeContainer.decodeIfPresent(String.self, forKey: .offText) textSize = try typeContainer.decodeIfPresent(VDS.Toggle.TextSize.self, forKey: .textSize) ?? .small textWeight = try typeContainer.decodeIfPresent(VDS.Toggle.TextWeight.self, forKey: .textWeight) ?? .regular textPosition = try typeContainer.decodeIfPresent(VDS.Toggle.TextPosition.self, forKey: .textPosition) ?? .left + + try super.init(from: decoder) + baseValue = selected } - public func encode(to encoder: Encoder) throws { + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(id, forKey: .id) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) try container.encodeModelIfPresent(action, forKey: .action) try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction) - try container.encode(moleculeName, forKey: .moleculeName) try container.encode(selected, forKey: .state) try container.encode(animated, forKey: .animated) - try container.encode(enabled, forKey: .enabled) try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText) - try container.encodeIfPresent(fieldKey, forKey: .fieldKey) - try container.encodeIfPresent(groupName, forKey: .groupName) - try container.encode(readOnly, forKey: .readOnly) - - try container.encode(inverted, forKey: .inverted) try container.encode(showText, forKey: .showText) try container.encodeIfPresent(onText, forKey: .onText) try container.encodeIfPresent(offText, forKey: .offText) From ef08aa043e52015908a965924e20e1b726430c46 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 14:14:01 -0500 Subject: [PATCH 22/46] added other properties to encoder :D Signed-off-by: Matt Bruce --- .../Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift index 3ce2773a..05a5ab31 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift @@ -98,5 +98,11 @@ open class DatePickerEntryFieldModel: FormFieldModel { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(selectedDate, forKey: .selectedDate) try container.encode(calendar, forKey: .calendar) + try container.encodeIfPresent(title, forKey: .title) + try container.encodeIfPresent(feedback, forKey: .feedback) + try container.encode(feedbackTextPlacement, forKey: .feedbackTextPlacement) + try container.encodeIfPresent(tooltip, forKey: .tooltip) + try container.encode(transparentBackground, forKey: .transparentBackground) + try container.encodeIfPresent(width, forKey: .width) } } From 458f303972034f7f4d164b7b2d124aa96624e772 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 14:21:17 -0500 Subject: [PATCH 23/46] fixed per comments Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift index 9ffbc20a..e33042a7 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift @@ -10,7 +10,7 @@ import Foundation import MVMCore import VDS -@objcMembers public class CheckboxesModel: MoleculeModelProtocol { +public class CheckboxesModel: MoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift index b1277d08..a71f0837 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift @@ -10,7 +10,7 @@ import Foundation import MVMCore import VDS -@objcMembers public class RadioButtonsModel: FormFieldModel { +public class RadioButtonsModel: FormFieldModel { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -23,7 +23,7 @@ import VDS // MARK: - Form Validation //-------------------------------------------------- - /// Returns the fieldValue of the selected box, otherwise the text of the selected box. + /// Returns the fieldValue of the selected RadioButton. public override func formFieldValue() -> AnyHashable? { guard enabled else { return nil } let selectedBox = radioButtons.first { $0.radioButton.state } From 3d5c18889885eb1d62f48c5d7cf6d3d3778004ff Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 15:16:26 -0500 Subject: [PATCH 24/46] changed comment Signed-off-by: Matt Bruce --- .../Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift index 05a5ab31..648c2db2 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift @@ -57,7 +57,7 @@ open class DatePickerEntryFieldModel: FormFieldModel { // MARK: - Form Validation //-------------------------------------------------- - /// Returns the fieldValue of the selected box, otherwise the text of the selected box. + /// Returns the fieldValue of the selectedDate.. public override func formFieldValue() -> AnyHashable? { guard let selectedDate, enabled else { return nil } return dateFormatter.string(from: selectedDate) From 9185e185fd63dda91a75f18402874fcd737ece1c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 15:17:27 -0500 Subject: [PATCH 25/46] removed duplicate . Signed-off-by: Matt Bruce --- .../Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift index 648c2db2..8cd54f43 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift @@ -57,7 +57,7 @@ open class DatePickerEntryFieldModel: FormFieldModel { // MARK: - Form Validation //-------------------------------------------------- - /// Returns the fieldValue of the selectedDate.. + /// Returns the fieldValue of the selectedDate. public override func formFieldValue() -> AnyHashable? { guard let selectedDate, enabled else { return nil } return dateFormatter.string(from: selectedDate) From 60cefc57a6e4ddc1f8640f8dfbd2074a803294fa Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 15:47:27 -0500 Subject: [PATCH 26/46] pushed word change Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift | 6 +++--- MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift | 6 +++--- MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift b/MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift index 87a755a6..91040f77 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/Checkboxes.swift @@ -46,9 +46,9 @@ open class Checkboxes: VDS.CheckboxGroup, VDSMoleculeViewProtocol { open override func didSelect(_ selectedControl: CheckboxItem) { super.didSelect(selectedControl) - // since the boxes has the state being tracked, we need to update the values here. - if let index = items.firstIndex(where: {$0 === selectedControl}), let selectedBox = checkboxes?[index] { - selectedBox.checkbox.selected = true + // since the checkboxes has the state being tracked, we need to update the values here. + if let index = items.firstIndex(where: {$0 === selectedControl}), let selected = checkboxes?[index] { + selected.checkbox.selected = true } _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift index 683d28b3..bc41f8bb 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtons.swift @@ -44,10 +44,10 @@ open class RadioButtons: VDS.RadioButtonGroup, VDSMoleculeViewProtocol { open override func didSelect(_ selectedControl: RadioButtonItem) { super.didSelect(selectedControl) - // since the boxes has the state being tracked, we need to update the values here. - if let index = items.firstIndex(where: {$0 === selectedControl}), let selectedBox = radioButtons?[index] { + // since the radiobutton has the state being tracked, we need to update the values here. + if let index = items.firstIndex(where: {$0 === selectedControl}), let selected = radioButtons?[index] { radioButtons?.forEach { $0.radioButton.state = false } - selectedBox.radioButton.state = true + selected.radioButton.state = true } _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift index a71f0837..e3a89a21 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift @@ -26,8 +26,8 @@ public class RadioButtonsModel: FormFieldModel { /// Returns the fieldValue of the selected RadioButton. public override func formFieldValue() -> AnyHashable? { guard enabled else { return nil } - let selectedBox = radioButtons.first { $0.radioButton.state } - return selectedBox?.radioButton.formFieldValue() + let selected = radioButtons.first { $0.radioButton.state } + return selected?.radioButton.formFieldValue() } //-------------------------------------------------- From de67fd7fb69e88f91aee74502599ce55554fc905 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 16:07:10 -0500 Subject: [PATCH 27/46] refactored Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift index 8b9282a9..90f12a09 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift @@ -8,7 +8,7 @@ import MVMCore import VDS -@objcMembers public class RadioBoxModel: FormFieldModel { +public class RadioBoxModel: FormFieldModel { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index 9301a932..9ed15051 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -73,7 +73,7 @@ import VDS extension Array where Element == RadioBoxModel { internal func convertToVDSRadioBoxModel(surface: Surface) -> [RadioBoxGroup.RadioBoxItemModel] { - compactMap({ item in + compactMap({ item in var radioBox = RadioBoxGroup.RadioBoxItemModel() radioBox.text = item.text radioBox.subText = item.subText @@ -81,7 +81,7 @@ extension Array where Element == RadioBoxModel { radioBox.surface = surface radioBox.selected = item.selected radioBox.strikethrough = item.strikethrough - radioBox.disabled = !(item.enabled && !item.readOnly) + radioBox.disabled = !item.isEnabled return radioBox }) } From 3b306a299ab73a31d82f4d62b5d04d2c63100d13 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 21 Aug 2024 16:28:14 -0500 Subject: [PATCH 28/46] using enabled now Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift | 2 +- .../HorizontalCombinationViews/RadioButtonLabelModel.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index 9ed15051..c85310b0 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -81,7 +81,7 @@ extension Array where Element == RadioBoxModel { radioBox.surface = surface radioBox.selected = item.selected radioBox.strikethrough = item.strikethrough - radioBox.disabled = !item.isEnabled + radioBox.enabled = item.isEnabled return radioBox }) } diff --git a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift index 0d09a97f..a24febf7 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift @@ -55,7 +55,7 @@ extension Array where Element == CheckboxLabelModel { } item.surface = surface item.selected = model.checkbox.selected - item.disabled = !(model.checkbox.enabled && !model.checkbox.readOnly) + item.enabled = model.checkbox.isEnabled return item }) } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift index 294dd14b..cf48a794 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift @@ -59,7 +59,7 @@ extension Array where Element == RadioButtonLabelModel { } item.surface = surface item.selected = model.radioButton.state - item.disabled = !(model.radioButton.enabled && !model.radioButton.readOnly) + item.enabled = model.radioButton.isEnabled return item }) } From 398bf948116a308ace8f12edc78802a0d872113d Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 11:41:28 -0500 Subject: [PATCH 29/46] removed obj-c compatibility Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index c85310b0..a5a66a5d 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -8,7 +8,7 @@ import MVMCore import VDS -@objcMembers public class RadioBoxesModel: FormFieldModel { +public class RadioBoxesModel: FormFieldModel { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- From b70d2f8addaefce80035793da2ba01b5543c0351 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 13:10:49 -0500 Subject: [PATCH 30/46] added isEqual Signed-off-by: Matt Bruce --- .../Atoms/FormFields/FormFieldModel.swift | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift index 7f43b8bb..7ac83f1d 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift @@ -136,7 +136,39 @@ import VDS try container.encode(required, forKey: .required) try container.encode(inverted, forKey: .inverted) } -} + + open func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard let model = model as? Self else { return false } + return moleculeName == model.moleculeName + && enabled == model.enabled + && showError == model.showError + && errorMessage == model.errorMessage + && readOnly == model.readOnly + && required == model.required + && inverted == model.inverted + && fieldKey == model.fieldKey + && groupName == model.groupName + && accessibilityText == model.accessibilityText + && accessibilityIdentifier == model.accessibilityIdentifier + && accessibilityTraits == model.accessibilityTraits + } + + open func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard let model = model as? Self else { return false } + return moleculeName == model.moleculeName + && enabled == model.enabled + && showError == model.showError + && errorMessage == model.errorMessage + && readOnly == model.readOnly + && required == model.required + && inverted == model.inverted + && fieldKey == model.fieldKey + && groupName == model.groupName + && accessibilityText == model.accessibilityText + && accessibilityIdentifier == model.accessibilityIdentifier + && accessibilityTraits == model.accessibilityTraits + } +} extension FormFieldModel { public var isEnabled: Bool { enabled && !readOnly } From f94ddbf8666a236c2d3b94ea2ef441943410b015 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 13:11:14 -0500 Subject: [PATCH 31/46] added isEqual to Checkbox variations Signed-off-by: Matt Bruce --- .../Atoms/Selectors/CheckboxModel.swift | 14 ++++++++++ .../Atoms/Selectors/CheckboxesModel.swift | 28 +++++++++++++++++++ .../Atoms/Views/CheckboxLabelModel.swift | 24 ++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift index 00554c2e..ed839deb 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift @@ -94,4 +94,18 @@ import VDS try container.encodeModelIfPresent(action, forKey: .action) try container.encodeModelIfPresent(offAction, forKey: .offAction) } + + open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard super.isEqual(to: model), let model = model as? Self else { return false } + return selected == model.selected + && animated == model.animated + && offAction.isEqual(to: model.offAction) + && action.isEqual(to: model.action) + } + + open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } + return selected == model.selected + && animated == model.animated + } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift index e33042a7..b3988944 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift @@ -82,4 +82,32 @@ public class CheckboxesModel: MoleculeModelProtocol { try container.encode(inverted, forKey: .inverted) try container.encode(checkboxes, forKey: .checkboxes) } + + open func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard let model = model as? Self else { return false } + return moleculeName == model.moleculeName + && enabled == model.enabled + && showError == model.showError + && readOnly == model.readOnly + && required == model.required + && inverted == model.inverted + && accessibilityText == model.accessibilityText + && accessibilityIdentifier == model.accessibilityIdentifier + && accessibilityTraits == model.accessibilityTraits + && checkboxes == model.checkboxes + } + + open func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard let model = model as? Self else { return false } + return moleculeName == model.moleculeName + && enabled == model.enabled + && showError == model.showError + && readOnly == model.readOnly + && required == model.required + && inverted == model.inverted + && accessibilityText == model.accessibilityText + && accessibilityIdentifier == model.accessibilityIdentifier + && accessibilityTraits == model.accessibilityTraits + && checkboxes == model.checkboxes + } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift index a24febf7..ffa694cc 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift @@ -36,6 +36,30 @@ import VDS self.label = label self.subTitle = subTitle } + + open func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard let model = model as? Self else { return false } + return moleculeName == model.moleculeName + && inverted == model.inverted + && accessibilityText == model.accessibilityText + && accessibilityIdentifier == model.accessibilityIdentifier + && accessibilityTraits == model.accessibilityTraits + && checkbox == model.checkbox + && label == model.label + && subTitle == model.subTitle + } + + open func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard let model = model as? Self else { return false } + return moleculeName == model.moleculeName + && inverted == model.inverted + && accessibilityText == model.accessibilityText + && accessibilityIdentifier == model.accessibilityIdentifier + && accessibilityTraits == model.accessibilityTraits + && checkbox == model.checkbox + && label == model.label + && subTitle == model.subTitle + } } extension Array where Element == CheckboxLabelModel { From c40dc5e396bb312091c99ad1722a5f31198a274b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 13:11:35 -0500 Subject: [PATCH 32/46] added isEqual to RadioBox variations Signed-off-by: Matt Bruce --- .../Atoms/Selectors/RadioBoxModel.swift | 23 ++++++++++++++++++- .../Atoms/Selectors/RadioBoxesModel.swift | 10 ++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift index 90f12a09..ad7dad7d 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift @@ -31,7 +31,6 @@ public class RadioBoxModel: FormFieldModel { case text case subText case subTextRight - case backgroundColor case selected case strikethrough case action @@ -90,4 +89,26 @@ public class RadioBoxModel: FormFieldModel { try container.encode(strikethrough, forKey: .strikethrough) try container.encodeModelIfPresent(action, forKey: .action) } + + open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard super.isEqual(to: model), let model = model as? Self else { return false } + return text == model.text + && subText == model.subText + && subTextRight == model.subTextRight + && selected == model.selected + && strikethrough == model.strikethrough + && fieldValue == model.fieldValue + && action.isEqual(to: model.action) + } + + open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } + return text == model.text + && subText == model.subText + && subTextRight == model.subTextRight + && selected == model.selected + && strikethrough == model.strikethrough + && fieldValue == model.fieldValue + } } + diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index a5a66a5d..f1bf76f4 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -69,6 +69,16 @@ public class RadioBoxesModel: FormFieldModel { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(boxes, forKey: .boxes) } + + open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard super.isEqual(to: model), let model = model as? Self else { return false } + return boxes == model.boxes + } + + open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } + return boxes == model.boxes + } } extension Array where Element == RadioBoxModel { From 878fd11c8a8dce4f75502cfc96739e12c8f64076 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 13:11:48 -0500 Subject: [PATCH 33/46] added isEqual to RadioButton variations Signed-off-by: Matt Bruce --- .../Atoms/Selectors/RadioButtonModel.swift | 14 +++++++++++ .../Atoms/Selectors/RadioButtonsModel.swift | 10 ++++++++ .../RadioButtonLabelModel.swift | 24 +++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift index 5340b079..1d188923 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift @@ -83,4 +83,18 @@ open class RadioButtonModel: FormFieldModel { try container.encodeIfPresent(fieldValue, forKey: .fieldValue) try container.encodeModelIfPresent(action, forKey: .action) } + + open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard super.isEqual(to: model), let model = model as? Self else { return false } + return state == model.state + && fieldValue == model.fieldValue + && action.isEqual(to: model.action) + } + + open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } + return state == model.state + && fieldValue == model.fieldValue + && action.isEqual(to: model.action) + } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift index e3a89a21..86e9f10c 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift @@ -69,4 +69,14 @@ public class RadioButtonsModel: FormFieldModel { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(radioButtons, forKey: .radioButtons) } + + open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard super.isEqual(to: model), let model = model as? Self else { return false } + return radioButtons == radioButtons + } + + open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } + return radioButtons == radioButtons + } } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift index cf48a794..512c8396 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift @@ -40,6 +40,30 @@ import VDS self.label = label self.subTitle = subTitle } + + open func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard let model = model as? Self else { return false } + return moleculeName == model.moleculeName + && inverted == model.inverted + && accessibilityText == model.accessibilityText + && accessibilityIdentifier == model.accessibilityIdentifier + && accessibilityTraits == model.accessibilityTraits + && radioButton == model.radioButton + && label == model.label + && subTitle == model.subTitle + } + + open func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard let model = model as? Self else { return false } + return moleculeName == model.moleculeName + && inverted == model.inverted + && accessibilityText == model.accessibilityText + && accessibilityIdentifier == model.accessibilityIdentifier + && accessibilityTraits == model.accessibilityTraits + && radioButton == model.radioButton + && label == model.label + && subTitle == model.subTitle + } } extension Array where Element == RadioButtonLabelModel { From db8ba6389249b004abd4c0311c20809eba8acf24 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 13:12:00 -0500 Subject: [PATCH 34/46] added isEqual to Toggle Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Selectors/ToggleModel.swift | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift index 7f937168..c2a4c467 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift @@ -111,4 +111,31 @@ public class ToggleModel: FormFieldModel { try container.encode(textWeight, forKey: .textWeight) try container.encode(textPosition, forKey: .textPosition) } + + open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard super.isEqual(to: model), let model = model as? Self else { return false } + return selected == model.selected + && animated == model.animated + && action.isEqual(to: model.action) + && alternateAction.isEqual(to: model.alternateAction) + && accessibilityText == model.accessibilityText + && showText == model.showText + && onText == model.onText + && offText == model.offText + && textSize == model.textSize + && textWeight == model.textWeight + && textPosition == model.textPosition + } + + open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } + return selected == model.selected + && animated == model.animated + && accessibilityText == model.accessibilityText + && showText == model.showText + && onText == model.onText + && offText == model.offText + && textSize == model.textSize + && textWeight == model.textWeight + && textPosition == model.textPosition } } From 86d49053a6ff2d1f6a4fbcdcacde3c0d6b47f3ed Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 13:12:58 -0500 Subject: [PATCH 35/46] add isEqual to DatePicker Signed-off-by: Matt Bruce --- .../DatePickerEntryFieldModel.swift | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift index 8cd54f43..17d89666 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift @@ -105,4 +105,30 @@ open class DatePickerEntryFieldModel: FormFieldModel { try container.encode(transparentBackground, forKey: .transparentBackground) try container.encodeIfPresent(width, forKey: .width) } + + open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard super.isEqual(to: model), let model = model as? Self else { return false } + return dateFormat == model.dateFormat + && selectedDate == model.selectedDate + && calendar == model.calendar + && title == model.title + && feedback == model.feedback + && feedbackTextPlacement == model.feedbackTextPlacement + && tooltip == model.tooltip + && transparentBackground == model.transparentBackground + && width == model.width + } + + open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } + return dateFormat == model.dateFormat + && selectedDate == model.selectedDate + && calendar == model.calendar + && title == model.title + && feedback == model.feedback + && feedbackTextPlacement == model.feedbackTextPlacement + && tooltip == model.tooltip + && transparentBackground == model.transparentBackground + && width == model.width + } } From 961a0546a8cc6d27b3a5cfdec462adf6637ab389 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 13:19:37 -0500 Subject: [PATCH 36/46] added isEqual to base model Signed-off-by: Matt Bruce --- .../TextFields/EntryFieldModel.swift | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index 1ef00628..82e21f42 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -34,7 +34,6 @@ import Foundation //-------------------------------------------------- private enum CodingKeys: String, CodingKey { - case backgroundColor case title case feedback case errorTextColor @@ -86,7 +85,6 @@ import Foundation required public init(from decoder: Decoder) throws { try super.init(from: decoder) let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) title = try typeContainer.decodeIfPresent(String.self, forKey: .title) feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) errorTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .errorTextColor) @@ -106,7 +104,6 @@ import Foundation open override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(title, forKey: .title) try container.encodeIfPresent(feedback, forKey: .feedback) try container.encodeIfPresent(text, forKey: .text) @@ -116,4 +113,28 @@ import Foundation try container.encode(hideBorders, forKey: .hideBorders) try container.encode(shouldMaskRecordedView, forKey: .shouldMaskRecordedView) } + + open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard super.isEqual(to: model), let model = model as? Self else { return false } + return selected == model.selected + && title == model.title + && feedback == model.feedback + && errorTextColor == model.errorTextColor + && locked == model.locked + && hideBorders == model.hideBorders + && text == model.text + && shouldMaskRecordedView == model.shouldMaskRecordedView + } + + open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } + return selected == model.selected + && title == model.title + && feedback == model.feedback + && errorTextColor == model.errorTextColor + && locked == model.locked + && hideBorders == model.hideBorders + && text == model.text + && shouldMaskRecordedView == model.shouldMaskRecordedView + } } From 2a497082a037e5df83da0f33ae7e80eb0e4b8c61 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 13:19:50 -0500 Subject: [PATCH 37/46] added isEqual to TextEntry Signed-off-by: Matt Bruce --- .../TextFields/TextEntryFieldModel.swift | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryFieldModel.swift index cb40ae9b..6add3203 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryFieldModel.swift @@ -218,4 +218,38 @@ import VDS try container.encode(transparentBackground, forKey: .transparentBackground) try container.encodeIfPresent(width, forKey: .width) } + + open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard super.isEqual(to: model), let model = model as? Self else { return false } + return placeholder == model.placeholder + && textAlignment == model.textAlignment + && enabledTextColor == model.enabledTextColor + && disabledTextColor == model.disabledTextColor + && keyboardOverride == model.keyboardOverride + && type == model.type + && clearTextOnTap == model.clearTextOnTap + && displayFormat == model.displayFormat + && displayMask == model.displayMask + && enableClipboardActions == model.enableClipboardActions + && tooltip == model.tooltip + && transparentBackground == model.transparentBackground + && width == model.width + } + + open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } + return placeholder == model.placeholder + && textAlignment == model.textAlignment + && enabledTextColor == model.enabledTextColor + && disabledTextColor == model.disabledTextColor + && keyboardOverride == model.keyboardOverride + && type == model.type + && clearTextOnTap == model.clearTextOnTap + && displayFormat == model.displayFormat + && displayMask == model.displayMask + && enableClipboardActions == model.enableClipboardActions + && tooltip == model.tooltip + && transparentBackground == model.transparentBackground + && width == model.width + } } From 68a72f6b2e32f18d303901d607008baaa5ddf3dd Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 13:20:10 -0500 Subject: [PATCH 38/46] added isEqual to ItemDropDown Signed-off-by: Matt Bruce --- .../ItemDropdownEntryFieldModel.swift | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Item Dropdown/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Item Dropdown/ItemDropdownEntryFieldModel.swift index 04d880ae..878b6023 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Item Dropdown/ItemDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Item Dropdown/ItemDropdownEntryFieldModel.swift @@ -78,4 +78,21 @@ import VDS try container.encode(feedbackTextPlacement, forKey: .feedbackTextPlacement) try container.encodeModelIfPresent(action, forKey: .action) } + + open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard super.isEqual(to: model), let model = model as? Self else { return false } + return options == model.options + && selectedIndex == model.selectedIndex + && showInlineLabel == model.showInlineLabel + && feedbackTextPlacement == model.feedbackTextPlacement + && action.isEqual(to: model.action) + } + + open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } + return options == model.options + && selectedIndex == model.selectedIndex + && showInlineLabel == model.showInlineLabel + && feedbackTextPlacement == model.feedbackTextPlacement + } } From f9915dfaccc3fff8eeae918a2262b69f6b5ca4e8 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 13:20:22 -0500 Subject: [PATCH 39/46] update func Signed-off-by: Matt Bruce --- MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift index c2a4c467..4cb478f6 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift @@ -137,5 +137,6 @@ public class ToggleModel: FormFieldModel { && offText == model.offText && textSize == model.textSize && textWeight == model.textWeight - && textPosition == model.textPosition } + && textPosition == model.textPosition + } } From e211d4dc2260b7b669c2a50beefb911b0daf25cc Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 13:21:52 -0500 Subject: [PATCH 40/46] added isEqual to TextViewEntryFieldModel Signed-off-by: Matt Bruce --- .../TextFields/TextViewEntryFieldModel.swift | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryFieldModel.swift index 2f47b2a6..95005a6c 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryFieldModel.swift @@ -21,7 +21,7 @@ public class TextViewEntryFieldModel: TextEntryFieldModel { public var showsPlaceholder: Bool = false public var minHeight: VDS.TextArea.Height = .twoX public var maxLength: Int? - + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- @@ -55,4 +55,21 @@ public class TextViewEntryFieldModel: TextEntryFieldModel { try container.encode(minHeight, forKey: .minHeight) try container.encodeIfPresent(maxLength, forKey: .maxLength) } + + open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard super.isEqual(to: model), let model = model as? Self else { return false } + return accessibilityText == model.accessibilityText + && editable == model.editable + && minHeight == model.minHeight + && maxLength == model.maxLength + } + + open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } + return accessibilityText == model.accessibilityText + && editable == model.editable + && minHeight == model.minHeight + && maxLength == model.maxLength + } + } From 533bcd2dea378885ef951d05b5ea5f33a8370a0e Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 13:30:13 -0500 Subject: [PATCH 41/46] added isEqual to CalendarView Signed-off-by: Matt Bruce --- .../Atoms/Views/CalendarViewModel.swift | 36 +++++++++++++++++++ .../Atomic/Extensions/VDS-Enums+Codable.swift | 15 +++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift index 16e9b425..0e888659 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift @@ -113,6 +113,42 @@ open class CalendarViewModel: MoleculeModelProtocol { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(id, forKey: .id) try container.encode(inverted, forKey: .inverted) + try container.encode(dateFormat, forKey: .dateFormat) + try container.encode(hideContainerBorder, forKey: .hideContainerBorder) + try container.encode(hideCurrentDateIndicator, forKey: .hideCurrentDateIndicator) + try container.encode(activeDates, forKey: .activeDates) + try container.encode(selectedDate, forKey: .selectedDate) + try container.encode(minDate, forKey: .minDate) + try container.encode(maxDate, forKey: .maxDate) + try container.encode(indicators, forKey: .indicators) + } + + open func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard let model = model as? Self else { return false } + return inverted == model.inverted + && dateFormat == model.dateFormat + && hideContainerBorder == model.hideContainerBorder + && hideCurrentDateIndicator == model.hideCurrentDateIndicator + && activeDates == model.activeDates + && inactiveDates == model.inactiveDates + && selectedDate == model.selectedDate + && minDate == model.minDate + && maxDate == model.maxDate + && indicators == model.indicators + } + + open func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard let model = model as? Self else { return false } + return inverted == model.inverted + && dateFormat == model.dateFormat + && hideContainerBorder == model.hideContainerBorder + && hideCurrentDateIndicator == model.hideCurrentDateIndicator + && activeDates == model.activeDates + && inactiveDates == model.inactiveDates + && selectedDate == model.selectedDate + && minDate == model.minDate + && maxDate == model.maxDate + && indicators == model.indicators } } diff --git a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift index fa95360e..6c6ae71f 100644 --- a/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift +++ b/MVMCoreUI/Atomic/Extensions/VDS-Enums+Codable.swift @@ -9,6 +9,7 @@ import Foundation import VDS import VDSCoreTokens +import MVMCore //-------------------------------------------------- // MARK: - Codable Extensions @@ -57,7 +58,7 @@ extension VDS.Button.Size: RawRepresentableCodable { public static var defaultValue: VDS.Button.Size? { nil } } -extension VDS.CalendarBase.CalendarIndicatorModel: Codable { +extension VDS.CalendarBase.CalendarIndicatorModel: Codable, ModelComparisonProtocol, MoleculeModelComparisonProtocol { enum CodingKeys: String, CodingKey { case label @@ -89,6 +90,18 @@ extension VDS.CalendarBase.CalendarIndicatorModel: Codable { formatter.formatterBehavior = .default return formatter } + + public func isEqual(to model: any ModelComparisonProtocol) -> Bool { + guard let model = model as? Self else { return false } + return label == model.label + && date == model.date + } + + public func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { + guard let model = model as? Self else { return false } + return label == model.label + && date == model.date + } } //-------------------------------------------------- From df1846c2954fa953ac6135d84664efb519e17796 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 14:09:48 -0500 Subject: [PATCH 42/46] added parentMoleculeModelProtocol Signed-off-by: Matt Bruce --- .../Atomic/Atoms/Selectors/CheckboxesModel.swift | 5 ++++- .../Atomic/Atoms/Selectors/RadioBoxesModel.swift | 10 ++++------ .../Atomic/Atoms/Selectors/RadioButtonsModel.swift | 11 ++++------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift index b3988944..2eca2503 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift @@ -10,7 +10,8 @@ import Foundation import MVMCore import VDS -public class CheckboxesModel: MoleculeModelProtocol { +public class CheckboxesModel: MoleculeModelProtocol, ParentMoleculeModelProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -30,6 +31,8 @@ public class CheckboxesModel: MoleculeModelProtocol { public var checkboxes: [CheckboxLabelModel] + public var children: [any MoleculeModelProtocol] { checkboxes } + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index f1bf76f4..e2eac3c2 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -8,7 +8,8 @@ import MVMCore import VDS -public class RadioBoxesModel: FormFieldModel { +public class RadioBoxesModel: FormFieldModel, ParentMoleculeModelProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -17,6 +18,8 @@ public class RadioBoxesModel: FormFieldModel { public var boxes: [RadioBoxModel] + public var children: [any MoleculeModelProtocol] { boxes } + //-------------------------------------------------- // MARK: - Form Validation //-------------------------------------------------- @@ -74,11 +77,6 @@ public class RadioBoxesModel: FormFieldModel { guard super.isEqual(to: model), let model = model as? Self else { return false } return boxes == model.boxes } - - open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } - return boxes == model.boxes - } } extension Array where Element == RadioBoxModel { diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift index 86e9f10c..36438e31 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift @@ -10,7 +10,7 @@ import Foundation import MVMCore import VDS -public class RadioButtonsModel: FormFieldModel { +public class RadioButtonsModel: FormFieldModel, ParentMoleculeModelProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -19,6 +19,8 @@ public class RadioButtonsModel: FormFieldModel { public var radioButtons: [RadioButtonLabelModel] + public var children: [any MoleculeModelProtocol] { radioButtons } + //-------------------------------------------------- // MARK: - Form Validation //-------------------------------------------------- @@ -72,11 +74,6 @@ public class RadioButtonsModel: FormFieldModel { open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { guard super.isEqual(to: model), let model = model as? Self else { return false } - return radioButtons == radioButtons - } - - open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } - return radioButtons == radioButtons + return radioButtons == model.radioButtons } } From 62c1aa6a8a507e6aa4ead2838ce21b0057fa43aa Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 14:10:26 -0500 Subject: [PATCH 43/46] removed isVisuallyEqual since this was the same as isEqual Signed-off-by: Matt Bruce --- .../FormFields/DatePickerEntryFieldModel.swift | 13 ------------- .../Atomic/Atoms/FormFields/FormFieldModel.swift | 16 ---------------- .../FormFields/TextFields/EntryFieldModel.swift | 12 ------------ .../Atomic/Atoms/Selectors/CheckboxModel.swift | 6 ------ .../Atomic/Atoms/Selectors/RadioBoxModel.swift | 10 ---------- .../Atoms/Selectors/RadioButtonModel.swift | 7 ------- .../Atomic/Atoms/Selectors/ToggleModel.swift | 13 ------------- 7 files changed, 77 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift index 17d89666..f7f84b07 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/DatePickerEntryFieldModel.swift @@ -118,17 +118,4 @@ open class DatePickerEntryFieldModel: FormFieldModel { && transparentBackground == model.transparentBackground && width == model.width } - - open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } - return dateFormat == model.dateFormat - && selectedDate == model.selectedDate - && calendar == model.calendar - && title == model.title - && feedback == model.feedback - && feedbackTextPlacement == model.feedbackTextPlacement - && tooltip == model.tooltip - && transparentBackground == model.transparentBackground - && width == model.width - } } diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift index 7ac83f1d..9f5c0415 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/FormFieldModel.swift @@ -152,22 +152,6 @@ import VDS && accessibilityIdentifier == model.accessibilityIdentifier && accessibilityTraits == model.accessibilityTraits } - - open func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard let model = model as? Self else { return false } - return moleculeName == model.moleculeName - && enabled == model.enabled - && showError == model.showError - && errorMessage == model.errorMessage - && readOnly == model.readOnly - && required == model.required - && inverted == model.inverted - && fieldKey == model.fieldKey - && groupName == model.groupName - && accessibilityText == model.accessibilityText - && accessibilityIdentifier == model.accessibilityIdentifier - && accessibilityTraits == model.accessibilityTraits - } } extension FormFieldModel { diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index 82e21f42..4ddb9a35 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -125,16 +125,4 @@ import Foundation && text == model.text && shouldMaskRecordedView == model.shouldMaskRecordedView } - - open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } - return selected == model.selected - && title == model.title - && feedback == model.feedback - && errorTextColor == model.errorTextColor - && locked == model.locked - && hideBorders == model.hideBorders - && text == model.text - && shouldMaskRecordedView == model.shouldMaskRecordedView - } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift index ed839deb..4ae2c89e 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxModel.swift @@ -102,10 +102,4 @@ import VDS && offAction.isEqual(to: model.offAction) && action.isEqual(to: model.action) } - - open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } - return selected == model.selected - && animated == model.animated - } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift index ad7dad7d..5095a6ab 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxModel.swift @@ -100,15 +100,5 @@ public class RadioBoxModel: FormFieldModel { && fieldValue == model.fieldValue && action.isEqual(to: model.action) } - - open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } - return text == model.text - && subText == model.subText - && subTextRight == model.subTextRight - && selected == model.selected - && strikethrough == model.strikethrough - && fieldValue == model.fieldValue - } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift index 1d188923..63c1ff24 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonModel.swift @@ -90,11 +90,4 @@ open class RadioButtonModel: FormFieldModel { && fieldValue == model.fieldValue && action.isEqual(to: model.action) } - - open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } - return state == model.state - && fieldValue == model.fieldValue - && action.isEqual(to: model.action) - } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift index 4cb478f6..1b3e79a0 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/ToggleModel.swift @@ -126,17 +126,4 @@ public class ToggleModel: FormFieldModel { && textWeight == model.textWeight && textPosition == model.textPosition } - - open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } - return selected == model.selected - && animated == model.animated - && accessibilityText == model.accessibilityText - && showText == model.showText - && onText == model.onText - && offText == model.offText - && textSize == model.textSize - && textWeight == model.textWeight - && textPosition == model.textPosition - } } From 59e762f52eab109de327860c4ab904e8b599420e Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 14:10:44 -0500 Subject: [PATCH 44/46] added == and != for equality Signed-off-by: Matt Bruce --- .../MoleculeComparisonProtocol.swift | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeComparisonProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeComparisonProtocol.swift index 97014092..5628faba 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeComparisonProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/MoleculeComparisonProtocol.swift @@ -70,3 +70,43 @@ public extension Optional where Wrapped: Collection { return self.isVisuallyEquivalent(to: models) } } + +func == (lhs: (any MoleculeModelComparisonProtocol)?, rhs: (any MoleculeModelComparisonProtocol)?) -> Bool { + switch (lhs, rhs) { + case (.some(let lhs), .some(let rhs)): + return lhs.isEqual(to: rhs) + case (.none, .none): + return true + default: + return false + } +} + +func != (lhs: (any MoleculeModelComparisonProtocol)?, rhs: (any MoleculeModelComparisonProtocol)?) -> Bool { + return !(lhs == rhs) +} + +func == (lhs: [any MoleculeModelComparisonProtocol]?, rhs: [any MoleculeModelComparisonProtocol]?) -> Bool { + switch (lhs, rhs) { + case (.some(let lhs), .some(let rhs)): + return lhs == rhs + case (.none, .none): + return true + default: + return false + } +} + +func != (lhs: [any MoleculeModelComparisonProtocol]?, rhs: [any MoleculeModelComparisonProtocol]?) -> Bool { + return !(lhs == rhs) +} + +func == (lhs: [any MoleculeModelComparisonProtocol], rhs: [any MoleculeModelComparisonProtocol]) -> Bool { + return lhs.elementsEqual(rhs, by: { (lhsElement, rhsElement) -> Bool in + return lhsElement == rhsElement + }) +} + +func != (lhs: [any MoleculeModelComparisonProtocol], rhs: [any MoleculeModelComparisonProtocol]) -> Bool { + return !(lhs == rhs) +} From 9bbf3256401faec9c316c05861f6265ccd5a8460 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 14:11:14 -0500 Subject: [PATCH 45/46] removed since this is not needed. Signed-off-by: Matt Bruce --- .../TextFields/TextEntryFieldModel.swift | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryFieldModel.swift index 6add3203..7cbad244 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextEntryFieldModel.swift @@ -235,21 +235,4 @@ import VDS && transparentBackground == model.transparentBackground && width == model.width } - - open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } - return placeholder == model.placeholder - && textAlignment == model.textAlignment - && enabledTextColor == model.enabledTextColor - && disabledTextColor == model.disabledTextColor - && keyboardOverride == model.keyboardOverride - && type == model.type - && clearTextOnTap == model.clearTextOnTap - && displayFormat == model.displayFormat - && displayMask == model.displayMask - && enableClipboardActions == model.enableClipboardActions - && tooltip == model.tooltip - && transparentBackground == model.transparentBackground - && width == model.width - } } From 8670fa31939e8d6c8df8eed68f3dd2bfbac90a52 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Thu, 22 Aug 2024 14:25:48 -0500 Subject: [PATCH 46/46] removed visualEquivalent Signed-off-by: Matt Bruce --- .../ItemDropdownEntryFieldModel.swift | 8 -------- .../TextFields/TextViewEntryFieldModel.swift | 8 -------- .../Atomic/Atoms/Selectors/CheckboxesModel.swift | 15 --------------- .../Atomic/Atoms/Selectors/RadioBoxesModel.swift | 5 ----- .../Atoms/Selectors/RadioButtonsModel.swift | 5 ----- .../Atomic/Atoms/Views/CalendarViewModel.swift | 14 -------------- .../Atomic/Atoms/Views/CheckboxLabelModel.swift | 15 --------------- .../RadioButtonLabelModel.swift | 15 --------------- 8 files changed, 85 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Item Dropdown/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Item Dropdown/ItemDropdownEntryFieldModel.swift index 878b6023..33512fc8 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Item Dropdown/ItemDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/Dropdown Fields/Item Dropdown/ItemDropdownEntryFieldModel.swift @@ -87,12 +87,4 @@ import VDS && feedbackTextPlacement == model.feedbackTextPlacement && action.isEqual(to: model.action) } - - open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } - return options == model.options - && selectedIndex == model.selectedIndex - && showInlineLabel == model.showInlineLabel - && feedbackTextPlacement == model.feedbackTextPlacement - } } diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryFieldModel.swift index 95005a6c..d123e7f8 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/TextViewEntryFieldModel.swift @@ -63,13 +63,5 @@ public class TextViewEntryFieldModel: TextEntryFieldModel { && minHeight == model.minHeight && maxLength == model.maxLength } - - open override func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard super.isVisuallyEquivalent(to: model), let model = model as? Self else { return false } - return accessibilityText == model.accessibilityText - && editable == model.editable - && minHeight == model.minHeight - && maxLength == model.maxLength - } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift index 2eca2503..08e9c030 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/CheckboxesModel.swift @@ -97,20 +97,5 @@ public class CheckboxesModel: MoleculeModelProtocol, ParentMoleculeModelProtocol && accessibilityText == model.accessibilityText && accessibilityIdentifier == model.accessibilityIdentifier && accessibilityTraits == model.accessibilityTraits - && checkboxes == model.checkboxes - } - - open func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard let model = model as? Self else { return false } - return moleculeName == model.moleculeName - && enabled == model.enabled - && showError == model.showError - && readOnly == model.readOnly - && required == model.required - && inverted == model.inverted - && accessibilityText == model.accessibilityText - && accessibilityIdentifier == model.accessibilityIdentifier - && accessibilityTraits == model.accessibilityTraits - && checkboxes == model.checkboxes } } diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift index e2eac3c2..310ccc54 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioBoxesModel.swift @@ -72,11 +72,6 @@ public class RadioBoxesModel: FormFieldModel, ParentMoleculeModelProtocol { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(boxes, forKey: .boxes) } - - open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { - guard super.isEqual(to: model), let model = model as? Self else { return false } - return boxes == model.boxes - } } extension Array where Element == RadioBoxModel { diff --git a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift index 36438e31..b5de4a9a 100644 --- a/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Selectors/RadioButtonsModel.swift @@ -71,9 +71,4 @@ public class RadioButtonsModel: FormFieldModel, ParentMoleculeModelProtocol { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(radioButtons, forKey: .radioButtons) } - - open override func isEqual(to model: any ModelComparisonProtocol) -> Bool { - guard super.isEqual(to: model), let model = model as? Self else { return false } - return radioButtons == model.radioButtons - } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift index 0e888659..3abb4cc5 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CalendarViewModel.swift @@ -136,20 +136,6 @@ open class CalendarViewModel: MoleculeModelProtocol { && maxDate == model.maxDate && indicators == model.indicators } - - open func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard let model = model as? Self else { return false } - return inverted == model.inverted - && dateFormat == model.dateFormat - && hideContainerBorder == model.hideContainerBorder - && hideCurrentDateIndicator == model.hideCurrentDateIndicator - && activeDates == model.activeDates - && inactiveDates == model.inactiveDates - && selectedDate == model.selectedDate - && minDate == model.minDate - && maxDate == model.maxDate - && indicators == model.indicators - } } extension CalendarViewModel { diff --git a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift index ffa694cc..fde30ae6 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CheckboxLabelModel.swift @@ -44,21 +44,6 @@ import VDS && accessibilityText == model.accessibilityText && accessibilityIdentifier == model.accessibilityIdentifier && accessibilityTraits == model.accessibilityTraits - && checkbox == model.checkbox - && label == model.label - && subTitle == model.subTitle - } - - open func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard let model = model as? Self else { return false } - return moleculeName == model.moleculeName - && inverted == model.inverted - && accessibilityText == model.accessibilityText - && accessibilityIdentifier == model.accessibilityIdentifier - && accessibilityTraits == model.accessibilityTraits - && checkbox == model.checkbox - && label == model.label - && subTitle == model.subTitle } } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift index 512c8396..a5863694 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/RadioButtonLabelModel.swift @@ -48,21 +48,6 @@ import VDS && accessibilityText == model.accessibilityText && accessibilityIdentifier == model.accessibilityIdentifier && accessibilityTraits == model.accessibilityTraits - && radioButton == model.radioButton - && label == model.label - && subTitle == model.subTitle - } - - open func isVisuallyEquivalent(to model: any MoleculeModelComparisonProtocol) -> Bool { - guard let model = model as? Self else { return false } - return moleculeName == model.moleculeName - && inverted == model.inverted - && accessibilityText == model.accessibilityText - && accessibilityIdentifier == model.accessibilityIdentifier - && accessibilityTraits == model.accessibilityTraits - && radioButton == model.radioButton - && label == model.label - && subTitle == model.subTitle } }