From 26a530af2c8f29ab31cfa894849259c8b9053aaa Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Tue, 24 Mar 2020 17:20:19 -0400 Subject: [PATCH] Form Cleaning --- MVMCoreUI.xcodeproj/project.pbxproj | 26 ++-- .../Atomic/Atoms/Buttons/ButtonModel.swift | 10 +- .../Atomic/Atoms/Buttons/PillButton.swift | 6 +- .../Atomic/Atoms/Buttons/RadioButton.swift | 4 +- .../Atoms/Buttons/RadioButtonModel.swift | 17 ++- .../Buttons/RadioButtonSelectionHelper.swift | 4 +- .../Atoms/TextFields/EntryFieldModel.swift | 28 ++-- .../Atoms/TextFields/TextEntryField.swift | 12 +- MVMCoreUI/Atomic/Atoms/Views/Checkbox.swift | 4 +- .../Atomic/Atoms/Views/CheckboxModel.swift | 20 +-- MVMCoreUI/Atomic/Atoms/Views/Toggle.swift | 4 +- .../Atomic/Atoms/Views/ToggleModel.swift | 26 ++-- .../BaseControllers/ViewController.swift | 6 +- .../FormActionFieldProtocol.swift | 14 -- .../FormUIHelpers/FormFieldProtocol.swift | 6 + .../FormGroupWatcherFieldProtocol.swift | 14 ++ .../FormHolderModelProtocol.swift | 2 +- .../FormUIHelpers/FormItemProtocol.swift | 10 +- .../FormRuleWatcherFieldProtocol.swift | 14 ++ MVMCoreUI/FormUIHelpers/FormValidator.swift | 139 ++++++++++-------- .../Rules/Rules/FormGroupRule.swift | 1 + .../Rules/Rules/RulesProtocol.swift | 30 +--- MVMCoreUI/FormUIHelpers/ValidProtocol.swift | 15 -- .../Controllers/MFViewController+Form.swift | 22 --- .../Controllers/MFViewController+Model.swift | 40 ----- .../Legacy/Controllers/MFViewController.m | 5 - 26 files changed, 214 insertions(+), 265 deletions(-) delete mode 100644 MVMCoreUI/FormUIHelpers/FormActionFieldProtocol.swift create mode 100644 MVMCoreUI/FormUIHelpers/FormGroupWatcherFieldProtocol.swift create mode 100644 MVMCoreUI/FormUIHelpers/FormRuleWatcherFieldProtocol.swift delete mode 100644 MVMCoreUI/FormUIHelpers/ValidProtocol.swift delete mode 100644 MVMCoreUI/Legacy/Controllers/MFViewController+Form.swift delete mode 100644 MVMCoreUI/Legacy/Controllers/MFViewController+Model.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 03335a4d..27346789 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -22,13 +22,12 @@ 011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95A0240453D0000E3791 /* RuleEqualsModel.swift */; }; 011D95A3240453F8000E3791 /* RuleRegexModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95A2240453F8000E3791 /* RuleRegexModel.swift */; }; 011D95A5240455DC000E3791 /* FormGroupRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95A4240455DC000E3791 /* FormGroupRule.swift */; }; - 011D95A924057AC7000E3791 /* FormActionFieldProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95A824057AC7000E3791 /* FormActionFieldProtocol.swift */; }; + 011D95A924057AC7000E3791 /* FormGroupWatcherFieldProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95A824057AC7000E3791 /* FormGroupWatcherFieldProtocol.swift */; }; 011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95AA2405C553000E3791 /* FormItemProtocol.swift */; }; 011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */; }; 011D95AF2407266E000E3791 /* RadioButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95AE2407266E000E3791 /* RadioButtonModel.swift */; }; - 011D9602240DA20A000E3791 /* ValidProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D9601240DA20A000E3791 /* ValidProtocol.swift */; }; + 011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D9601240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift */; }; 011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */; }; - 011D9628240EFA1E000E3791 /* MFViewController+Form.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D9627240EFA1E000E3791 /* MFViewController+Form.swift */; }; 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */; }; 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */; }; 012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88B0238C880100FE3DA1 /* CarouselPagingModelProtocol.swift */; }; @@ -52,7 +51,6 @@ 01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D922327ECFB00EF99AA /* ProgressBar.swift */; }; 01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D942327ED1900EF99AA /* HeadlineBodyLinkToggle.swift */; }; 017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */; }; - 017BEB3C2361EA1D0024EF95 /* MFViewController+Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */; }; 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */; }; 017BEB7B236763000024EF95 /* LineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB7A236763000024EF95 /* LineModel.swift */; }; 017BEB7F23676E870024EF95 /* MoleculeObjectMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB7E23676E870024EF95 /* MoleculeObjectMapping.swift */; }; @@ -415,13 +413,12 @@ 011D95A0240453D0000E3791 /* RuleEqualsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleEqualsModel.swift; sourceTree = ""; }; 011D95A2240453F8000E3791 /* RuleRegexModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleRegexModel.swift; sourceTree = ""; }; 011D95A4240455DC000E3791 /* FormGroupRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormGroupRule.swift; sourceTree = ""; }; - 011D95A824057AC7000E3791 /* FormActionFieldProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormActionFieldProtocol.swift; sourceTree = ""; }; + 011D95A824057AC7000E3791 /* FormGroupWatcherFieldProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormGroupWatcherFieldProtocol.swift; sourceTree = ""; }; 011D95AA2405C553000E3791 /* FormItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormItemProtocol.swift; sourceTree = ""; }; 011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormHolderProtocol.swift; sourceTree = ""; }; 011D95AE2407266E000E3791 /* RadioButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonModel.swift; sourceTree = ""; }; - 011D9601240DA20A000E3791 /* ValidProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidProtocol.swift; sourceTree = ""; }; + 011D9601240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormRuleWatcherFieldProtocol.swift; sourceTree = ""; }; 011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonLabelModel.swift; sourceTree = ""; }; - 011D9627240EFA1E000E3791 /* MFViewController+Form.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFViewController+Form.swift"; sourceTree = ""; }; 012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModelProtocol.swift; sourceTree = ""; }; 012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateProtocol.swift; sourceTree = ""; }; 012A88AE238C626E00FE3DA1 /* CarouselModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselModel.swift; sourceTree = ""; }; @@ -445,7 +442,6 @@ 01509D922327ECFB00EF99AA /* ProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = ""; }; 01509D942327ED1900EF99AA /* HeadlineBodyLinkToggle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlineBodyLinkToggle.swift; sourceTree = ""; }; 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonLabel.swift; sourceTree = ""; }; - 017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFViewController+Model.swift"; sourceTree = ""; }; 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeViewProtocol.swift; sourceTree = ""; }; 017BEB7A236763000024EF95 /* LineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineModel.swift; sourceTree = ""; }; 017BEB7E23676E870024EF95 /* MoleculeObjectMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeObjectMapping.swift; sourceTree = ""; }; @@ -827,13 +823,13 @@ 011D958A24042794000E3791 /* Rules */ = { isa = PBXGroup; children = ( + 011D95A4240455DC000E3791 /* FormGroupRule.swift */, 011D958424042432000E3791 /* RulesProtocol.swift */, 011D959A240451E3000E3791 /* RuleRequiredModel.swift */, 011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */, 011D959E240453A1000E3791 /* RuleAllValueChangedModel.swift */, 011D95A0240453D0000E3791 /* RuleEqualsModel.swift */, 011D95A2240453F8000E3791 /* RuleRegexModel.swift */, - 011D95A4240455DC000E3791 /* FormGroupRule.swift */, 0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */, ); name = Rules; @@ -855,8 +851,8 @@ 011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */, 011D95AA2405C553000E3791 /* FormItemProtocol.swift */, 011D958624042492000E3791 /* FormFieldProtocol.swift */, - 011D95A824057AC7000E3791 /* FormActionFieldProtocol.swift */, - 011D9601240DA20A000E3791 /* ValidProtocol.swift */, + 011D95A824057AC7000E3791 /* FormGroupWatcherFieldProtocol.swift */, + 011D9601240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift */, 0105618A224BBE7700E1557D /* FormValidator.swift */, 011D958A24042794000E3791 /* Rules */, ); @@ -1015,8 +1011,6 @@ children = ( D29DF16021E69996003B2FB9 /* MFViewController.h */, D29DF15F21E69996003B2FB9 /* MFViewController.m */, - 017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */, - 011D9627240EFA1E000E3791 /* MFViewController+Form.swift */, D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */, D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */, D29DF29121E7ADB8003B2FB9 /* MFProgrammaticScrollViewController.h */, @@ -1908,12 +1902,11 @@ D2E2A99423D8CCBC000B42E6 /* HeadlineBodyLinkModel.swift in Sources */, 01004F3022721C3800991ECC /* RadioButton.swift in Sources */, D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */, - 017BEB3C2361EA1D0024EF95 /* MFViewController+Model.swift in Sources */, D236E5B7242007C500C38625 /* MVMControllerModelProtocol.swift in Sources */, D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, D2B18B7F2360913400A9AEDC /* Control.swift in Sources */, - 011D95A924057AC7000E3791 /* FormActionFieldProtocol.swift in Sources */, + 011D95A924057AC7000E3791 /* FormGroupWatcherFieldProtocol.swift in Sources */, D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */, 0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */, D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */, @@ -1935,7 +1928,7 @@ 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, BB6C6AC1242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTall.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, - 011D9602240DA20A000E3791 /* ValidProtocol.swift in Sources */, + 011D9602240DA20A000E3791 /* FormRuleWatcherFieldProtocol.swift in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */, D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */, @@ -2122,7 +2115,6 @@ 94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */, D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */, D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */, - 011D9628240EFA1E000E3791 /* MFViewController+Form.swift in Sources */, 0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */, 52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */, D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift index ac9d1dc1..02244a69 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/ButtonModel.swift @@ -18,8 +18,7 @@ public enum ButtonSize: String, Codable { case tiny } -public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormActionFieldProtocol { - +public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupWatcherFieldProtocol { public static var identifier: String = "button" public var backgroundColor: Color? public var title: String @@ -33,13 +32,14 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormAction public var disabledFillColor: Color? public var disabledTextColor: Color? public var disabledBorderColor: Color? - public var groupName: String? = FormValidator.defaultGroupName + public var groupName: String = FormValidator.defaultGroupName - public func updateEnable(_ enabled: Bool) { - self.enabled = enabled + public func setValidity(_ valid: Bool, group: FormGroupRule) { + enabled = valid updateUI?() } + /// Temporary binding mechanism for the view to update on enable changes. public var updateUI: (() -> Void)? init(with title: String, action: ActionModelProtocol) { diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift index e3f99862..19f032fc 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/PillButton.swift @@ -127,10 +127,12 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { setTitle(model.title, for: .normal) model.updateUI = { [weak self] in - self?.enableField(model.enabled) + MVMCoreDispatchUtility.performBlock(onMainThread: { + self?.enableField(model.enabled) + }) } - FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate) + FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButton.swift index 7dd5976a..56466020 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButton.swift @@ -81,7 +81,7 @@ import UIKit } else { isSelected = !isSelected } - FormValidator.validate(delegate: delegateObject?.formHolderDelegate) + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) setNeedsDisplay() } @@ -130,7 +130,7 @@ import UIKit isSelected = model.state let radioButtonModel = RadioButtonSelectionHelper.setupForRadioButtonGroup(model, formValidator: delegateObject?.formHolderDelegate?.formValidator) - FormValidator.setupValidation(molecule: radioButtonModel, delegate: delegateObject?.formHolderDelegate) + FormValidator.setupValidation(for: radioButtonModel, delegate: delegateObject?.formHolderDelegate) } public override func reset() { diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonModel.swift index 581e03f8..579c0ed9 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonModel.swift @@ -20,11 +20,13 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { public var state: Bool = false public var enabled: Bool = true - public var baseValue: AnyHashable? - public var groupName: String? - public var fieldKey: String? + /// The specific value to send to server. TODO: update this to be more generic. public var fieldValue: String? + public var baseValue: AnyHashable? + public var groupName: String = FormValidator.defaultGroupName + public var fieldKey: String? + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- @@ -34,8 +36,8 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { case backgroundColor case state case enabled - case fieldKey case fieldValue + case fieldKey case groupName } @@ -45,6 +47,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { public init(_ state: Bool) { self.state = state + baseValue = state } //-------------------------------------------------- @@ -71,8 +74,12 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { } backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + + baseValue = state fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) - groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { + self.groupName = groupName + } fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonSelectionHelper.swift b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonSelectionHelper.swift index 263a85a4..a613695a 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonSelectionHelper.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonSelectionHelper.swift @@ -10,10 +10,8 @@ import Foundation import UIKit @objcMembers public class RadioButtonSelectionHelper: FormFieldProtocol { - - public var fieldKey: String? - public var groupName: String? = FormValidator.defaultGroupName + public var groupName: String = FormValidator.defaultGroupName private var selectedRadioButton: RadioButton? private var fieldGroupName: String? public var baseValue: AnyHashable? diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift index 54b441f7..729b3516 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/EntryFieldModel.swift @@ -9,7 +9,7 @@ import Foundation -@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, ValidProtocol { +@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, FormRuleWatcherFieldProtocol { //-------------------------------------------------- // MARK: - Properties @@ -26,9 +26,10 @@ import Foundation public var isEnabled: Bool = true public var isLocked: Bool? public var isSelected: Bool? - public var fieldKey: String? - public var groupName: String? = FormValidator.defaultGroupName public var text: String? + + public var fieldKey: String? + public var groupName: String = FormValidator.defaultGroupName public var baseValue: AnyHashable? public var isValid: Bool? { @@ -36,9 +37,12 @@ import Foundation updateUI?() } } + + /// Temporary binding mechanism for the view to update on enable changes. public var updateUI: (() -> Void)? - public func setValidity(_ isValid: Bool) { - self.isValid = isValid + + public func setValidity(_ valid: Bool, rule: RulesProtocol) { + self.isValid = valid } //-------------------------------------------------- @@ -54,10 +58,10 @@ import Foundation case errorMessage = "errorMsg" case isLocked case isSelected - case fieldKey case isValid case isRequired = "required" case text + case fieldKey case groupName } @@ -69,6 +73,11 @@ import Foundation // MARK: - Initializers //-------------------------------------------------- + public init(with text: String) { + self.text = text + baseValue = text + } + required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) @@ -78,12 +87,13 @@ import Foundation isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true isLocked = try typeContainer.decodeIfPresent(Bool.self, forKey: .isLocked) isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected) - fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) isValid = try typeContainer.decodeIfPresent(Bool.self, forKey: .isValid) text = try typeContainer.decodeIfPresent(String.self, forKey: .text) - + + baseValue = text + fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { - self.groupName = groupName + self.groupName = groupName } } diff --git a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift index 2ef6f292..ad5f6392 100644 --- a/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/TextFields/TextEntryField.swift @@ -232,7 +232,7 @@ import UIKit /// Validates the text of the entry field. @objc public func validateTextField() { text = textField.text - FormValidator.validate(delegate: delegateObject?.formHolderDelegate) + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) } @objc public func updateValidation(_ isValid: Bool) { @@ -279,12 +279,14 @@ import UIKit guard let model = model as? TextEntryFieldModel else { return } model.updateUI = { [weak self] in - if self?.isSelected ?? false { - self?.updateValidation(model.isValid ?? true) - } + MVMCoreDispatchUtility.performBlock(onMainThread: { + if self?.isSelected ?? false { + self?.updateValidation(model.isValid ?? true) + } + }) } self.delegateObject = delegateObject - FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate) + FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) textColor.enabled = model.enabledTextColor?.uiColor textColor.disabled = model.disabledTextColor?.uiColor text = model.text diff --git a/MVMCoreUI/Atomic/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atomic/Atoms/Views/Checkbox.swift index c76383cb..0ab3bbf3 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Checkbox.swift @@ -129,7 +129,7 @@ import MVMCore (model as? CheckboxModel)?.isChecked = isSelected shapeLayer?.removeAllAnimations() updateCheckboxUI(isSelected: isSelected, isAnimated: isAnimated) - FormValidator.validate(delegate: delegateObject?.formHolderDelegate) + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) updateAccessibilityLabel() } } @@ -398,7 +398,7 @@ import MVMCore super.set(with: model, delegateObject, additionalData) guard let model = model as? CheckboxModel else { return } self.delegateObject = delegateObject - FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate) + FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate) if let fieldKey = model.fieldKey { self.fieldKey = fieldKey diff --git a/MVMCoreUI/Atomic/Atoms/Views/CheckboxModel.swift b/MVMCoreUI/Atomic/Atoms/Views/CheckboxModel.swift index 13b730a6..423ed1ee 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/CheckboxModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/CheckboxModel.swift @@ -29,10 +29,8 @@ import Foundation public var disabledCheckColor: Color = Color(uiColor: .mvmCoolGray3) public var action: ActionModelProtocol? - public var fieldKey: String? - public var fieldValue: JSONValue? - public var groupName: String? = FormValidator.defaultGroupName + public var groupName: String = FormValidator.defaultGroupName public var baseValue: AnyHashable? //-------------------------------------------------- @@ -41,8 +39,6 @@ import Foundation private enum CodingKeys: String, CodingKey { case moleculeName - case fieldKey - case fieldValue case isChecked = "checked" case isEnabled = "enabled" case isAnimated = "animated" @@ -56,23 +52,25 @@ import Foundation case disabledCheckColor case disabledBorderColor case action + case fieldKey case groupName } - - init(isChecked: Bool = false) {} public func formFieldValue() -> AnyHashable? { return isChecked } + public init(isChecked: Bool = false) { + self.isChecked = isChecked + baseValue = isChecked + } + //-------------------------------------------------- // MARK: - Codec //-------------------------------------------------- required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - fieldValue = try typeContainer.decodeIfPresent(JSONValue.self, forKey: .fieldValue) - fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) borderWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .borderWidth) ?? 1 borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) ?? Color(uiColor: .black) checkColor = try typeContainer.decodeIfPresent(Color.self, forKey: .checkColor) ?? Color(uiColor: .black) @@ -86,6 +84,9 @@ import Foundation isRound = try typeContainer.decodeIfPresent(Bool.self, forKey: .isRound) ?? false isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true action = try typeContainer.decodeModelIfPresent(codingKey: .action) + + baseValue = isChecked + fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { self.groupName = groupName } @@ -95,7 +96,6 @@ import Foundation var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(groupName, forKey: .groupName) - try container.encodeIfPresent(fieldValue, forKey: .fieldValue) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(borderColor, forKey: .borderColor) try container.encode(borderWidth, forKey: .borderWidth) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift index 3d9a2f21..0f7ff8b1 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Toggle.swift @@ -102,7 +102,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) } (model as? ToggleModel)?.state = isOn - FormValidator.validate(delegate: delegateObject?.formHolderDelegate) + _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") setNeedsLayout() layoutIfNeeded() @@ -343,7 +343,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) self.model = model self.delegateObject = delegateObject - FormValidator.setupValidation(molecule: toggleModel, delegate: delegateObject?.formHolderDelegate) + FormValidator.setupValidation(for: toggleModel, delegate: delegateObject?.formHolderDelegate) guard let model = model as? ToggleModel else { return } if let color = model.onTintColor?.uiColor { containerTintColor?.on = color diff --git a/MVMCoreUI/Atomic/Atoms/Views/ToggleModel.swift b/MVMCoreUI/Atomic/Atoms/Views/ToggleModel.swift index 334ba00f..b7febf97 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/ToggleModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/ToggleModel.swift @@ -17,14 +17,15 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo public var enabled: Bool = true public var action: ActionModelProtocol? public var alternateAction: ActionModelProtocol? - public var fieldKey: String? - public var groupName: String? = FormValidator.defaultGroupName - public var baseValue: AnyHashable? public var onTintColor: Color? public var offTintColor: Color? public var onKnobTintColor: Color? public var offKnobTintColor: Color? + public var fieldKey: String? + public var groupName: String = FormValidator.defaultGroupName + public var baseValue: AnyHashable? + private enum CodingKeys: String, CodingKey { case moleculeName case state @@ -32,13 +33,13 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo case enabled case action case backgroundColor - case fieldKey case alternateAction - case groupName case onTintColor case offTintColor case onKnobTintColor case offKnobTintColor + case fieldKey + case groupName } public func formFieldValue() -> AnyHashable? { @@ -47,6 +48,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo public init(_ state: Bool) { self.state = state + baseValue = state } required public init(from decoder: Decoder) throws { @@ -63,14 +65,16 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo action = try typeContainer.decodeModelIfPresent(codingKey: .action) alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) - if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { - self.groupName = groupName - } onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor) offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor) onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor) offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor) + + baseValue = state + fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { + self.groupName = groupName + } } public func encode(to encoder: Encoder) throws { @@ -80,11 +84,11 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(state, forKey: .state) - try container.encodeIfPresent(fieldKey, forKey: .fieldKey) - try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(onTintColor, forKey: .onTintColor) try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor) try container.encodeIfPresent(onKnobTintColor, forKey: .onKnobTintColor) try container.encodeIfPresent(offKnobTintColor, forKey: .offKnobTintColor) + try container.encodeIfPresent(fieldKey, forKey: .fieldKey) + try container.encodeIfPresent(groupName, forKey: .groupName) } } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 7a3446d2..024606f4 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -170,8 +170,8 @@ import UIKit navigationModel.line = LineModel(type: .none) } pageModel?.navigationItem = navigationModel - if self.formValidator == nil { - let rules = pageModel?.formRules + if self.formValidator == nil, + let rules = pageModel?.formRules { self.formValidator = FormValidator(rules) } } @@ -244,7 +244,7 @@ import UIKit } open func updateViews() { - formValidator?.validate() + _ = formValidator?.validate() } override open func viewDidLoad() { diff --git a/MVMCoreUI/FormUIHelpers/FormActionFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/FormActionFieldProtocol.swift deleted file mode 100644 index 31208e95..00000000 --- a/MVMCoreUI/FormUIHelpers/FormActionFieldProtocol.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// FormActionFieldProtocol.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 1/31/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -public protocol FormActionFieldProtocol: EnableableModelProtocol, FormItemProtocol { - func updateEnable(_ enabled: Bool) - var updateUI: (() -> Void)? { get set } -} diff --git a/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift index c59ccd08..b9d2defe 100644 --- a/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift @@ -5,13 +5,19 @@ // Created by Suresh, Kamlesh on 1/31/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // +// Form fields are items can be interacted with. They have value, and may need to be validated. import Foundation public protocol FormFieldProtocol: FormItemProtocol { + /// How the validator identifies the field when validating rules. var fieldKey: String? { get set } + + /// A place to store the initial value of the field for checking if the value has changed. var baseValue: AnyHashable? { get set } + + /// Returns the value of the field. Used for validations and possibly for sending to server. func formFieldValue() -> AnyHashable? } diff --git a/MVMCoreUI/FormUIHelpers/FormGroupWatcherFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/FormGroupWatcherFieldProtocol.swift new file mode 100644 index 00000000..624ea374 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/FormGroupWatcherFieldProtocol.swift @@ -0,0 +1,14 @@ +// +// FormGroupWatcherFieldProtocol.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 1/31/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// +// Fields that want to be informed of group validity. + +import Foundation + +public protocol FormGroupWatcherFieldProtocol: FormItemProtocol { + func setValidity(_ valid: Bool, group: FormGroupRule) +} diff --git a/MVMCoreUI/FormUIHelpers/FormHolderModelProtocol.swift b/MVMCoreUI/FormUIHelpers/FormHolderModelProtocol.swift index a9428a2b..b548024c 100644 --- a/MVMCoreUI/FormUIHelpers/FormHolderModelProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/FormHolderModelProtocol.swift @@ -5,7 +5,7 @@ // Created by Suresh, Kamlesh on 2/5/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // -// A protocol for the model of the delegate object that holds the form validator. The rules are stored in the model. +// A protocol for the model of the delegate object that holds the form validator. The rules that need to be validated are stored in the model. import Foundation diff --git a/MVMCoreUI/FormUIHelpers/FormItemProtocol.swift b/MVMCoreUI/FormUIHelpers/FormItemProtocol.swift index 9b671238..0c7f71bd 100644 --- a/MVMCoreUI/FormUIHelpers/FormItemProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/FormItemProtocol.swift @@ -5,15 +5,11 @@ // Created by Suresh, Kamlesh on 2/25/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // +// The base form item protocol. Shared by different types of items. In our case, the models (not views) are form items which are registered with the validator. import Foundation public protocol FormItemProtocol { - static var defaultGroupName: String? { get } - var groupName: String? { get set } -} -extension FormItemProtocol{ - public static var defaultGroupName: String? { - return "default" - } + /// The group name to used to group this item for validation, enableability, and value getting. + var groupName: String { get set } } diff --git a/MVMCoreUI/FormUIHelpers/FormRuleWatcherFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/FormRuleWatcherFieldProtocol.swift new file mode 100644 index 00000000..3fc47d25 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/FormRuleWatcherFieldProtocol.swift @@ -0,0 +1,14 @@ +// +// FormRuleWatcherFieldProtocol.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 3/2/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// +// Fields that want to be informed of rule validity. + +import Foundation + +public protocol FormRuleWatcherFieldProtocol { + func setValidity(_ valid: Bool, rule: RulesProtocol) +} diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 0a14e027..a38b4b3f 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -12,103 +12,118 @@ import MVMCore @objcMembers public class FormValidator: NSObject { static var defaultGroupName: String = "default" - var extraValidationBlock: (() -> Bool)? - var formRules: [FormGroupRule]? + var formRules: [FormGroupRule] weak var delegate: FormHolderProtocol? - var fieldMolecules: [String: FormFieldProtocol] = [:] - var formActionMolecules: [FormActionFieldProtocol] = [] + var fields: [String: FormFieldProtocol] = [:] + var groupWatchers: [FormGroupWatcherFieldProtocol] = [] var radioButtonsModelByGroup: [String: RadioButtonSelectionHelper] = [:] - public init(_ formRules: [FormGroupRule]?) { + public init(_ formRules: [FormGroupRule]) { self.formRules = formRules } - public func insertMolecule(_ molecule: FormItemProtocol) { - if var molecule = molecule as? FormFieldProtocol, - let fieldKey = molecule.fieldKey { - if molecule.baseValue == nil { - molecule.baseValue = molecule.formFieldValue() - } - fieldMolecules[fieldKey] = molecule - } - if let molecule = molecule as? FormActionFieldProtocol { - formActionMolecules.append(molecule) + /// Adds the form field to the validator. + public func add(_ field: FormFieldProtocol) { + if let fieldKey = field.fieldKey { + fields[fieldKey] = field } } - public static func setupValidation(molecule: FormItemProtocol, delegate: FormHolderProtocol?) { + /// Adds the form action to the validator. + public func add(_ action: FormGroupWatcherFieldProtocol) { + groupWatchers.append(action) + } + + /// Determines the type of item and adds it. + private func insert(_ item: FormItemProtocol) { + if let item = item as? FormFieldProtocol { + add(item) + } else if let item = item as? FormGroupWatcherFieldProtocol { + add(item) + } + } + + /// Convenience function. Gets the form validator from the holder and sets up the item with it. + public static func setupValidation(for item: FormItemProtocol, delegate: FormHolderProtocol?) { if let validator = delegate?.formValidator { validator.delegate = delegate - validator.insertMolecule(molecule) + validator.insert(item) } } + + /// Convenience function. Gets the form validator from the holder and asks it to validate. + public static func validate(delegate: FormHolderProtocol?) -> Bool? { + return delegate?.formValidator?.validate() + } + + /// Validates all rule groups. Returns if valid + public func validate() -> Bool { + var valid = true + for group in formRules { + valid = valid && validateGroup(group) + } + return valid + } + + /// Validates a given rule group. Returns if valid + public func validateGroup(_ group: FormGroupRule) -> Bool { + // Validate each rule. + var valid = true + for rule in group.rules { + valid = valid && validateRule(rule) + } + + // Notify the group watchers of validity. + for watcher in groupWatchers { + if watcher.groupName == group.groupName { + watcher.setValidity(valid, group: group) + } + } + + return valid + } - public static func getFormValidatorFor(delegate: FormHolderProtocol?) -> FormValidator? { - return delegate?.formValidator - } - - public static func validate(delegate: FormHolderProtocol?) { - delegate?.formValidator?.validate() - } - - public func validate() { - guard let formRules = formRules else { - return - } - formActionMolecules.forEach { (actionModel) in - if let groupName = actionModel.groupName, - let formRule = formRules.first(where: { $0.groupName == groupName }) { - validate(groupName, actionModel, formRule.rules) - } - } - } - - public func validate(_ groupName: String, _ actionModel: FormActionFieldProtocol, _ rules: [RulesProtocol]) { + /// Validates a given rule. Returns if valid. + public func validateRule(_ rule: RulesProtocol) -> Bool { var valid = true - for rule in rules { - valid = valid && rule.isValid(fieldMolecules) - if !valid { - break - } + for formKey in rule.fields { + guard let formField = fields[formKey] else { continue } + let fieldValidity = rule.isValid(formField) + (formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: rule) + valid = valid && fieldValidity } - actionModel.updateEnable(valid) - } - - public func formField(for fieldKey: String) -> FormFieldProtocol? { - return fieldMolecules[fieldKey] + return valid } } -// mark Form params +// mark Form params +// TODO: Temporary hacks, rewrite architecture to support this. @objc public extension FormValidator { @objc func addFormParams(requestParameters: MVMCoreRequestParameters) { - let formButton = getFormButton(forPageType: requestParameters.pageType) - let groupName = formButton?.groupName ?? FormValidator.defaultGroupName + let groupName = getGroupName(forPageType: requestParameters.pageType) ?? FormValidator.defaultGroupName let formParams = self.getFormParams(forGroup: groupName) requestParameters.add(formParams) } @objc func getFormParams( forGroup groupName: String) -> [String: Any] { var extraParam: [String: Any] = [:] - MVMCoreDispatchUtility.performSyncBlock(onMainThread: { - for (fieldKey, molecule) in self.fieldMolecules { - if let formFieldValue = molecule.formFieldValue(), - groupName == molecule.groupName { - extraParam[fieldKey] = formFieldValue - } + for (fieldKey, field) in fields { + if let formFieldValue = field.formFieldValue(), + groupName == field.groupName { + extraParam[fieldKey] = formFieldValue } - }) + } return extraParam } } -// Temporary +// TODO: Temporary hacks, rewrite architecture to support this. public extension FormValidator { - func getFormButton(forPageType pageType: String?) -> ButtonModel? { - for actionItem in formActionMolecules { + func getGroupName(forPageType pageType: String?) -> String? { + for actionItem in groupWatchers { if let buttonModel = actionItem as? ButtonModel, pageType == (buttonModel.action as? ActionOpenPageModel)?.pageType { - return buttonModel + return buttonModel.groupName } } return nil diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/FormGroupRule.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/FormGroupRule.swift index 34dfb7b8..b40d0460 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/FormGroupRule.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/FormGroupRule.swift @@ -5,6 +5,7 @@ // Created by Suresh, Kamlesh on 2/24/20. // Copyright © 2020 Verizon Wireless. All rights reserved. // +// Used by the form validator for storing the rules for a particular group. import Foundation diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift index 25119e03..6afe5b17 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift @@ -14,16 +14,19 @@ public enum RulesCodingKey: String, CodingKey { } public protocol RulesProtocol: ModelProtocol { - var type: String { get set } + // The type of rule + var type: String { get } + + // The fields that this rule applies to. var fields: [String] { get set } - func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool + + // Returns if a given field is valid according to the rule func isValid(_ formField: FormFieldProtocol) -> Bool - func setValid(_ formField: FormFieldProtocol, _ isValid: Bool) } public extension RulesProtocol { - var ruleType: String? { + var type: String { get { return Self.identifier } } @@ -34,23 +37,4 @@ public extension RulesProtocol { static var categoryName: String { return "\(RulesProtocol.self)" } - - func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { - var valid = true - - for formKey in fields { - guard let formField = fieldMolecules[formKey] else { continue } - let fieldValidity = isValid(formField) - setValid(formField, fieldValidity) - valid = valid && fieldValidity - } - - return valid - } - - func setValid(_ formField: FormFieldProtocol, _ isValid: Bool) { - guard let formFieldValid = formField as? ValidProtocol else { return } - - formFieldValid.setValidity(isValid) - } } diff --git a/MVMCoreUI/FormUIHelpers/ValidProtocol.swift b/MVMCoreUI/FormUIHelpers/ValidProtocol.swift deleted file mode 100644 index 20afd256..00000000 --- a/MVMCoreUI/FormUIHelpers/ValidProtocol.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// ValidProtocol.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 3/2/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -public protocol ValidProtocol { - var isValid: Bool? { get set } - func setValidity(_ isValid: Bool) - var updateUI: (() -> Void)? { get set } -} diff --git a/MVMCoreUI/Legacy/Controllers/MFViewController+Form.swift b/MVMCoreUI/Legacy/Controllers/MFViewController+Form.swift deleted file mode 100644 index 2c3b14bf..00000000 --- a/MVMCoreUI/Legacy/Controllers/MFViewController+Form.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// MFViewController+Form.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 3/3/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -extension MFViewController: ObservingTextFieldDelegate { -} - -public extension MFViewController { - @objc func startValidation() { - (self as? FormHolderProtocol)?.formValidator?.validate() - } - - @objc func addFormParams(requestParameters: MVMCoreRequestParameters) { - (self as? FormHolderProtocol)?.formValidator?.addFormParams(requestParameters: requestParameters) - } -} diff --git a/MVMCoreUI/Legacy/Controllers/MFViewController+Model.swift b/MVMCoreUI/Legacy/Controllers/MFViewController+Model.swift deleted file mode 100644 index 30abf59d..00000000 --- a/MVMCoreUI/Legacy/Controllers/MFViewController+Model.swift +++ /dev/null @@ -1,40 +0,0 @@ -// -// MFViewController+Model.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 10/24/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - -extension MFViewController: MoleculeDelegateProtocol { - - public func getModuleWithName(_ name: String?) -> [AnyHashable: Any]? { - guard let name = name else { return nil } - - return loadObject?.modulesJSON?.optionalDictionaryForKey(name) - } - - public func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol? { - guard let moduleJSON = loadObject?.modulesJSON?.optionalDictionaryForKey(moleculeName), - let moleculeName = moduleJSON.optionalStringForKey("moleculeName"), - let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self) - else { return nil } - - do { - return try modelType.decode(jsonDict: moduleJSON) as? MoleculeModelProtocol - } catch { - MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)") - } - - return nil - } - - // These are required because swift will call the extension function otherwise. - public func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) {} - - @objc public func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {} - @objc public func addMolecules(_ molecules: [[AnyHashable : Any]], indexPath: IndexPath, animation: UITableView.RowAnimation) {} - @objc public func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {} -} diff --git a/MVMCoreUI/Legacy/Controllers/MFViewController.m b/MVMCoreUI/Legacy/Controllers/MFViewController.m index febb14cf..68dd75c4 100644 --- a/MVMCoreUI/Legacy/Controllers/MFViewController.m +++ b/MVMCoreUI/Legacy/Controllers/MFViewController.m @@ -467,9 +467,6 @@ - (void)newDataBuildAndUpdate { [MVMCoreDispatchUtility performBlockOnMainThread:^{ [self newDataBuildScreen]; - dispatch_async(dispatch_get_main_queue(), ^{ - [self startValidation]; - }); self.needToUpdateUI = YES; [self.view setNeedsLayout]; }]; @@ -666,8 +663,6 @@ if (requestParameters.openSupportPanel) { [[MVMCoreUISession sharedGlobal].splitViewController.rightPanel willOpenWithActionInformation:actionInformation]; } - - [self addFormParamsWithRequestParameters:requestParameters]; requestParameters.parentPageType = [self.loadObject.pageJSON stringForKey:@"parentPageType"]; [[MVMCoreLoadHandler sharedGlobal] loadRequest:requestParameters dataForPage:additionalData delegateObject:[self delegateObject]]; }