From 65c3f0427a64d4ad45ab55a7ef143579102655fa Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Thu, 18 Apr 2019 11:07:00 -0400 Subject: [PATCH 01/45] radiobuttons --- MVMCoreUI.xcodeproj/project.pbxproj | 6 + MVMCoreUI/Atoms/Views/MFLabel.m | 4 +- MVMCoreUI/Molecules/RadioButton.swift | 135 ++++++++++++++++++ .../MVMCoreUIMoleculeMappingObject.m | 3 +- 4 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 MVMCoreUI/Molecules/RadioButton.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 1f3e1d53..e9fd6b52 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618A224BBE7700E1557D /* FormValidator.swift */; }; 0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */; }; 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */; }; + 01157B94225D376D00F15D92 /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01157B93225D376D00F15D92 /* RadioButton.swift */; }; 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198F79E225679870066C936 /* FormValidationProtocol.swift */; }; 0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 0198F7A02256A80A0066C936 /* MFRadioButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0198F7A22256A80A0066C936 /* MFRadioButton.m */; }; @@ -168,6 +169,7 @@ 0105618A224BBE7700E1557D /* FormValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidator.swift; sourceTree = ""; }; 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = ""; }; 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+FormParams.swift"; sourceTree = ""; }; + 01157B93225D376D00F15D92 /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = ""; }; 0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = ""; }; 0198F7A02256A80A0066C936 /* MFRadioButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFRadioButton.h; sourceTree = ""; }; 0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = ""; }; @@ -442,6 +444,7 @@ D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */, D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */, D274CA322236A78900B01B62 /* StandardFooterView.swift */, + 01157B93225D376D00F15D92 /* RadioButton.swift */, ); path = Molecules; sourceTree = ""; @@ -560,6 +563,8 @@ D29DF17D21E69E26003B2FB9 /* Views */ = { isa = PBXGroup; children = ( + 0198F7A02256A80A0066C936 /* MFRadioButton.h */, + 0198F7A22256A80A0066C936 /* MFRadioButton.m */, DBC4391622442196001AB423 /* CaretView.swift */, DBC4391722442197001AB423 /* DashLine.swift */, D29DF17E21E69E2E003B2FB9 /* MFView.h */, @@ -898,6 +903,7 @@ D282AACB2243C61700C46919 /* ButtonView.swift in Sources */, 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */, D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */, + 01157B94225D376D00F15D92 /* RadioButton.swift in Sources */, D29DF18121E69E50003B2FB9 /* MFView.m in Sources */, D29DF18321E69E54003B2FB9 /* SeparatorView.m in Sources */, D29DF17A21E69E1F003B2FB9 /* MFCustomButton.m in Sources */, diff --git a/MVMCoreUI/Atoms/Views/MFLabel.m b/MVMCoreUI/Atoms/Views/MFLabel.m index 5fb19037..60d42178 100644 --- a/MVMCoreUI/Atoms/Views/MFLabel.m +++ b/MVMCoreUI/Atoms/Views/MFLabel.m @@ -154,7 +154,9 @@ } + (nonnull MFLabel *)label { - return [[MFLabel alloc] initWithFrame:CGRectZero]; + MFLabel *labelToReturn = [[MFLabel alloc] initWithFrame:CGRectZero]; + labelToReturn.translatesAutoresizingMaskIntoConstraints = NO; + return labelToReturn; } #pragma mark - Setters diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift new file mode 100644 index 00000000..7703b7dc --- /dev/null +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -0,0 +1,135 @@ +// +// RadioButton.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 4/9/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers open class RadioButton: ViewConstrainingView, FormValidationProtocol{ + + var moleculeJson: [AnyHashable: Any]? + var selectedRadioButton: MFRadioButton? + var selectedValue: String? + + // MARK: - Inits + public init() { + super.init(frame: .zero) + } + + public override init(frame: CGRect) { + super.init(frame: frame) + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + self.moleculeJson = json + + // Configure class properties with JSON values + guard let jsonDictionary = moleculeJson, + let optionsList = jsonDictionary.optionalArrayForKey("optionsList") else { + return + } + + if let delegateObject = delegateObject as? MVMCoreUIDelegateObject { + FormValidator.setupValidation(molecule: self, delegate: delegateObject.formValidationProtocol) + } + + var items:[UIView] = [] + for option in optionsList { + if let itemUI = createOptionItem(option as? [AnyHashable: Any]) { + items.append(itemUI) + } + } + + let verticalSpace = MFStyler.defaultVerticalPadding(forSize: MVMCoreUIUtility.getWidth()) + StackableViewController.populateView(self, + withUIArray: items) { (item) -> UIEdgeInsets in + return UIEdgeInsets(top: verticalSpace, + left: 0, + bottom: 0, + right: 0) + } + } + + func createOptionItem(_ optionJson: [AnyHashable: Any]?) -> UIView? { + + guard let json = optionJson else { + return nil + } + + let containerView = ViewConstrainingView.empty() + let radioButton = MFRadioButton() + radioButton.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(radioButton) + + let label = MFLabel.commonLabel() + label.setWithJSON(json.dictionaryForKey(KeyLabel), delegateObject: nil, additionalData: nil) + containerView.addSubview(label) + + radioButton.leftAnchor.constraint(equalTo: containerView.leftAnchor, constant: 0).isActive = true + radioButton.topAnchor.constraint(greaterThanOrEqualTo: containerView.topAnchor, constant: PaddingOne).isActive = true + containerView.bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true + radioButton.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true + + label.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingTwo).isActive = true + label.rightAnchor.constraint(equalTo: containerView.rightAnchor, constant: 0).isActive = true + label.topAnchor.constraint(greaterThanOrEqualTo: containerView.topAnchor, constant: PaddingOne).isActive = true + label.bottomAnchor.constraint(greaterThanOrEqualTo: containerView.bottomAnchor, constant: PaddingOne).isActive = true + label.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true + + addActionHandler(containerView, radioButton, json) + return containerView + } + + func addActionHandler(_ containerView: UIView, _ radioButton: MFRadioButton, _ optionJson: [AnyHashable: Any]) { + let dummyButton = MFCustomButton(frame: .zero) + dummyButton.translatesAutoresizingMaskIntoConstraints = false + containerView.addSubview(dummyButton) + NSLayoutConstraint.constraintPinSubview(toSuperview: dummyButton) + containerView.bringSubviewToFront(dummyButton) + + dummyButton.add({ (button) in + if let selectedbutton = self.selectedRadioButton { + selectedbutton.isSelected = false + } + self.selectedValue = optionJson.optionalStringForKey(KeyValue) + self.selectedRadioButton = radioButton + self.selectedRadioButton?.isSelected = true + }, for: .touchUpInside) + } + + func getColor( _ json: [AnyHashable: Any], _ key: String) -> UIColor? { + if let colorHex = json.optionalStringForKey(key) { + return UIColor.mfGet(forHex: colorHex) + } else { + return nil + } + } + + open override func setupView() { + super.setupView() + self.translatesAutoresizingMaskIntoConstraints = false + } + + // Used to check the validity of the field, to enable/disable the primary button. + @objc public func isValidField() -> Bool { + return selectedValue != nil + } + + // The Field name key value pair for sending to server + @objc public func formFieldName() -> String? { + return moleculeJson?.stringForkey("fieldKey") + } + + // The Feild value key value paid for sending to server + @objc public func formFieldValue() -> String? { + return selectedValue + } +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index c1d7a36d..8c7a88ec 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -32,7 +32,8 @@ @"standardFooter": StandardFooterView.class, @"caretView": CaretView.class, @"caretButton": CaretButton.class, - @"textField" : MFTextField.class + @"textField" : MFTextField.class, + @"radioButton": RadioButton.class } mutableCopy]; }); return mapping; From 382a4c5d3b3db66d6b0822882e02a33968ba579b Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 26 Apr 2019 16:45:13 -0400 Subject: [PATCH 02/45] improvments --- MVMCoreUI.xcodeproj/project.pbxproj | 18 ++- .../Atoms/Views/MFView+FormValidation.swift | 21 +++ MVMCoreUI/Atoms/Views/MFView.h | 3 + MVMCoreUI/FormUIHelpers/FormValidator.swift | 9 +- MVMCoreUI/Molecules/RadioButton.swift | 134 ++++++++---------- MVMCoreUI/Molecules/RadioButtonList.swift | 92 ++++++++++++ .../MVMCoreUIMoleculeMappingObject.m | 1 + 7 files changed, 190 insertions(+), 88 deletions(-) create mode 100644 MVMCoreUI/Atoms/Views/MFView+FormValidation.swift create mode 100644 MVMCoreUI/Molecules/RadioButtonList.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index b294f7d1..63ff3d19 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -7,10 +7,12 @@ objects = { /* Begin PBXBuildFile section */ + 01004F3022721C3800991ECC /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01004F2F22721C3800991ECC /* RadioButton.swift */; }; + 01004F322273972F00991ECC /* MFView+FormValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01004F312273972F00991ECC /* MFView+FormValidation.swift */; }; 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618A224BBE7700E1557D /* FormValidator.swift */; }; 0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */; }; 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */; }; - 01157B94225D376D00F15D92 /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01157B93225D376D00F15D92 /* RadioButton.swift */; }; + 01157B94225D376D00F15D92 /* RadioButtonList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01157B93225D376D00F15D92 /* RadioButtonList.swift */; }; 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198F79E225679870066C936 /* FormValidationProtocol.swift */; }; 0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 0198F7A02256A80A0066C936 /* MFRadioButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0198F7A22256A80A0066C936 /* MFRadioButton.m */; }; @@ -165,10 +167,12 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 01004F2F22721C3800991ECC /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = ""; }; + 01004F312273972F00991ECC /* MFView+FormValidation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFView+FormValidation.swift"; sourceTree = ""; }; 0105618A224BBE7700E1557D /* FormValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidator.swift; sourceTree = ""; }; 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = ""; }; 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+FormParams.swift"; sourceTree = ""; }; - 01157B93225D376D00F15D92 /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = ""; }; + 01157B93225D376D00F15D92 /* RadioButtonList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonList.swift; sourceTree = ""; }; 0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = ""; }; 0198F7A02256A80A0066C936 /* MFRadioButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFRadioButton.h; sourceTree = ""; }; 0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = ""; }; @@ -442,7 +446,8 @@ D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */, D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */, D274CA322236A78900B01B62 /* StandardFooterView.swift */, - 01157B93225D376D00F15D92 /* RadioButton.swift */, + 01157B93225D376D00F15D92 /* RadioButtonList.swift */, + 01004F2F22721C3800991ECC /* RadioButton.swift */, ); path = Molecules; sourceTree = ""; @@ -561,11 +566,10 @@ D29DF17D21E69E26003B2FB9 /* Views */ = { isa = PBXGroup; children = ( - 0198F7A02256A80A0066C936 /* MFRadioButton.h */, - 0198F7A22256A80A0066C936 /* MFRadioButton.m */, DBC4391622442196001AB423 /* CaretView.swift */, DBC4391722442197001AB423 /* DashLine.swift */, D29DF17E21E69E2E003B2FB9 /* MFView.h */, + 01004F312273972F00991ECC /* MFView+FormValidation.swift */, D29DF17F21E69E2E003B2FB9 /* MFView.m */, D29DF31E21ED0CBA003B2FB9 /* LabelView.h */, D29DF31F21ED0CBA003B2FB9 /* LabelView.m */, @@ -871,6 +875,7 @@ D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, + 01004F3022721C3800991ECC /* RadioButton.swift in Sources */, D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, D29DF25321E6A177003B2FB9 /* MFDigitTextField.m in Sources */, @@ -885,6 +890,7 @@ D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */, 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */, D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, + 01004F322273972F00991ECC /* MFView+FormValidation.swift in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, D29DF24D21E6A177003B2FB9 /* MFTextField.m in Sources */, D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */, @@ -900,7 +906,7 @@ D282AACB2243C61700C46919 /* ButtonView.swift in Sources */, 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */, D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */, - 01157B94225D376D00F15D92 /* RadioButton.swift in Sources */, + 01157B94225D376D00F15D92 /* RadioButtonList.swift in Sources */, D29DF18121E69E50003B2FB9 /* MFView.m in Sources */, D29DF18321E69E54003B2FB9 /* SeparatorView.m in Sources */, D29DF17A21E69E1F003B2FB9 /* MFCustomButton.m in Sources */, diff --git a/MVMCoreUI/Atoms/Views/MFView+FormValidation.swift b/MVMCoreUI/Atoms/Views/MFView+FormValidation.swift new file mode 100644 index 00000000..9e4fe2a9 --- /dev/null +++ b/MVMCoreUI/Atoms/Views/MFView+FormValidation.swift @@ -0,0 +1,21 @@ +// +// MFView+FormValidation.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 4/26/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import Foundation + + +extension FormValidationProtocol where Self: MFView { + + func setupFormValidation(delegateObject: DelegateObject?) { + if let delegateObject = delegateObject as? MVMCoreUIDelegateObject, + let formValidationProtocol = delegateObject.formValidationProtocol { + FormValidator.setupValidation(molecule: self, delegate:formValidationProtocol) + formValidator = FormValidator.getFormValidatorFor(delegate:formValidationProtocol) + } + } +} diff --git a/MVMCoreUI/Atoms/Views/MFView.h b/MVMCoreUI/Atoms/Views/MFView.h index 5e32ff0a..079e3c3a 100644 --- a/MVMCoreUI/Atoms/Views/MFView.h +++ b/MVMCoreUI/Atoms/Views/MFView.h @@ -10,8 +10,11 @@ #import @import MVMCore.MVMCoreViewProtocol; +@class FormValidator; + @interface MFView : UIView +@property (nullable, strong, nonatomic) FormValidator *formValidator; @property (nullable, nonatomic, strong) NSDictionary *json; // Called in the initialization functions. Can setup ui here. diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 1b546d69..5eb28904 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -40,10 +40,7 @@ import UIKit public func enableByValidation() { var valid = true for molecule in molecules { - if let isValidField = molecule.isValidField, - isValidField() == false { - valid = false - } + valid = valid && (molecule.isValidField?() ?? true) } let enableField = valid && (extraValidationBlock?() ?? true) shouldEnable(enableField) @@ -51,9 +48,7 @@ import UIKit public func shouldEnable(_ enable: Bool) { for molecule in molecules { - if let enableField = molecule.enableField { - enableField(enable) - } + molecule.enableField?(enable) } } } diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index 7703b7dc..4fb469fd 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -2,17 +2,19 @@ // RadioButton.swift // MVMCoreUI // -// Created by Suresh, Kamlesh on 4/9/19. +// Created by Suresh, Kamlesh on 4/25/19. // Copyright © 2019 Verizon Wireless. All rights reserved. // import UIKit -@objcMembers open class RadioButton: ViewConstrainingView, FormValidationProtocol{ - var moleculeJson: [AnyHashable: Any]? - var selectedRadioButton: MFRadioButton? - var selectedValue: String? +@objcMembers open class RadioButton: ViewConstrainingView, FormValidationProtocol{ + + var selectedRadioButton: MFRadioButton? + let radioButton = MFRadioButton() + let label = Label() + var target: RadioButtonListProtocol? // MARK: - Inits public init() { @@ -27,84 +29,67 @@ import UIKit super.init(coder: aDecoder) } + public init(target: RadioButtonListProtocol) { + super.init(frame: .zero) + self.target = target + } + + open override func setupView() { + super.setupView() + self.translatesAutoresizingMaskIntoConstraints = false + + radioButton.translatesAutoresizingMaskIntoConstraints = false + addSubview(radioButton) + + addSubview(label) + + radioButton.leftAnchor.constraint(equalTo: leftAnchor, constant: 0).isActive = true + radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true + bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true + radioButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + + label.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingTwo).isActive = true + label.rightAnchor.constraint(equalTo: rightAnchor, constant: 0).isActive = true + label.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true + label.bottomAnchor.constraint(greaterThanOrEqualTo: bottomAnchor, constant: PaddingOne).isActive = true + label.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + } + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - self.moleculeJson = json // Configure class properties with JSON values - guard let jsonDictionary = moleculeJson, - let optionsList = jsonDictionary.optionalArrayForKey("optionsList") else { - return + guard let jsonDictionary = json else { + return } - - if let delegateObject = delegateObject as? MVMCoreUIDelegateObject { - FormValidator.setupValidation(molecule: self, delegate: delegateObject.formValidationProtocol) - } - - var items:[UIView] = [] - for option in optionsList { - if let itemUI = createOptionItem(option as? [AnyHashable: Any]) { - items.append(itemUI) - } - } - - let verticalSpace = MFStyler.defaultVerticalPadding(forSize: MVMCoreUIUtility.getWidth()) - StackableViewController.populateView(self, - withUIArray: items) { (item) -> UIEdgeInsets in - return UIEdgeInsets(top: verticalSpace, - left: 0, - bottom: 0, - right: 0) - } - } - - func createOptionItem(_ optionJson: [AnyHashable: Any]?) -> UIView? { - - guard let json = optionJson else { - return nil - } - - let containerView = ViewConstrainingView.empty() - let radioButton = MFRadioButton() - radioButton.translatesAutoresizingMaskIntoConstraints = false - containerView.addSubview(radioButton) - - let label = MFLabel.commonLabel() - label.setWithJSON(json.dictionaryForKey(KeyLabel), delegateObject: nil, additionalData: nil) - containerView.addSubview(label) - - radioButton.leftAnchor.constraint(equalTo: containerView.leftAnchor, constant: 0).isActive = true - radioButton.topAnchor.constraint(greaterThanOrEqualTo: containerView.topAnchor, constant: PaddingOne).isActive = true - containerView.bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true - radioButton.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true - label.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingTwo).isActive = true - label.rightAnchor.constraint(equalTo: containerView.rightAnchor, constant: 0).isActive = true - label.topAnchor.constraint(greaterThanOrEqualTo: containerView.topAnchor, constant: PaddingOne).isActive = true - label.bottomAnchor.constraint(greaterThanOrEqualTo: containerView.bottomAnchor, constant: PaddingOne).isActive = true - label.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true - - addActionHandler(containerView, radioButton, json) - return containerView + setupFormValidation(delegateObject: delegateObject) + label.setWithJSON(jsonDictionary.dictionaryForKey(KeyLabel), delegateObject: nil, additionalData: nil) + addActionHandler() } - func addActionHandler(_ containerView: UIView, _ radioButton: MFRadioButton, _ optionJson: [AnyHashable: Any]) { + func addActionHandler() { + let dummyButton = MFCustomButton(frame: .zero) dummyButton.translatesAutoresizingMaskIntoConstraints = false - containerView.addSubview(dummyButton) + addSubview(dummyButton) NSLayoutConstraint.constraintPinSubview(toSuperview: dummyButton) - containerView.bringSubviewToFront(dummyButton) + bringSubviewToFront(dummyButton) dummyButton.add({ (button) in - if let selectedbutton = self.selectedRadioButton { - selectedbutton.isSelected = false - } - self.selectedValue = optionJson.optionalStringForKey(KeyValue) - self.selectedRadioButton = radioButton - self.selectedRadioButton?.isSelected = true + self.tapAction() }, for: .touchUpInside) } + func tapAction() { + if let target = target { + target.selected?(self) + } else { + radioButton.isSelected = !radioButton.isSelected + } + formValidator?.enableByValidation() + } + func getColor( _ json: [AnyHashable: Any], _ key: String) -> UIColor? { if let colorHex = json.optionalStringForKey(key) { return UIColor.mfGet(forHex: colorHex) @@ -112,24 +97,23 @@ import UIKit return nil } } - - open override func setupView() { - super.setupView() - self.translatesAutoresizingMaskIntoConstraints = false - } // Used to check the validity of the field, to enable/disable the primary button. @objc public func isValidField() -> Bool { - return selectedValue != nil + if !radioButton.isSelected { + return true + } + return formFieldValue() != nil } // The Field name key value pair for sending to server @objc public func formFieldName() -> String? { - return moleculeJson?.stringForkey("fieldKey") + return radioButton.isSelected ? json?.stringForkey("fieldKey") : nil } // The Feild value key value paid for sending to server @objc public func formFieldValue() -> String? { - return selectedValue + return radioButton.isSelected ? json?.stringForkey(KeyValue) : nil } } + diff --git a/MVMCoreUI/Molecules/RadioButtonList.swift b/MVMCoreUI/Molecules/RadioButtonList.swift new file mode 100644 index 00000000..e0393927 --- /dev/null +++ b/MVMCoreUI/Molecules/RadioButtonList.swift @@ -0,0 +1,92 @@ +// +// RadioButton.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 4/9/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objc public protocol RadioButtonListProtocol: NSObjectProtocol { + + @objc optional func selected(_ radioButton: RadioButton) +} + + +@objcMembers open class RadioButtonList: ViewConstrainingView, FormValidationProtocol, RadioButtonListProtocol { + + var selectedRadioButton: RadioButton? + var selectedValue: String? + + // MARK: - Inits + public init() { + super.init(frame: .zero) + } + + public override init(frame: CGRect) { + super.init(frame: frame) + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + // Configure class properties with JSON values + guard let jsonDictionary = json, + let optionsList = jsonDictionary.optionalArrayForKey("optionsList") as? [[AnyHashable: Any]], + let delegateObject = delegateObject as? MVMCoreUIDelegateObject else { + return + } + + setupFormValidation(delegateObject: delegateObject) + var items:[UIView] = [] + for option in optionsList { + let radioButton = RadioButton(target: self) + radioButton.setWithJSON(option, delegateObject: delegateObject, additionalData: nil) + items.append(radioButton) + } + + let verticalSpace = MFStyler.defaultVerticalPadding(forSize: MVMCoreUIUtility.getWidth()) + StackableViewController.populateView(self, + withUIArray: items) { (item) -> UIEdgeInsets in + return UIEdgeInsets(top: verticalSpace, + left: 0, + bottom: 0, + right: 0) + } + } + + public func selected(_ radioButton: RadioButton) { + selectedRadioButton?.radioButton.isSelected = false + selectedRadioButton = radioButton + selectedRadioButton?.radioButton.isSelected = true + } + + open override func setupView() { + super.setupView() + self.translatesAutoresizingMaskIntoConstraints = false + } + + // Used to check the validity of the field, to enable/disable the primary button. + @objc public func isValidField() -> Bool { + if !(json?.boolForKey("required") ?? true) { + return true + } + + return selectedRadioButton?.isValidField() ?? false + } + + // The Field name key value pair for sending to server + @objc public func formFieldName() -> String? { + return selectedRadioButton?.formFieldName() + } + + // The Feild value key value paid for sending to server + @objc public func formFieldValue() -> String? { + return selectedRadioButton?.formFieldValue() + } +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 6f1b577b..759f65c4 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -33,6 +33,7 @@ @"caretView": CaretView.class, @"caretButton": CaretButton.class, @"textField" : MFTextField.class, + @"radioButtonList": RadioButtonList.class, @"radioButton": RadioButton.class } mutableCopy]; }); From 24ab8f5ece8daac56851e0bc90aca84820812b7a Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 1 May 2019 10:41:04 -0400 Subject: [PATCH 03/45] cleanup --- MVMCoreUI/Molecules/RadioButton.swift | 67 +++++++++++--------- MVMCoreUI/Molecules/RadioButtonList.swift | 76 ++++++++++++++--------- 2 files changed, 83 insertions(+), 60 deletions(-) diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index 4fb469fd..c66bdedd 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -9,7 +9,7 @@ import UIKit -@objcMembers open class RadioButton: ViewConstrainingView, FormValidationProtocol{ +@objcMembers open class RadioButton: ViewConstrainingView { var selectedRadioButton: MFRadioButton? let radioButton = MFRadioButton() @@ -36,11 +36,13 @@ import UIKit open override func setupView() { super.setupView() - self.translatesAutoresizingMaskIntoConstraints = false + guard subviews.count == 0 else { + return + } + translatesAutoresizingMaskIntoConstraints = false radioButton.translatesAutoresizingMaskIntoConstraints = false addSubview(radioButton) - addSubview(label) radioButton.leftAnchor.constraint(equalTo: leftAnchor, constant: 0).isActive = true @@ -55,19 +57,6 @@ import UIKit label.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true } - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - - // Configure class properties with JSON values - guard let jsonDictionary = json else { - return - } - - setupFormValidation(delegateObject: delegateObject) - label.setWithJSON(jsonDictionary.dictionaryForKey(KeyLabel), delegateObject: nil, additionalData: nil) - addActionHandler() - } - func addActionHandler() { let dummyButton = MFCustomButton(frame: .zero) @@ -76,8 +65,8 @@ import UIKit NSLayoutConstraint.constraintPinSubview(toSuperview: dummyButton) bringSubviewToFront(dummyButton) - dummyButton.add({ (button) in - self.tapAction() + dummyButton.add({ [weak self] (button) in + self?.tapAction() }, for: .touchUpInside) } @@ -97,23 +86,43 @@ import UIKit return nil } } +} + +// MARK: - MVMCoreUIMoleculeViewProtocol +extension RadioButton { - // Used to check the validity of the field, to enable/disable the primary button. - @objc public func isValidField() -> Bool { - if !radioButton.isSelected { - return true + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + // Configure class properties with JSON values + guard let jsonDictionary = json else { + return } - return formFieldValue() != nil + + label.setWithJSON(jsonDictionary.optionalDictionaryForKey(KeyLabel), + delegateObject: delegateObject, + additionalData: additionalData) + addActionHandler() } - // The Field name key value pair for sending to server - @objc public func formFieldName() -> String? { - return radioButton.isSelected ? json?.stringForkey("fieldKey") : nil + open override func needsToBeConstrained() -> Bool { + return true } - // The Feild value key value paid for sending to server - @objc public func formFieldValue() -> String? { - return radioButton.isSelected ? json?.stringForkey(KeyValue) : nil + open override func moleculeAlignment() -> UIStackView.Alignment { + return UIStackView.Alignment.leading; } } +// MARK: - FormValidationProtocol +extension RadioButton: FormValidationProtocol { + // The Field name key value pair for sending to server + @objc public func formFieldName() -> String? { + return json?.optionalStringForKey("fieldKey") + } + + // The Field value key value paid for sending to server + @objc public func formFieldValue() -> Any? { + return json?.optionalStringForKey(KeyValue) + } +} diff --git a/MVMCoreUI/Molecules/RadioButtonList.swift b/MVMCoreUI/Molecules/RadioButtonList.swift index e0393927..fdfbd00a 100644 --- a/MVMCoreUI/Molecules/RadioButtonList.swift +++ b/MVMCoreUI/Molecules/RadioButtonList.swift @@ -13,8 +13,7 @@ import UIKit @objc optional func selected(_ radioButton: RadioButton) } - -@objcMembers open class RadioButtonList: ViewConstrainingView, FormValidationProtocol, RadioButtonListProtocol { +@objcMembers open class RadioButtonList: ViewConstrainingView, RadioButtonListProtocol { var selectedRadioButton: RadioButton? var selectedValue: String? @@ -32,6 +31,43 @@ import UIKit super.init(coder: aDecoder) } + public func selected(_ radioButton: RadioButton) { + selectedRadioButton?.radioButton.isSelected = false + selectedRadioButton = radioButton + selectedRadioButton?.radioButton.isSelected = true + formValidator?.enableByValidation() + } + + open override func setupView() { + super.setupView() + self.translatesAutoresizingMaskIntoConstraints = false + } +} + +// MARK: - FormValidationProtocol +extension RadioButtonList: FormValidationProtocol { + // Used to check the validity of the field, to enable/disable the primary button. + @objc public func isValidField() -> Bool { + if !(json?.boolForKey("required") ?? true) { + return true + } + return selectedRadioButton != nil + } + + // The Field name key value pair for sending to server + @objc public func formFieldName() -> String? { + return selectedRadioButton?.formFieldName() + } + + // The Feild value key value paid for sending to server + @objc public func formFieldValue() -> Any? { + return selectedRadioButton?.formFieldValue() + } +} + +// MARK: - MVMCoreUIMoleculeViewProtocol +extension RadioButtonList { + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) @@ -39,9 +75,9 @@ import UIKit guard let jsonDictionary = json, let optionsList = jsonDictionary.optionalArrayForKey("optionsList") as? [[AnyHashable: Any]], let delegateObject = delegateObject as? MVMCoreUIDelegateObject else { - return + return } - + setupFormValidation(delegateObject: delegateObject) var items:[UIView] = [] for option in optionsList { @@ -49,7 +85,7 @@ import UIKit radioButton.setWithJSON(option, delegateObject: delegateObject, additionalData: nil) items.append(radioButton) } - + let verticalSpace = MFStyler.defaultVerticalPadding(forSize: MVMCoreUIUtility.getWidth()) StackableViewController.populateView(self, withUIArray: items) { (item) -> UIEdgeInsets in @@ -60,33 +96,11 @@ import UIKit } } - public func selected(_ radioButton: RadioButton) { - selectedRadioButton?.radioButton.isSelected = false - selectedRadioButton = radioButton - selectedRadioButton?.radioButton.isSelected = true - } - - open override func setupView() { - super.setupView() - self.translatesAutoresizingMaskIntoConstraints = false + open override func needsToBeConstrained() -> Bool { + return true } - // Used to check the validity of the field, to enable/disable the primary button. - @objc public func isValidField() -> Bool { - if !(json?.boolForKey("required") ?? true) { - return true - } - - return selectedRadioButton?.isValidField() ?? false - } - - // The Field name key value pair for sending to server - @objc public func formFieldName() -> String? { - return selectedRadioButton?.formFieldName() - } - - // The Feild value key value paid for sending to server - @objc public func formFieldValue() -> String? { - return selectedRadioButton?.formFieldValue() + open override func moleculeAlignment() -> UIStackView.Alignment { + return UIStackView.Alignment.leading; } } From 312bc0b868df2c264f06943bca8b26d61e017200 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 3 May 2019 17:45:10 -0400 Subject: [PATCH 04/45] code review --- MVMCoreUI/Molecules/RadioButton.swift | 7 ++++++- MVMCoreUI/Molecules/RadioButtonList.swift | 5 ++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index c66bdedd..d5cc4d87 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -11,10 +11,10 @@ import UIKit @objcMembers open class RadioButton: ViewConstrainingView { - var selectedRadioButton: MFRadioButton? let radioButton = MFRadioButton() let label = Label() var target: RadioButtonListProtocol? + var dummyButton: MFCustomButton? // MARK: - Inits public init() { @@ -59,7 +59,12 @@ import UIKit func addActionHandler() { + if dummyButton != nil { + return + } + let dummyButton = MFCustomButton(frame: .zero) + self.dummyButton = dummyButton dummyButton.translatesAutoresizingMaskIntoConstraints = false addSubview(dummyButton) NSLayoutConstraint.constraintPinSubview(toSuperview: dummyButton) diff --git a/MVMCoreUI/Molecules/RadioButtonList.swift b/MVMCoreUI/Molecules/RadioButtonList.swift index fdfbd00a..6a1083fd 100644 --- a/MVMCoreUI/Molecules/RadioButtonList.swift +++ b/MVMCoreUI/Molecules/RadioButtonList.swift @@ -79,6 +79,9 @@ extension RadioButtonList { } setupFormValidation(delegateObject: delegateObject) + + StackableViewController.remove(self.subviews) + var items:[UIView] = [] for option in optionsList { let radioButton = RadioButton(target: self) @@ -86,7 +89,7 @@ extension RadioButtonList { items.append(radioButton) } - let verticalSpace = MFStyler.defaultVerticalPadding(forSize: MVMCoreUIUtility.getWidth()) + let verticalSpace = MFStyler.defaultVerticalPaddingForApplicationWidth() StackableViewController.populateView(self, withUIArray: items) { (item) -> UIEdgeInsets in return UIEdgeInsets(top: verticalSpace, From 8d2f5e1de05f7ce376b677e26888b703cc2e9974 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 7 May 2019 12:16:45 -0400 Subject: [PATCH 05/45] MFTextField with forDropDownWithBothDelegates --- MVMCoreUI/Atoms/Views/MFView+FormValidation.swift | 13 +++++++++++++ MVMCoreUI/Atoms/Views/MFView.h | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/MFView+FormValidation.swift b/MVMCoreUI/Atoms/Views/MFView+FormValidation.swift index 9e4fe2a9..66d3d27a 100644 --- a/MVMCoreUI/Atoms/Views/MFView+FormValidation.swift +++ b/MVMCoreUI/Atoms/Views/MFView+FormValidation.swift @@ -9,8 +9,21 @@ import Foundation +fileprivate struct FormValidatorHolder { + static var formValidator: FormValidator? +} + extension FormValidationProtocol where Self: MFView { + var formValidator: FormValidator? { + get { + return FormValidatorHolder.formValidator + } + set(newValue) { + FormValidatorHolder.formValidator = newValue + } + } + func setupFormValidation(delegateObject: DelegateObject?) { if let delegateObject = delegateObject as? MVMCoreUIDelegateObject, let formValidationProtocol = delegateObject.formValidationProtocol { diff --git a/MVMCoreUI/Atoms/Views/MFView.h b/MVMCoreUI/Atoms/Views/MFView.h index 079e3c3a..243408ac 100644 --- a/MVMCoreUI/Atoms/Views/MFView.h +++ b/MVMCoreUI/Atoms/Views/MFView.h @@ -14,7 +14,7 @@ @interface MFView : UIView -@property (nullable, strong, nonatomic) FormValidator *formValidator; +//@property (nullable, strong, nonatomic) FormValidator *formValidator; @property (nullable, nonatomic, strong) NSDictionary *json; // Called in the initialization functions. Can setup ui here. From e90b4c299e84ce13a69fc77d4e69ad027b55fa09 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 13 May 2019 13:42:18 -0400 Subject: [PATCH 06/45] enhancements --- MVMCoreUI.xcodeproj/project.pbxproj | 6 +--- .../Atoms/Views/MFView+FormValidation.swift | 34 ------------------- MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m | 9 ++--- .../FormValidator+FormParams.swift | 9 ++--- MVMCoreUI/FormUIHelpers/FormValidator.swift | 18 +++++----- MVMCoreUI/Molecules/RadioButton.swift | 1 - MVMCoreUI/Molecules/RadioButtonList.swift | 10 ++++-- .../MVMCoreUIMoleculeMappingObject.m | 3 +- 8 files changed, 24 insertions(+), 66 deletions(-) delete mode 100644 MVMCoreUI/Atoms/Views/MFView+FormValidation.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 5409c5a9..ddf5c036 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 01004F3022721C3800991ECC /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01004F2F22721C3800991ECC /* RadioButton.swift */; }; - 01004F322273972F00991ECC /* MFView+FormValidation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01004F312273972F00991ECC /* MFView+FormValidation.swift */; }; 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618A224BBE7700E1557D /* FormValidator.swift */; }; 0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */; }; 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */; }; @@ -171,7 +170,6 @@ /* Begin PBXFileReference section */ 01004F2F22721C3800991ECC /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = ""; }; - 01004F312273972F00991ECC /* MFView+FormValidation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFView+FormValidation.swift"; sourceTree = ""; }; 0105618A224BBE7700E1557D /* FormValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidator.swift; sourceTree = ""; }; 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = ""; }; 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+FormParams.swift"; sourceTree = ""; }; @@ -325,10 +323,10 @@ D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = ""; }; D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = ""; }; D2E1FADA2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MVMCoreUIDelegateObject.swift; sourceTree = ""; }; - DB891E822253FA8500022516 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeTableViewCell.swift; sourceTree = ""; }; D2E1FADE2268B8E700AEFD8C /* ThreeLayerTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreeLayerTableViewController.swift; sourceTree = ""; }; D2E1FAE02268E81D00AEFD8C /* MoleculeListTemplate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeListTemplate.swift; sourceTree = ""; }; + DB891E822253FA8500022516 /* Label.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; DBC4391622442196001AB423 /* CaretView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretView.swift; sourceTree = ""; }; DBC4391722442197001AB423 /* DashLine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DashLine.swift; sourceTree = ""; }; DBC4391A224421A0001AB423 /* CaretButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CaretButton.swift; sourceTree = ""; }; @@ -578,7 +576,6 @@ DBC4391622442196001AB423 /* CaretView.swift */, DBC4391722442197001AB423 /* DashLine.swift */, D29DF17E21E69E2E003B2FB9 /* MFView.h */, - 01004F312273972F00991ECC /* MFView+FormValidation.swift */, D29DF17F21E69E2E003B2FB9 /* MFView.m */, D29DF31E21ED0CBA003B2FB9 /* LabelView.h */, D29DF31F21ED0CBA003B2FB9 /* LabelView.m */, @@ -899,7 +896,6 @@ D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */, 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */, D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, - 01004F322273972F00991ECC /* MFView+FormValidation.swift in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, D29DF24D21E6A177003B2FB9 /* MFTextField.m in Sources */, D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */, diff --git a/MVMCoreUI/Atoms/Views/MFView+FormValidation.swift b/MVMCoreUI/Atoms/Views/MFView+FormValidation.swift deleted file mode 100644 index 66d3d27a..00000000 --- a/MVMCoreUI/Atoms/Views/MFView+FormValidation.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// MFView+FormValidation.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 4/26/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - - -fileprivate struct FormValidatorHolder { - static var formValidator: FormValidator? -} - -extension FormValidationProtocol where Self: MFView { - - var formValidator: FormValidator? { - get { - return FormValidatorHolder.formValidator - } - set(newValue) { - FormValidatorHolder.formValidator = newValue - } - } - - func setupFormValidation(delegateObject: DelegateObject?) { - if let delegateObject = delegateObject as? MVMCoreUIDelegateObject, - let formValidationProtocol = delegateObject.formValidationProtocol { - FormValidator.setupValidation(molecule: self, delegate:formValidationProtocol) - formValidator = FormValidator.getFormValidatorFor(delegate:formValidationProtocol) - } - } -} diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m index 0158beb1..757d1b50 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -42,7 +42,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; @property (nonatomic) BOOL isRequired; @property (nullable, strong, nonatomic) NSString *fieldKey; -@property (nullable, strong, nonatomic) DelegateObject *delegate; +@property (nullable, strong, nonatomic) MVMCoreUIDelegateObject *delegateObject; @end @@ -61,7 +61,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; - (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { [FormValidator setupValidationWithMolecule:self delegate:((MVMCoreUIDelegateObject *)delegateObject).formValidationProtocol]; - self.delegate = delegateObject; + self.delegateObject = (MVMCoreUIDelegateObject *) delegateObject; self.fieldKey = [json stringForKey:KeyFieldKey]; self.isRequired = [json boolForKey:KeyRequired]; @@ -342,10 +342,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; [self.checkMark updateCheckSelected:NO animated:animated]; } - if (self.delegate && [self.delegate respondsToSelector:@selector(formValidationProtocol)] && [[self.delegate performSelector:@selector(formValidationProtocol)] respondsToSelector:@selector(formValidatorModel)]) { - FormValidator *formValidator = [[self.delegate performSelector:@selector(formValidationProtocol)] performSelector:@selector(formValidatorModel)]; - [formValidator enableByValidation]; - } + [FormValidator enableByValidationWithDelegate:((MVMCoreUIDelegateObject *)self.delegateObject).formValidationProtocol]; } - (void)setColor:(nullable UIColor *)color forState:(UIControlState)state { diff --git a/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift b/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift index 17da0e72..bb9885ab 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift @@ -17,12 +17,9 @@ import Foundation var extraParam: [String: Any] = [:] MVMCoreDispatchUtility.performSyncBlock(onMainThread: { for molecule in self.molecules { - if let formFieldName = molecule.formFieldName, - let formFieldValue = molecule.formFieldValue, - let fieldName = formFieldName(), - let fieldValue = formFieldValue() { - - extraParam[fieldName] = fieldValue + if let formFieldName = molecule.formFieldName?(), + let formFieldValue = molecule.formFieldValue?() { + extraParam[formFieldName] = formFieldValue } } }) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 5eb28904..07f4a583 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -19,19 +19,19 @@ import UIKit molecules.append(molecule) } - public static func getFormValidatorFor(delegate: FormValidationProtocol) -> FormValidator? { - if let delegateFormValidatorModel = delegate.formValidatorModel, - let validator = delegateFormValidatorModel() { - return validator - } else { - return nil + public static func enableByValidationWith(delegate: FormValidationProtocol?) { + if let delegate = delegate { + let formValidator = FormValidator.getFormValidatorFor(delegate: delegate) + formValidator?.enableByValidation() } } + public static func getFormValidatorFor(delegate: FormValidationProtocol) -> FormValidator? { + return delegate.formValidatorModel?() + } + public static func setupValidation(molecule: UIView & FormValidationProtocol, delegate: FormValidationProtocol?) { - if let delegateFormValidatorModel = delegate?.formValidatorModel, - let validator = delegateFormValidatorModel() { - + if let validator = delegate?.formValidatorModel?() { validator.delegate = delegate validator.insertMolecule(molecule) } diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index d5cc4d87..f55ef302 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -81,7 +81,6 @@ import UIKit } else { radioButton.isSelected = !radioButton.isSelected } - formValidator?.enableByValidation() } func getColor( _ json: [AnyHashable: Any], _ key: String) -> UIColor? { diff --git a/MVMCoreUI/Molecules/RadioButtonList.swift b/MVMCoreUI/Molecules/RadioButtonList.swift index 6a1083fd..1b597214 100644 --- a/MVMCoreUI/Molecules/RadioButtonList.swift +++ b/MVMCoreUI/Molecules/RadioButtonList.swift @@ -17,6 +17,8 @@ import UIKit var selectedRadioButton: RadioButton? var selectedValue: String? + var delegateObject:MVMCoreUIDelegateObject? + // MARK: - Inits public init() { @@ -35,7 +37,8 @@ import UIKit selectedRadioButton?.radioButton.isSelected = false selectedRadioButton = radioButton selectedRadioButton?.radioButton.isSelected = true - formValidator?.enableByValidation() + + FormValidator.enableByValidationWith(delegate: self.delegateObject?.formValidationProtocol) } open override func setupView() { @@ -56,7 +59,7 @@ extension RadioButtonList: FormValidationProtocol { // The Field name key value pair for sending to server @objc public func formFieldName() -> String? { - return selectedRadioButton?.formFieldName() + return json?.optionalStringForKey("fieldKey") } // The Feild value key value paid for sending to server @@ -78,7 +81,8 @@ extension RadioButtonList { return } - setupFormValidation(delegateObject: delegateObject) + self.delegateObject = delegateObject + FormValidator.setupValidation(molecule: self, delegate: delegateObject.formValidationProtocol) StackableViewController.remove(self.subviews) diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index f8d97233..0a37d62e 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -33,8 +33,7 @@ @"caretView": CaretView.class, @"caretButton": CaretButton.class, @"textField" : MFTextField.class, - @"radioButtonList": RadioButtonList.class, - @"radioButton": RadioButton.class, + @"radioButton": RadioButtonList.class, @"checkbox" : MVMCoreUICheckBox.class } mutableCopy]; }); From 45dde90fdcef4340a1ceadc0f6d492cbbc8478c6 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 14 May 2019 09:52:52 -0400 Subject: [PATCH 07/45] review --- MVMCoreUI/Atoms/Views/MFView.h | 3 --- MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m | 6 +++++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MFView.h b/MVMCoreUI/Atoms/Views/MFView.h index 243408ac..5e32ff0a 100644 --- a/MVMCoreUI/Atoms/Views/MFView.h +++ b/MVMCoreUI/Atoms/Views/MFView.h @@ -10,11 +10,8 @@ #import @import MVMCore.MVMCoreViewProtocol; -@class FormValidator; - @interface MFView : UIView -//@property (nullable, strong, nonatomic) FormValidator *formValidator; @property (nullable, nonatomic, strong) NSDictionary *json; // Called in the initialization functions. Can setup ui here. diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m index ff46aa6a..76f2d0f6 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -60,7 +60,11 @@ static const CGFloat CheckBoxHeightWidth = 18.0; - (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { - [FormValidator setupValidationWithMolecule:self delegate:((MVMCoreUIDelegateObject *)delegateObject).formValidationProtocol]; + if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) { + [FormValidator setupValidationWithMolecule:self delegate:((MVMCoreUIDelegateObject *)delegateObject).formValidationProtocol]; + } + + self.delegate = delegateObject; self.fieldKey = [json stringForKey:KeyFieldKey]; self.isRequired = [json boolForKey:KeyRequired]; From ee09cfa2784e10b19a14f10f372b1f6aa0740eac Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 14 May 2019 11:04:33 -0400 Subject: [PATCH 08/45] conflicts --- MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m index 48a46ef6..cb6f7eaf 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -60,17 +60,11 @@ static const CGFloat CheckBoxHeightWidth = 18.0; - (void)setWithJSON:(NSDictionary *)json delegateObject:(DelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { -<<<<<<< HEAD if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) { [FormValidator setupValidationWithMolecule:self delegate:((MVMCoreUIDelegateObject *)delegateObject).formValidationProtocol]; } - - self.delegate = delegateObject; -======= - [FormValidator setupValidationWithMolecule:self delegate:((MVMCoreUIDelegateObject *)delegateObject).formValidationProtocol]; self.delegateObject = (MVMCoreUIDelegateObject *) delegateObject; ->>>>>>> e90b4c299e84ce13a69fc77d4e69ad027b55fa09 self.fieldKey = [json stringForKey:KeyFieldKey]; self.isRequired = [json boolForKey:KeyRequired]; From 132b810a664e899be27b60a74edeec699142815f Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 14 May 2019 21:52:32 -0400 Subject: [PATCH 09/45] refactoring --- MVMCoreUI.xcodeproj/project.pbxproj | 8 +- MVMCoreUI/FormUIHelpers/FormValidator.swift | 8 +- MVMCoreUI/Molecules/RadioButton.swift | 89 +++++++++++++------ MVMCoreUI/Molecules/RadioButtonModel.swift | 57 ++++++++++++ .../MVMCoreUIMoleculeMappingObject.m | 2 +- 5 files changed, 128 insertions(+), 36 deletions(-) create mode 100644 MVMCoreUI/Molecules/RadioButtonModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index ddf5c036..e2b1e234 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -11,7 +11,7 @@ 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618A224BBE7700E1557D /* FormValidator.swift */; }; 0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */; }; 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */; }; - 01157B94225D376D00F15D92 /* RadioButtonList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01157B93225D376D00F15D92 /* RadioButtonList.swift */; }; + 0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */; }; 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198F79E225679870066C936 /* FormValidationProtocol.swift */; }; 0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 0198F7A02256A80A0066C936 /* MFRadioButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0198F7A22256A80A0066C936 /* MFRadioButton.m */; }; @@ -173,7 +173,7 @@ 0105618A224BBE7700E1557D /* FormValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidator.swift; sourceTree = ""; }; 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = ""; }; 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+FormParams.swift"; sourceTree = ""; }; - 01157B93225D376D00F15D92 /* RadioButtonList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonList.swift; sourceTree = ""; }; + 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonModel.swift; sourceTree = ""; }; 0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = ""; }; 0198F7A02256A80A0066C936 /* MFRadioButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFRadioButton.h; sourceTree = ""; }; 0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = ""; }; @@ -451,9 +451,9 @@ D2A5145C2211D22A00345BFB /* MVMCoreUIMoleculeViewProtocol.h */, D2A5145E2211DDC100345BFB /* MoleculeStackView.swift */, D274CA322236A78900B01B62 /* StandardFooterView.swift */, - 01157B93225D376D00F15D92 /* RadioButtonList.swift */, 01004F2F22721C3800991ECC /* RadioButton.swift */, D2E1FADC2268B25E00AEFD8C /* MoleculeTableViewCell.swift */, + 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */, ); path = Molecules; sourceTree = ""; @@ -879,6 +879,7 @@ D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, + 0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */, D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, 01004F3022721C3800991ECC /* RadioButton.swift in Sources */, @@ -912,7 +913,6 @@ 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */, D2E1FADD2268B25E00AEFD8C /* MoleculeTableViewCell.swift in Sources */, D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */, - 01157B94225D376D00F15D92 /* RadioButtonList.swift in Sources */, D29DF18121E69E50003B2FB9 /* MFView.m in Sources */, D29DF18321E69E54003B2FB9 /* SeparatorView.m in Sources */, D29DF17A21E69E1F003B2FB9 /* MFCustomButton.m in Sources */, diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 07f4a583..af40b2de 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -12,10 +12,11 @@ import UIKit @objcMembers public class FormValidator: NSObject { var delegate: FormValidationProtocol? - var molecules: [UIView & FormValidationProtocol] = [] + var molecules: [FormValidationProtocol] = [] var extraValidationBlock: (() -> Bool)? + var radioButtonsModelByGroup: [String: RadioButtonModel] = [:] - public func insertMolecule(_ molecule: UIView & FormValidationProtocol) { + public func insertMolecule(_ molecule: FormValidationProtocol) { molecules.append(molecule) } @@ -30,7 +31,7 @@ import UIKit return delegate.formValidatorModel?() } - public static func setupValidation(molecule: UIView & FormValidationProtocol, delegate: FormValidationProtocol?) { + public static func setupValidation(molecule: FormValidationProtocol, delegate: FormValidationProtocol?) { if let validator = delegate?.formValidatorModel?() { validator.delegate = delegate validator.insertMolecule(molecule) @@ -52,3 +53,4 @@ import UIKit } } } + diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index f55ef302..c814de13 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -12,10 +12,16 @@ import UIKit @objcMembers open class RadioButton: ViewConstrainingView { let radioButton = MFRadioButton() - let label = Label() - var target: RadioButtonListProtocol? + var delegateObject:MVMCoreUIDelegateObject? var dummyButton: MFCustomButton? - + let label = Label() + + var groupName: String? + var fieldKey: String? + var formValue: Bool? + var isRequired: Bool = false + var radioButtonModel: RadioButtonModel? + // MARK: - Inits public init() { super.init(frame: .zero) @@ -29,11 +35,6 @@ import UIKit super.init(coder: aDecoder) } - public init(target: RadioButtonListProtocol) { - super.init(frame: .zero) - self.target = target - } - open override func setupView() { super.setupView() guard subviews.count == 0 else { @@ -43,18 +44,26 @@ import UIKit translatesAutoresizingMaskIntoConstraints = false radioButton.translatesAutoresizingMaskIntoConstraints = false addSubview(radioButton) - addSubview(label) radioButton.leftAnchor.constraint(equalTo: leftAnchor, constant: 0).isActive = true radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true radioButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true - - label.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingTwo).isActive = true - label.rightAnchor.constraint(equalTo: rightAnchor, constant: 0).isActive = true - label.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true - label.bottomAnchor.constraint(greaterThanOrEqualTo: bottomAnchor, constant: PaddingOne).isActive = true - label.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + + if let rightView = createRightView() { + addSubview(rightView) + rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingTwo).isActive = true + rightView.rightAnchor.constraint(equalTo: rightAnchor, constant: 0).isActive = true + rightView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true + rightView.bottomAnchor.constraint(greaterThanOrEqualTo: bottomAnchor, constant: PaddingOne).isActive = true + rightView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + } + addActionHandler() + } + + func createRightView() -> ViewConstrainingView? { + let rightView = ViewConstrainingView(constrainingView: label) + return rightView } func addActionHandler() { @@ -76,19 +85,12 @@ import UIKit } func tapAction() { - if let target = target { - target.selected?(self) + if let radioButtonModel = radioButtonModel { + radioButtonModel.selected(self) } else { radioButton.isSelected = !radioButton.isSelected } - } - - func getColor( _ json: [AnyHashable: Any], _ key: String) -> UIColor? { - if let colorHex = json.optionalStringForKey(key) { - return UIColor.mfGet(forHex: colorHex) - } else { - return nil - } + FormValidator.enableByValidationWith(delegate: self.delegateObject?.formValidationProtocol) } } @@ -102,11 +104,27 @@ extension RadioButton { guard let jsonDictionary = json else { return } + groupName = jsonDictionary.optionalStringForKey("groupName") + fieldKey = jsonDictionary.optionalStringForKey("fieldKey") + isRequired = jsonDictionary.boolForKey("required") + self.delegateObject = delegateObject as? MVMCoreUIDelegateObject + + radioButtonModel = RadioButtonModel.setupForRadioButtonGroup(radioButton: self, + formValidator: self.delegateObject?.formValidationProtocol?.formValidatorModel?()) + + /* If the radio button has a group, it will have RadioButtonModel. + In this case the RadioButtonModel should be the validator + */ + if let radioButtonModel = radioButtonModel { + FormValidator.setupValidation(molecule: radioButtonModel, delegate: self.delegateObject?.formValidationProtocol) + } else { + FormValidator.setupValidation(molecule: self, delegate: self.delegateObject?.formValidationProtocol) + } + label.setWithJSON(jsonDictionary.optionalDictionaryForKey(KeyLabel), delegateObject: delegateObject, additionalData: additionalData) - addActionHandler() } open override func needsToBeConstrained() -> Bool { @@ -118,15 +136,30 @@ extension RadioButton { } } + // MARK: - FormValidationProtocol extension RadioButton: FormValidationProtocol { + // Used to check the validity of the field, to enable/disable the primary button. + @objc public func isValidField() -> Bool { + if isRequired == false { + return true + } + return radioButtonModel?.isValidField() ?? false + } + // The Field name key value pair for sending to server @objc public func formFieldName() -> String? { + if let radioButtonModel = radioButtonModel { + return radioButtonModel.formFieldName() + } return json?.optionalStringForKey("fieldKey") } - // The Field value key value paid for sending to server + // The Feild value key value paid for sending to server @objc public func formFieldValue() -> Any? { - return json?.optionalStringForKey(KeyValue) + if let radioButtonModel = radioButtonModel { + return radioButtonModel.formFieldValue() + } + return radioButton.isSelected } } diff --git a/MVMCoreUI/Molecules/RadioButtonModel.swift b/MVMCoreUI/Molecules/RadioButtonModel.swift new file mode 100644 index 00000000..fbbb1a60 --- /dev/null +++ b/MVMCoreUI/Molecules/RadioButtonModel.swift @@ -0,0 +1,57 @@ +// +// RadioButtonModel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 5/14/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import Foundation +import UIKit + +@objcMembers public class RadioButtonModel: NSObject { + + private var selectedRadioButton: RadioButton? + private var radioButtons: [RadioButton] = [] + + public static func setupForRadioButtonGroup(radioButton: RadioButton, formValidator: FormValidator?) -> RadioButtonModel? { + + guard let groupName = radioButton.groupName, + let formValidator = formValidator else { + return nil + } + + let radioButtonModel = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonModel() + formValidator.radioButtonsModelByGroup[groupName] = radioButtonModel + radioButtonModel.radioButtons.append(radioButton) + + return radioButtonModel + } + + public func selected(_ radioButton: RadioButton) { + selectedRadioButton?.radioButton.isSelected = false + selectedRadioButton = radioButton + selectedRadioButton?.radioButton.isSelected = true + } +} + +// MARK: - FormValidationProtocol +extension RadioButtonModel: FormValidationProtocol { + // Used to check the validity of the field, to enable/disable the primary button. + @objc public func isValidField() -> Bool { + if selectedRadioButton != nil { + return true + } + return false + } + + // The Field name key value pair for sending to server + @objc public func formFieldName() -> String? { + return selectedRadioButton?.fieldKey + } + + // The Feild value key value paid for sending to server + @objc public func formFieldValue() -> Any? { + return selectedRadioButton != nil ? true : false + } +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 0a37d62e..d6e7d9f2 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -33,7 +33,7 @@ @"caretView": CaretView.class, @"caretButton": CaretButton.class, @"textField" : MFTextField.class, - @"radioButton": RadioButtonList.class, + @"radioButton": RadioButton.class, @"checkbox" : MVMCoreUICheckBox.class } mutableCopy]; }); From 6828f833e723b928835fd3d0c12a36f4dec4f8fb Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 31 May 2019 17:29:32 -0400 Subject: [PATCH 10/45] code review --- MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m | 8 +++--- MVMCoreUI/Molecules/RadioButton.swift | 29 +++++++++------------- MVMCoreUI/Molecules/RadioButtonModel.swift | 13 ++-------- MVMCoreUI/Styles/MFStyler.h | 3 +++ MVMCoreUI/Styles/MFStyler.m | 1 + 5 files changed, 21 insertions(+), 33 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m index cf608538..9bd8eaee 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -60,11 +60,9 @@ static const CGFloat CheckBoxHeightWidth = 18.0; - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { - if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) { - [FormValidator setupValidationWithMolecule:self delegate:((MVMCoreUIDelegateObject *)delegateObject).formValidationProtocol]; - } + [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; - self.delegateObject = (MVMCoreUIDelegateObject *) delegateObject; + self.delegateObject = delegateObject; self.fieldKey = [json stringForKey:KeyFieldKey]; self.isRequired = [json boolForKey:KeyRequired]; @@ -345,7 +343,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; [self.checkMark updateCheckSelected:NO animated:animated]; } - [FormValidator enableByValidationWithDelegate:((MVMCoreUIDelegateObject *)self.delegateObject).formValidationProtocol]; + [FormValidator enableByValidationWithDelegate:self.delegateObject.formValidationProtocol]; } - (void)setColor:(nullable UIColor *)color forState:(UIControlState)state { diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index c814de13..ae2f7d52 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -12,7 +12,7 @@ import UIKit @objcMembers open class RadioButton: ViewConstrainingView { let radioButton = MFRadioButton() - var delegateObject:MVMCoreUIDelegateObject? + var delegateObject: MVMCoreUIDelegateObject? var dummyButton: MFCustomButton? let label = Label() @@ -52,13 +52,14 @@ import UIKit if let rightView = createRightView() { addSubview(rightView) - rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingTwo).isActive = true + rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true rightView.rightAnchor.constraint(equalTo: rightAnchor, constant: 0).isActive = true rightView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true rightView.bottomAnchor.constraint(greaterThanOrEqualTo: bottomAnchor, constant: PaddingOne).isActive = true rightView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true } addActionHandler() + addActionHandler() } func createRightView() -> ViewConstrainingView? { @@ -68,7 +69,7 @@ import UIKit func addActionHandler() { - if dummyButton != nil { + guard dummyButton == nil else { return } @@ -97,7 +98,8 @@ import UIKit // MARK: - MVMCoreUIMoleculeViewProtocol extension RadioButton { - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { + @objc open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) // Configure class properties with JSON values @@ -106,9 +108,8 @@ extension RadioButton { } groupName = jsonDictionary.optionalStringForKey("groupName") fieldKey = jsonDictionary.optionalStringForKey("fieldKey") - isRequired = jsonDictionary.boolForKey("required") - - self.delegateObject = delegateObject as? MVMCoreUIDelegateObject + isRequired = jsonDictionary.boolForKey("required") + self.delegateObject = delegateObject radioButtonModel = RadioButtonModel.setupForRadioButtonGroup(radioButton: self, formValidator: self.delegateObject?.formValidationProtocol?.formValidatorModel?()) @@ -130,7 +131,7 @@ extension RadioButton { open override func needsToBeConstrained() -> Bool { return true } - + open override func moleculeAlignment() -> UIStackView.Alignment { return UIStackView.Alignment.leading; } @@ -141,7 +142,7 @@ extension RadioButton { extension RadioButton: FormValidationProtocol { // Used to check the validity of the field, to enable/disable the primary button. @objc public func isValidField() -> Bool { - if isRequired == false { + guard isRequired else { return true } return radioButtonModel?.isValidField() ?? false @@ -149,17 +150,11 @@ extension RadioButton: FormValidationProtocol { // The Field name key value pair for sending to server @objc public func formFieldName() -> String? { - if let radioButtonModel = radioButtonModel { - return radioButtonModel.formFieldName() - } - return json?.optionalStringForKey("fieldKey") + return radioButtonModel?.formFieldName() ?? json?.optionalStringForKey("fieldKey") } // The Feild value key value paid for sending to server @objc public func formFieldValue() -> Any? { - if let radioButtonModel = radioButtonModel { - return radioButtonModel.formFieldValue() - } - return radioButton.isSelected + return radioButtonModel?.formFieldValue() ?? radioButton.isSelected } } diff --git a/MVMCoreUI/Molecules/RadioButtonModel.swift b/MVMCoreUI/Molecules/RadioButtonModel.swift index fbbb1a60..096cb80a 100644 --- a/MVMCoreUI/Molecules/RadioButtonModel.swift +++ b/MVMCoreUI/Molecules/RadioButtonModel.swift @@ -12,10 +12,8 @@ import UIKit @objcMembers public class RadioButtonModel: NSObject { private var selectedRadioButton: RadioButton? - private var radioButtons: [RadioButton] = [] public static func setupForRadioButtonGroup(radioButton: RadioButton, formValidator: FormValidator?) -> RadioButtonModel? { - guard let groupName = radioButton.groupName, let formValidator = formValidator else { return nil @@ -23,8 +21,6 @@ import UIKit let radioButtonModel = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonModel() formValidator.radioButtonsModelByGroup[groupName] = radioButtonModel - radioButtonModel.radioButtons.append(radioButton) - return radioButtonModel } @@ -39,17 +35,12 @@ import UIKit extension RadioButtonModel: FormValidationProtocol { // Used to check the validity of the field, to enable/disable the primary button. @objc public func isValidField() -> Bool { - if selectedRadioButton != nil { - return true - } - return false + return selectedRadioButton != nil ? true : false } - - // The Field name key value pair for sending to server + // Name of the field to send to server @objc public func formFieldName() -> String? { return selectedRadioButton?.fieldKey } - // The Feild value key value paid for sending to server @objc public func formFieldValue() -> Any? { return selectedRadioButton != nil ? true : false diff --git a/MVMCoreUI/Styles/MFStyler.h b/MVMCoreUI/Styles/MFStyler.h index 0a52c468..83fd0271 100644 --- a/MVMCoreUI/Styles/MFStyler.h +++ b/MVMCoreUI/Styles/MFStyler.h @@ -36,6 +36,9 @@ extern CGFloat const PaddingVerticalWhiteGrayView; extern CGFloat const PaddingVerticalHeadlineAlternate; extern CGFloat const PaddingPrimaryButtonTop; +// +extern CGFloat const PaddingHorizontalBetweenRelatedItems; + // These are based on the multiple of 6 rule extern CGFloat const PaddingOne; extern CGFloat const PaddingTwo; diff --git a/MVMCoreUI/Styles/MFStyler.m b/MVMCoreUI/Styles/MFStyler.m index 261181b1..d0d436a2 100644 --- a/MVMCoreUI/Styles/MFStyler.m +++ b/MVMCoreUI/Styles/MFStyler.m @@ -25,6 +25,7 @@ CGFloat const PaddingVerticalWhiteGrayView = 72; CGFloat const PaddingVerticalHeadlineAlternate = 48; CGFloat const PaddingPrimaryButtonTop = 36; +CGFloat const PaddingHorizontalBetweenRelatedItems = 16; CGFloat const PaddingOne = 6; CGFloat const PaddingTwo = 12; CGFloat const PaddingThree = 18; From b72f9a2b71186e206df6dfa64d74b9984569b136 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 4 Jun 2019 09:43:16 -0400 Subject: [PATCH 11/45] code review --- MVMCoreUI/Molecules/RadioButton.swift | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index ae2f7d52..90c4fd5e 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -44,8 +44,9 @@ import UIKit translatesAutoresizingMaskIntoConstraints = false radioButton.translatesAutoresizingMaskIntoConstraints = false addSubview(radioButton) - - radioButton.leftAnchor.constraint(equalTo: leftAnchor, constant: 0).isActive = true + + + radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true radioButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true @@ -53,7 +54,7 @@ import UIKit if let rightView = createRightView() { addSubview(rightView) rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true - rightView.rightAnchor.constraint(equalTo: rightAnchor, constant: 0).isActive = true + rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true rightView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true rightView.bottomAnchor.constraint(greaterThanOrEqualTo: bottomAnchor, constant: PaddingOne).isActive = true rightView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true @@ -127,14 +128,6 @@ extension RadioButton { delegateObject: delegateObject, additionalData: additionalData) } - - open override func needsToBeConstrained() -> Bool { - return true - } - - open override func moleculeAlignment() -> UIStackView.Alignment { - return UIStackView.Alignment.leading; - } } From 8eae881bf1539d972196cc15b55eeae86543cf22 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 24 Jun 2019 10:47:43 -0400 Subject: [PATCH 12/45] code review --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 2 +- MVMCoreUI/Molecules/RadioButton.swift | 48 ++++++-- MVMCoreUI/Molecules/RadioButtonList.swift | 113 ------------------ MVMCoreUI/Styles/MFStyler.h | 2 - .../Strings/en.lproj/Localizable.strings | 7 ++ .../Templates/MoleculeStackTemplate.swift | 16 +-- 6 files changed, 53 insertions(+), 135 deletions(-) delete mode 100644 MVMCoreUI/Molecules/RadioButtonList.swift diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index af40b2de..91928f3e 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -16,7 +16,7 @@ import UIKit var extraValidationBlock: (() -> Bool)? var radioButtonsModelByGroup: [String: RadioButtonModel] = [:] - public func insertMolecule(_ molecule: FormValidationProtocol) { + public func insertMolecule(_ molecule: FormValidationProtocol) { molecules.append(molecule) } diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index 90c4fd5e..ad9e72e7 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -45,22 +45,35 @@ import UIKit radioButton.translatesAutoresizingMaskIntoConstraints = false addSubview(radioButton) + isAccessibilityElement = true + accessibilityTraits = .none + accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true - radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true - bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true + var constraint = radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne) + constraint.priority = .defaultLow + constraint.isActive = true + + constraint = bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne) + constraint.priority = .defaultLow + constraint.isActive = true + radioButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true if let rightView = createRightView() { addSubview(rightView) rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true - rightView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true - rightView.bottomAnchor.constraint(greaterThanOrEqualTo: bottomAnchor, constant: PaddingOne).isActive = true - rightView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + + constraint = rightView.topAnchor.constraint(equalTo: topAnchor, constant: PaddingOne) + constraint.priority = .defaultHigh + constraint.isActive = true + + constraint = bottomAnchor.constraint(greaterThanOrEqualTo: rightView.bottomAnchor, constant: PaddingOne) + constraint.priority = .defaultHigh + constraint.isActive = true } addActionHandler() - addActionHandler() } func createRightView() -> ViewConstrainingView? { @@ -92,7 +105,8 @@ import UIKit } else { radioButton.isSelected = !radioButton.isSelected } - FormValidator.enableByValidationWith(delegate: self.delegateObject?.formValidationProtocol) + FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) + changeAccessibilityLabel() } } @@ -113,20 +127,21 @@ extension RadioButton { self.delegateObject = delegateObject radioButtonModel = RadioButtonModel.setupForRadioButtonGroup(radioButton: self, - formValidator: self.delegateObject?.formValidationProtocol?.formValidatorModel?()) + formValidator: delegateObject?.formValidationProtocol?.formValidatorModel?()) /* If the radio button has a group, it will have RadioButtonModel. In this case the RadioButtonModel should be the validator */ if let radioButtonModel = radioButtonModel { - FormValidator.setupValidation(molecule: radioButtonModel, delegate: self.delegateObject?.formValidationProtocol) + FormValidator.setupValidation(molecule: radioButtonModel, delegate: delegateObject?.formValidationProtocol) } else { - FormValidator.setupValidation(molecule: self, delegate: self.delegateObject?.formValidationProtocol) + FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) } label.setWithJSON(jsonDictionary.optionalDictionaryForKey(KeyLabel), delegateObject: delegateObject, additionalData: additionalData) + changeAccessibilityLabel() } } @@ -146,8 +161,19 @@ extension RadioButton: FormValidationProtocol { return radioButtonModel?.formFieldName() ?? json?.optionalStringForKey("fieldKey") } - // The Feild value key value paid for sending to server + // The Field value key value pair for sending to server @objc public func formFieldValue() -> Any? { return radioButtonModel?.formFieldValue() ?? radioButton.isSelected } } + +// MARK: Accessibility +extension RadioButton { + func changeAccessibilityLabel() { + let stateString = radioButton.isSelected ? "radio_selected_state" : "radio_not_selected_state" + let localizedStringState = MVMCoreUIUtility.hardcodedString(withKey: stateString) ?? "" + let accebilityString = (label.accessibilityLabel ?? (json?.optionalStringForKey("accessibilityText") ?? "")) + + (MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "") + localizedStringState + accessibilityLabel = accebilityString + } +} diff --git a/MVMCoreUI/Molecules/RadioButtonList.swift b/MVMCoreUI/Molecules/RadioButtonList.swift deleted file mode 100644 index 1b597214..00000000 --- a/MVMCoreUI/Molecules/RadioButtonList.swift +++ /dev/null @@ -1,113 +0,0 @@ -// -// RadioButton.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 4/9/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import UIKit - -@objc public protocol RadioButtonListProtocol: NSObjectProtocol { - - @objc optional func selected(_ radioButton: RadioButton) -} - -@objcMembers open class RadioButtonList: ViewConstrainingView, RadioButtonListProtocol { - - var selectedRadioButton: RadioButton? - var selectedValue: String? - var delegateObject:MVMCoreUIDelegateObject? - - - // MARK: - Inits - public init() { - super.init(frame: .zero) - } - - public override init(frame: CGRect) { - super.init(frame: frame) - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - - public func selected(_ radioButton: RadioButton) { - selectedRadioButton?.radioButton.isSelected = false - selectedRadioButton = radioButton - selectedRadioButton?.radioButton.isSelected = true - - FormValidator.enableByValidationWith(delegate: self.delegateObject?.formValidationProtocol) - } - - open override func setupView() { - super.setupView() - self.translatesAutoresizingMaskIntoConstraints = false - } -} - -// MARK: - FormValidationProtocol -extension RadioButtonList: FormValidationProtocol { - // Used to check the validity of the field, to enable/disable the primary button. - @objc public func isValidField() -> Bool { - if !(json?.boolForKey("required") ?? true) { - return true - } - return selectedRadioButton != nil - } - - // The Field name key value pair for sending to server - @objc public func formFieldName() -> String? { - return json?.optionalStringForKey("fieldKey") - } - - // The Feild value key value paid for sending to server - @objc public func formFieldValue() -> Any? { - return selectedRadioButton?.formFieldValue() - } -} - -// MARK: - MVMCoreUIMoleculeViewProtocol -extension RadioButtonList { - - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: DelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - - // Configure class properties with JSON values - guard let jsonDictionary = json, - let optionsList = jsonDictionary.optionalArrayForKey("optionsList") as? [[AnyHashable: Any]], - let delegateObject = delegateObject as? MVMCoreUIDelegateObject else { - return - } - - self.delegateObject = delegateObject - FormValidator.setupValidation(molecule: self, delegate: delegateObject.formValidationProtocol) - - StackableViewController.remove(self.subviews) - - var items:[UIView] = [] - for option in optionsList { - let radioButton = RadioButton(target: self) - radioButton.setWithJSON(option, delegateObject: delegateObject, additionalData: nil) - items.append(radioButton) - } - - let verticalSpace = MFStyler.defaultVerticalPaddingForApplicationWidth() - StackableViewController.populateView(self, - withUIArray: items) { (item) -> UIEdgeInsets in - return UIEdgeInsets(top: verticalSpace, - left: 0, - bottom: 0, - right: 0) - } - } - - open override func needsToBeConstrained() -> Bool { - return true - } - - open override func moleculeAlignment() -> UIStackView.Alignment { - return UIStackView.Alignment.leading; - } -} diff --git a/MVMCoreUI/Styles/MFStyler.h b/MVMCoreUI/Styles/MFStyler.h index 095426ad..f5632dca 100644 --- a/MVMCoreUI/Styles/MFStyler.h +++ b/MVMCoreUI/Styles/MFStyler.h @@ -35,8 +35,6 @@ extern CGFloat const PaddingHorizontalLarge; extern CGFloat const PaddingVerticalWhiteGrayView; extern CGFloat const PaddingVerticalHeadlineAlternate; extern CGFloat const PaddingPrimaryButtonTop; - -// extern CGFloat const PaddingHorizontalBetweenRelatedItems; // These are based on the multiple of 6 rule diff --git a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings index 96088cab..8bfb4511 100644 --- a/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/en.lproj/Localizable.strings @@ -35,6 +35,13 @@ "checkbox_checked_state" = "Checked"; "checkbox_unchecked_state" = "Unchecked"; "checkbox_desc_state" = "%@ CheckBox %@"; + +// Radio Button +"radio_action_hint" = "Double tap to select"; +"radio_selected_state" = "Selected"; +"radio_not_selected_state" = "Not Selected"; +"radio_desc_state" = "Option"; + // Switch "mfswitch_buttonlabel" = "Switch Button"; "AccOn" = "on"; diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 3f5e04da..1fb6e0c8 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -8,9 +8,9 @@ import UIKit -public class MoleculeStackTemplate: ThreeLayerViewController { +open class MoleculeStackTemplate: ThreeLayerViewController { - public override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { + open override func shouldFinishProcessingLoad(_ loadObject: MVMCoreLoadObject, error: AutoreleasingUnsafeMutablePointer) -> Bool { var shouldFinish = super.shouldFinishProcessingLoad(loadObject, error: error) if shouldFinish, let firstError = modulesNeeded().errors?.first { // Don't continue if there was an error loading needed modules. @@ -20,25 +20,25 @@ public class MoleculeStackTemplate: ThreeLayerViewController { return shouldFinish } - public override func spaceBetweenTopAndMiddle() -> CGFloat? { + open override func spaceBetweenTopAndMiddle() -> CGFloat? { return 0 } - public override func viewForTop() -> UIView? { + open override func viewForTop() -> UIView? { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return nil } return molecule } - public override func viewForMiddle() -> UIView? { + open override func viewForMiddle() -> UIView? { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack") else { return nil } return MoleculeStackView(withJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) } - override public func viewForBottom() -> UIView? { + override open func viewForBottom() -> UIView? { guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { return nil } @@ -46,14 +46,14 @@ public class MoleculeStackTemplate: ThreeLayerViewController { } // MARK: - cache handling - public override func pageTypesToListenFor() -> [Any]? { + open override func pageTypesToListenFor() -> [Any]? { guard let pageType = self.pageType else { return super.pageTypesToListenFor() } return [pageType] } - public override func modulesToListenFor() -> [Any]? { + open override func modulesToListenFor() -> [Any]? { // Get all of the molecules that need modules. return modulesNeeded().modules } From 73e6f7f513d15a648211e88ab9db09f50aa7b3d8 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 25 Jun 2019 09:20:27 -0400 Subject: [PATCH 13/45] spelling --- MVMCoreUI/Molecules/RadioButtonModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Molecules/RadioButtonModel.swift b/MVMCoreUI/Molecules/RadioButtonModel.swift index 096cb80a..2063fd83 100644 --- a/MVMCoreUI/Molecules/RadioButtonModel.swift +++ b/MVMCoreUI/Molecules/RadioButtonModel.swift @@ -41,7 +41,7 @@ extension RadioButtonModel: FormValidationProtocol { @objc public func formFieldName() -> String? { return selectedRadioButton?.fieldKey } - // The Feild value key value paid for sending to server + // The field value key value pair for sending to server @objc public func formFieldValue() -> Any? { return selectedRadioButton != nil ? true : false } From dcd782903eb1d305bbea9bdd3e45731ad79244b8 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 25 Jun 2019 09:49:05 -0400 Subject: [PATCH 14/45] constraints --- MVMCoreUI/Molecules/RadioButton.swift | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index ad9e72e7..0fc89c1b 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -50,14 +50,8 @@ import UIKit accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true - var constraint = radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne) - constraint.priority = .defaultLow - constraint.isActive = true - - constraint = bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne) - constraint.priority = .defaultLow - constraint.isActive = true - + radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true + bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true radioButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true if let rightView = createRightView() { @@ -65,11 +59,11 @@ import UIKit rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true - constraint = rightView.topAnchor.constraint(equalTo: topAnchor, constant: PaddingOne) + var constraint = rightView.topAnchor.constraint(equalTo: topAnchor, constant: PaddingOne) constraint.priority = .defaultHigh constraint.isActive = true - constraint = bottomAnchor.constraint(greaterThanOrEqualTo: rightView.bottomAnchor, constant: PaddingOne) + constraint = bottomAnchor.constraint(equalTo: rightView.bottomAnchor, constant: PaddingOne) constraint.priority = .defaultHigh constraint.isActive = true } From 6b71115eb03ce61cf1123cfa0e5bf4473884f77a Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 27 Aug 2019 20:25:07 -0400 Subject: [PATCH 15/45] fixes --- MVMCoreUI/Molecules/RadioButton.swift | 43 +++++----------------- MVMCoreUI/Molecules/RadioButtonModel.swift | 4 +- 2 files changed, 11 insertions(+), 36 deletions(-) diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index 0fc89c1b..acd5f016 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -16,12 +16,16 @@ import UIKit var dummyButton: MFCustomButton? let label = Label() - var groupName: String? var fieldKey: String? var formValue: Bool? var isRequired: Bool = false var radioButtonModel: RadioButtonModel? + lazy var groupName: String? = { + [unowned self] in + return json?.optionalStringForKey("groupName") ?? json?.optionalStringForKey("fieldKey") + }() + // MARK: - Inits public init() { super.init(frame: .zero) @@ -115,22 +119,15 @@ extension RadioButton { guard let jsonDictionary = json else { return } - groupName = jsonDictionary.optionalStringForKey("groupName") + fieldKey = jsonDictionary.optionalStringForKey("fieldKey") isRequired = jsonDictionary.boolForKey("required") self.delegateObject = delegateObject - radioButtonModel = RadioButtonModel.setupForRadioButtonGroup(radioButton: self, + let radioButtonModel = RadioButtonModel.setupForRadioButtonGroup(radioButton: self, formValidator: delegateObject?.formValidationProtocol?.formValidatorModel?()) - - /* If the radio button has a group, it will have RadioButtonModel. - In this case the RadioButtonModel should be the validator - */ - if let radioButtonModel = radioButtonModel { - FormValidator.setupValidation(molecule: radioButtonModel, delegate: delegateObject?.formValidationProtocol) - } else { - FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) - } + FormValidator.setupValidation(molecule: radioButtonModel, delegate: delegateObject?.formValidationProtocol) + self.radioButtonModel = radioButtonModel label.setWithJSON(jsonDictionary.optionalDictionaryForKey(KeyLabel), delegateObject: delegateObject, @@ -139,28 +136,6 @@ extension RadioButton { } } - -// MARK: - FormValidationProtocol -extension RadioButton: FormValidationProtocol { - // Used to check the validity of the field, to enable/disable the primary button. - @objc public func isValidField() -> Bool { - guard isRequired else { - return true - } - return radioButtonModel?.isValidField() ?? false - } - - // The Field name key value pair for sending to server - @objc public func formFieldName() -> String? { - return radioButtonModel?.formFieldName() ?? json?.optionalStringForKey("fieldKey") - } - - // The Field value key value pair for sending to server - @objc public func formFieldValue() -> Any? { - return radioButtonModel?.formFieldValue() ?? radioButton.isSelected - } -} - // MARK: Accessibility extension RadioButton { func changeAccessibilityLabel() { diff --git a/MVMCoreUI/Molecules/RadioButtonModel.swift b/MVMCoreUI/Molecules/RadioButtonModel.swift index 2063fd83..40238307 100644 --- a/MVMCoreUI/Molecules/RadioButtonModel.swift +++ b/MVMCoreUI/Molecules/RadioButtonModel.swift @@ -13,10 +13,10 @@ import UIKit private var selectedRadioButton: RadioButton? - public static func setupForRadioButtonGroup(radioButton: RadioButton, formValidator: FormValidator?) -> RadioButtonModel? { + public static func setupForRadioButtonGroup(radioButton: RadioButton, formValidator: FormValidator?) -> RadioButtonModel { guard let groupName = radioButton.groupName, let formValidator = formValidator else { - return nil + return RadioButtonModel() } let radioButtonModel = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonModel() From 096c95f6e048b9231d4b10c66acfda0be59a33cd Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 28 Aug 2019 12:16:07 -0400 Subject: [PATCH 16/45] Setting up new molecule. --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++ .../Atoms/Buttons/HeadlineBodyButton.swift | 57 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 MVMCoreUI/Atoms/Buttons/HeadlineBodyButton.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 22b92460..952f8826 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; }; + 0A804A3D2316CB79009A8656 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A804A3C2316CB79009A8656 /* HeadlineBodyButton.swift */; }; B8200E152280C4CF007245F4 /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E142280C4CF007245F4 /* ProgressBar.swift */; }; B8200E192281DC1A007245F4 /* CornerLabels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E182281DC1A007245F4 /* CornerLabels.swift */; }; D206997721FB8A0B00CAE0DE /* MVMCoreUINavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -197,6 +198,7 @@ 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = ""; }; 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = ""; }; 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = ""; }; + 0A804A3C2316CB79009A8656 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; B8200E142280C4CF007245F4 /* ProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = ""; }; B8200E182281DC1A007245F4 /* CornerLabels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerLabels.swift; sourceTree = ""; }; D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUINavigationController.h; sourceTree = ""; }; @@ -608,6 +610,7 @@ DBC4391A224421A0001AB423 /* CaretButton.swift */, D29DF25821E6A22D003B2FB9 /* MFButtonProtocol.h */, D29DF16B21E69E1F003B2FB9 /* ButtonDelegateProtocol.h */, + 0A804A3C2316CB79009A8656 /* HeadlineBodyButton.swift */, D29DF16A21E69E1F003B2FB9 /* MFCustomButton.h */, D29DF17021E69E1F003B2FB9 /* MFCustomButton.m */, D29DF16C21E69E1F003B2FB9 /* PrimaryButton.h */, @@ -953,6 +956,7 @@ 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */, D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, + 0A804A3D2316CB79009A8656 /* HeadlineBodyButton.swift in Sources */, D29DF24D21E6A177003B2FB9 /* MFTextField.m in Sources */, D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */, D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/HeadlineBodyButton.swift b/MVMCoreUI/Atoms/Buttons/HeadlineBodyButton.swift new file mode 100644 index 00000000..78b11f67 --- /dev/null +++ b/MVMCoreUI/Atoms/Buttons/HeadlineBodyButton.swift @@ -0,0 +1,57 @@ +// +// HeadlineBodyButton.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 8/28/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import Foundation + + +@objcMembers open class HeadlineBodyButton: ViewConstrainingView { + //------------------------------------------------------ + // MARK: - Outlets + //------------------------------------------------------ + + + + //------------------------------------------------------ + // MARK: - Properties + //------------------------------------------------------ + + + + //------------------------------------------------------ + // MARK: - Lifecycle + //------------------------------------------------------ + + open override func setupView() { + super.setupView() + guard subviews.count == 0 else { + return + } + + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + } + + //------------------------------------------------------ + // MARK: - JSON + //------------------------------------------------------ + + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + } + + open override func reset() { + + } + + open override func setAsMolecule() { + super.setAsMolecule() + } +} From 9ca6ba50da9a486988e5e17ad3dc530f014508b6 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 29 Aug 2019 10:50:38 -0400 Subject: [PATCH 17/45] New class. --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++++---- ...utton.swift => HeadlineBodyPrimaryButton.swift} | 14 +++++--------- 2 files changed, 9 insertions(+), 13 deletions(-) rename MVMCoreUI/Atoms/Buttons/{HeadlineBodyButton.swift => HeadlineBodyPrimaryButton.swift} (72%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 952f8826..16458819 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -19,7 +19,7 @@ 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; }; - 0A804A3D2316CB79009A8656 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A804A3C2316CB79009A8656 /* HeadlineBodyButton.swift */; }; + 0A804A3D2316CB79009A8656 /* HeadlineBodyPrimaryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A804A3C2316CB79009A8656 /* HeadlineBodyPrimaryButton.swift */; }; B8200E152280C4CF007245F4 /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E142280C4CF007245F4 /* ProgressBar.swift */; }; B8200E192281DC1A007245F4 /* CornerLabels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E182281DC1A007245F4 /* CornerLabels.swift */; }; D206997721FB8A0B00CAE0DE /* MVMCoreUINavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -198,7 +198,7 @@ 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = ""; }; 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = ""; }; 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = ""; }; - 0A804A3C2316CB79009A8656 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; + 0A804A3C2316CB79009A8656 /* HeadlineBodyPrimaryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyPrimaryButton.swift; sourceTree = ""; }; B8200E142280C4CF007245F4 /* ProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = ""; }; B8200E182281DC1A007245F4 /* CornerLabels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerLabels.swift; sourceTree = ""; }; D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUINavigationController.h; sourceTree = ""; }; @@ -610,7 +610,7 @@ DBC4391A224421A0001AB423 /* CaretButton.swift */, D29DF25821E6A22D003B2FB9 /* MFButtonProtocol.h */, D29DF16B21E69E1F003B2FB9 /* ButtonDelegateProtocol.h */, - 0A804A3C2316CB79009A8656 /* HeadlineBodyButton.swift */, + 0A804A3C2316CB79009A8656 /* HeadlineBodyPrimaryButton.swift */, D29DF16A21E69E1F003B2FB9 /* MFCustomButton.h */, D29DF17021E69E1F003B2FB9 /* MFCustomButton.m */, D29DF16C21E69E1F003B2FB9 /* PrimaryButton.h */, @@ -956,7 +956,7 @@ 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */, D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, - 0A804A3D2316CB79009A8656 /* HeadlineBodyButton.swift in Sources */, + 0A804A3D2316CB79009A8656 /* HeadlineBodyPrimaryButton.swift in Sources */, D29DF24D21E6A177003B2FB9 /* MFTextField.m in Sources */, D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */, D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/HeadlineBodyButton.swift b/MVMCoreUI/Atoms/Buttons/HeadlineBodyPrimaryButton.swift similarity index 72% rename from MVMCoreUI/Atoms/Buttons/HeadlineBodyButton.swift rename to MVMCoreUI/Atoms/Buttons/HeadlineBodyPrimaryButton.swift index 78b11f67..029a42c0 100644 --- a/MVMCoreUI/Atoms/Buttons/HeadlineBodyButton.swift +++ b/MVMCoreUI/Atoms/Buttons/HeadlineBodyPrimaryButton.swift @@ -1,5 +1,5 @@ // -// HeadlineBodyButton.swift +// HeadlineBodyPrimaryButton.swift // MVMCoreUI // // Created by Kevin Christiano on 8/28/19. @@ -9,7 +9,7 @@ import Foundation -@objcMembers open class HeadlineBodyButton: ViewConstrainingView { +@objcMembers open class HeadlineBodyPrimaryButton: ViewConstrainingView { //------------------------------------------------------ // MARK: - Outlets //------------------------------------------------------ @@ -28,9 +28,8 @@ import Foundation open override func setupView() { super.setupView() - guard subviews.count == 0 else { - return - } + + guard subviews.count == 0 else { return } } @@ -42,10 +41,7 @@ import Foundation // MARK: - JSON //------------------------------------------------------ - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - - } + open override func reset() { From 062edc5d4114ddde718107674c6c9155642f03fa Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 30 Aug 2019 15:33:05 -0400 Subject: [PATCH 18/45] refactoring for validation based on group --- MVMCoreUI/Atoms/Buttons/PrimaryButton.m | 10 ++++-- MVMCoreUI/Atoms/TextFields/MFTextField.h | 7 ++-- MVMCoreUI/Atoms/TextFields/MFTextField.m | 32 ++++++++--------- MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m | 2 +- .../FormValidationProtocol.swift | 24 +++++++++---- .../FormValidator+FormParams.swift | 6 ++-- MVMCoreUI/FormUIHelpers/FormValidator.swift | 35 +++++++++++++------ MVMCoreUI/Molecules/RadioButton.swift | 23 ++++++++++-- MVMCoreUI/Molecules/RadioButtonModel.swift | 10 ++++-- MVMCoreUI/Molecules/Switch.swift | 6 +++- MVMCoreUI/Molecules/SwitchLineItem.swift | 21 ++++++++++- 11 files changed, 124 insertions(+), 52 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m index 57470bf9..fa719012 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m @@ -17,9 +17,10 @@ @import MVMCore.MVMCoreGetterUtility; @import MVMCore.NSDictionary_MFConvenience; -@interface PrimaryButton() +@interface PrimaryButton() @property (nonatomic) BOOL validationRequired; +@property (nonatomic, strong) NSArray *requiredFieldsList; @property (nonatomic) BOOL smallButton; @property (assign, nonatomic) BOOL tinyButton; @property (nonatomic) CGFloat sizeForSizing; @@ -697,6 +698,7 @@ self.disabledBorderColor = [UIColor mfGetColorForHex:color]; } self.validationRequired = [json boolForKey:@"validationRequired"]; + self.requiredFieldsList = [json array:@"requiredFields"]; NSString *size = [json string:@"size"]; if ([size isEqualToString:@"small"]) { @@ -773,7 +775,11 @@ } } -#pragma mark - FormValidationProtocol +#pragma mark - FormValidationEnableDisableProtocol + +- (NSArray *)requiredFields { + return self.requiredFieldsList; +} - (void)enableField:(BOOL)enable { if (!self.validationRequired) { diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.h b/MVMCoreUI/Atoms/TextFields/MFTextField.h index 72adf682..3e229092 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.h +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.h @@ -43,9 +43,10 @@ @property (nonatomic,getter=isEnabled) BOOL enabled; // To set the placeholder and text -@property (nullable, weak, nonatomic) NSString *text; -@property (nullable, weak, nonatomic) NSString *formText; -@property (nullable, weak, nonatomic) NSString *fieldKey; +@property (nullable, strong, nonatomic) NSString *text; +@property (nullable, strong, nonatomic) NSString *formText; +@property (nullable, strong, nonatomic) NSString *fieldKey; +@property (nullable, strong, nonatomic) NSString *groupName; @property (nullable, weak, nonatomic) NSString *placeholder; // will move out in Feb release diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.m b/MVMCoreUI/Atoms/TextFields/MFTextField.m index ba68c0ed..0e9be054 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.m +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.m @@ -18,7 +18,7 @@ @import MVMCore.NSDictionary_MFConvenience; @import MVMCore.MVMCoreJSONConstants; -@interface MFTextField() +@interface MFTextField() @property (strong, nonatomic) UIColor *customPlaceHolderColor; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *separatorHeightConstraint; @@ -303,28 +303,20 @@ return; } - NSString *string = [map string:KeyLabel]; - if (string.length > 0) { - self.formText = string; - } - string = [map string:KeyValue]; - if (string.length > 0) { + self.formText = [map string:KeyLabel];; + self.groupName = [map string:@"groupName"]; + self.errMessage = [map string:KeyErrorMessage]; + self.fieldKey = [map string:KeyFieldKey]; + + NSString *string = [map stringForKey:KeyValue]; + if (string.length) { self.text = string; } + string = [map stringForKey:KeyDisable]; if ([string isEqual:StringY] || [map boolForKey:KeyDisable]) { [self enable:NO]; } - string = [map string:KeyErrorMessage]; - if (string.length > 0) { - self.errMessage = string; - } - - // key used to send text value to server - string = [map string:KeyFieldKey]; - if (string.length > 0) { - self.fieldKey = string; - } string = [map string:KeyType]; if ([string isEqualToString:@"dropDown"]) { @@ -588,5 +580,9 @@ - (nullable id)formFieldValue { return self.text; } - + +- (NSString * _Nullable)formFieldGroupName { + return self.groupName; +} + @end diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m index 2b5a7f37..f31aace3 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUICheckBox.m @@ -21,7 +21,7 @@ static const CGFloat FaultTolerance = 20.f; static const CGFloat CheckBoxHeightWidth = 18.0; -@interface MVMCoreUICheckBox () +@interface MVMCoreUICheckBox () @property (nonatomic, readwrite) BOOL isSelected; @property (weak, nonatomic) UIView *checkedSquare; diff --git a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift index b593a503..0af41b42 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift @@ -12,16 +12,26 @@ import Foundation // Getter method to get the FormValidator form the delegate (Mostly from the parent View Controller) @objc optional func formValidatorModel() -> FormValidator? - +} + +@objc public protocol FormValidationFormFieldProtocol: FormValidationProtocol { // Used to check the validity of the field, to enable/disable the primary button. - @objc optional func isValidField() -> Bool + @objc func isValidField() -> Bool + // The Field name key value pair for sending to server + @objc func formFieldName() -> String? + + // Returns the group name for validation + @objc func formFieldGroupName() -> String? + + // The Field value key value pair for sending to server + @objc func formFieldValue() -> Any? +} + +@objc public protocol FormValidationEnableDisableProtocol: FormValidationProtocol { // Based on the isValidField(), the fields which needs to be enabled can call this method @objc optional func enableField(_ enable: Bool) - // The Field name key value pair for sending to server - @objc optional func formFieldName() -> String? - - // The Field value key value pair for sending to server - @objc optional func formFieldValue() -> Any? + // Returns the list of field keys required to enable/disable + @objc optional func requiredFields() -> [String]? } diff --git a/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift b/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift index bb9885ab..4c4945a4 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift @@ -16,9 +16,9 @@ import Foundation @objc func getFormParams() -> [String: Any] { var extraParam: [String: Any] = [:] MVMCoreDispatchUtility.performSyncBlock(onMainThread: { - for molecule in self.molecules { - if let formFieldName = molecule.formFieldName?(), - let formFieldValue = molecule.formFieldValue?() { + for molecule in self.fieldMolecules { + if let formFieldName = molecule.formFieldName(), + let formFieldValue = molecule.formFieldValue() { extraParam[formFieldName] = formFieldValue } } diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 91928f3e..821db784 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -8,16 +8,22 @@ import Foundation import UIKit +import MVMCore @objcMembers public class FormValidator: NSObject { var delegate: FormValidationProtocol? - var molecules: [FormValidationProtocol] = [] - var extraValidationBlock: (() -> Bool)? + var fieldMolecules: [FormValidationFormFieldProtocol] = [] + var enableDisableMolecules: [FormValidationEnableDisableProtocol] = [] var radioButtonsModelByGroup: [String: RadioButtonModel] = [:] public func insertMolecule(_ molecule: FormValidationProtocol) { - molecules.append(molecule) + if let molecule = molecule as? FormValidationFormFieldProtocol { + fieldMolecules.append(molecule) + } + if let molecule = molecule as? FormValidationEnableDisableProtocol { + enableDisableMolecules.append(molecule) + } } public static func enableByValidationWith(delegate: FormValidationProtocol?) { @@ -39,18 +45,25 @@ import UIKit } public func enableByValidation() { - var valid = true - for molecule in molecules { - valid = valid && (molecule.isValidField?() ?? true) + var groupValue: [String: Bool] = [:] + for molecule in fieldMolecules { + let valid = molecule.isValidField() + if let grouName = molecule.formFieldGroupName() { + groupValue[grouName] = valid && (groupValue[grouName] ?? true) + } } - let enableField = valid && (extraValidationBlock?() ?? true) - shouldEnable(enableField) + shouldEnable(groupValue) } - public func shouldEnable(_ enable: Bool) { - for molecule in molecules { - molecule.enableField?(enable) + public func shouldEnable(_ groupValue: [String: Bool]) { + for molecule in enableDisableMolecules { + var valid = false + for groupName in molecule.requiredFields?() ?? [] { + valid = groupValue[groupName] ?? false + } + molecule.enableField?(valid) } } + } diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index acd5f016..b95b2ab7 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -9,9 +9,9 @@ import UIKit -@objcMembers open class RadioButton: ViewConstrainingView { +@objcMembers open class RadioButton: ViewConstrainingView, FormValidationFormFieldProtocol { - let radioButton = MFRadioButton() + public let radioButton = MFRadioButton() var delegateObject: MVMCoreUIDelegateObject? var dummyButton: MFCustomButton? let label = Label() @@ -20,10 +20,11 @@ import UIKit var formValue: Bool? var isRequired: Bool = false var radioButtonModel: RadioButtonModel? + lazy var groupName: String? = { [unowned self] in - return json?.optionalStringForKey("groupName") ?? json?.optionalStringForKey("fieldKey") + return json?.optionalStringForKey("radioGroupName") ?? json?.optionalStringForKey("fieldKey") }() // MARK: - Inits @@ -106,6 +107,22 @@ import UIKit FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) changeAccessibilityLabel() } + + public func isValidField() -> Bool { + return radioButton.isSelected + } + + public func formFieldName() -> String? { + return json?.optionalStringForKey("fieldKey") + } + + public func formFieldGroupName() -> String? { + return json?.optionalStringForKey("radioGroupName") + } + + public func formFieldValue() -> Any? { + return radioButton.isSelected + } } // MARK: - MVMCoreUIMoleculeViewProtocol diff --git a/MVMCoreUI/Molecules/RadioButtonModel.swift b/MVMCoreUI/Molecules/RadioButtonModel.swift index 40238307..812ea36a 100644 --- a/MVMCoreUI/Molecules/RadioButtonModel.swift +++ b/MVMCoreUI/Molecules/RadioButtonModel.swift @@ -12,14 +12,16 @@ import UIKit @objcMembers public class RadioButtonModel: NSObject { private var selectedRadioButton: RadioButton? + private var fieldGroupName: String? public static func setupForRadioButtonGroup(radioButton: RadioButton, formValidator: FormValidator?) -> RadioButtonModel { guard let groupName = radioButton.groupName, let formValidator = formValidator else { return RadioButtonModel() } - + let radioButtonModel = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonModel() + radioButtonModel.fieldGroupName = radioButton.formFieldGroupName() formValidator.radioButtonsModelByGroup[groupName] = radioButtonModel return radioButtonModel } @@ -32,7 +34,11 @@ import UIKit } // MARK: - FormValidationProtocol -extension RadioButtonModel: FormValidationProtocol { +extension RadioButtonModel: FormValidationFormFieldProtocol { + public func formFieldGroupName() -> String? { + return selectedRadioButton?.formFieldGroupName() ?? self.fieldGroupName + } + // Used to check the validity of the field, to enable/disable the primary button. @objc public func isValidField() -> Bool { return selectedRadioButton != nil ? true : false diff --git a/MVMCoreUI/Molecules/Switch.swift b/MVMCoreUI/Molecules/Switch.swift index 5b23b1d5..8cb19909 100644 --- a/MVMCoreUI/Molecules/Switch.swift +++ b/MVMCoreUI/Molecules/Switch.swift @@ -8,7 +8,7 @@ import UIKit -@objcMembers public class Switch: ViewConstrainingView, FormValidationProtocol{ +@objcMembers public class Switch: ViewConstrainingView, FormValidationFormFieldProtocol { public var mvmSwitch = MVMCoreUISwitch() var isRequired = false var delegateObject: DelegateObject? @@ -76,6 +76,10 @@ import UIKit return mvmSwitch.isOn } + public func formFieldGroupName() -> String? { + return json?.optionalStringForKey("groupName") + } + public override func needsToBeConstrained() -> Bool { return true } diff --git a/MVMCoreUI/Molecules/SwitchLineItem.swift b/MVMCoreUI/Molecules/SwitchLineItem.swift index 8c15e8ec..54860158 100644 --- a/MVMCoreUI/Molecules/SwitchLineItem.swift +++ b/MVMCoreUI/Molecules/SwitchLineItem.swift @@ -8,7 +8,9 @@ import UIKit -@objcMembers public class SwitchLineItem: ViewConstrainingView, FormValidationProtocol{ +@objcMembers public class SwitchLineItem: ViewConstrainingView, FormValidationFormFieldProtocol { + + public var mvmSwitch = Switch() public var label = Label() public var leftContainerView = UIView() @@ -116,6 +118,23 @@ import UIKit public override func alignment() -> UIStackView.Alignment { return UIStackView.Alignment.leading } + + + public func isValidField() -> Bool { + return mvmSwitch.isValidField() + } + + public func formFieldName() -> String? { + return mvmSwitch.formFieldName() + } + + public func formFieldGroupName() -> String? { + return mvmSwitch.formFieldGroupName() + } + + public func formFieldValue() -> Any? { + return mvmSwitch.formFieldValue() + } } From c8611ca83ad96c8f4286759e8d56f2129cbe3ff3 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 4 Sep 2019 14:39:19 -0400 Subject: [PATCH 19/45] fixes --- MVMCoreUI/Molecules/RadioButton.swift | 4 ++-- MVMCoreUI/Molecules/RadioButtonModel.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index b95b2ab7..53fbaefc 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -22,7 +22,7 @@ import UIKit var radioButtonModel: RadioButtonModel? - lazy var groupName: String? = { + lazy var radioGroupName: String? = { [unowned self] in return json?.optionalStringForKey("radioGroupName") ?? json?.optionalStringForKey("fieldKey") }() @@ -117,7 +117,7 @@ import UIKit } public func formFieldGroupName() -> String? { - return json?.optionalStringForKey("radioGroupName") + return json?.optionalStringForKey("groupName") } public func formFieldValue() -> Any? { diff --git a/MVMCoreUI/Molecules/RadioButtonModel.swift b/MVMCoreUI/Molecules/RadioButtonModel.swift index 812ea36a..68e95790 100644 --- a/MVMCoreUI/Molecules/RadioButtonModel.swift +++ b/MVMCoreUI/Molecules/RadioButtonModel.swift @@ -15,7 +15,7 @@ import UIKit private var fieldGroupName: String? public static func setupForRadioButtonGroup(radioButton: RadioButton, formValidator: FormValidator?) -> RadioButtonModel { - guard let groupName = radioButton.groupName, + guard let groupName = radioButton.radioGroupName, let formValidator = formValidator else { return RadioButtonModel() } From eac6bf3aa3fb1850bf6955ec57f6926dd0714ee1 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 11 Sep 2019 15:56:24 -0400 Subject: [PATCH 20/45] impreovements --- MVMCoreUI/Atoms/Buttons/PrimaryButton.h | 1 + MVMCoreUI/Atoms/Buttons/PrimaryButton.m | 10 ++++-- .../FormValidationProtocol.swift | 3 ++ MVMCoreUI/FormUIHelpers/FormValidator.swift | 33 +++++++++++++++---- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton.h b/MVMCoreUI/Atoms/Buttons/PrimaryButton.h index 99929430..be780b0f 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton.h +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton.h @@ -26,6 +26,7 @@ typedef enum : NSUInteger { static CGFloat const PrimaryButtonHeight = 42.0; static CGFloat const PrimaryButtonSmallHeight = 30.0; + @interface PrimaryButton : MFCustomButton @property (nonatomic, readonly, assign) PrimaryButtonType primaryButtonType; //use reset function to set diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m index fa719012..daeb2751 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m @@ -13,6 +13,7 @@ #import "MFStyler.h" #import "UIColor+MFConvenience.h" #import + @import MVMCore.MVMCoreDispatchUtility; @import MVMCore.MVMCoreGetterUtility; @import MVMCore.NSDictionary_MFConvenience; @@ -667,6 +668,9 @@ } - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { + + self.validationRequired = [json boolForKey:@"validationRequired"]; + self.requiredFieldsList = [json array:@"requiredFields"]; [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; self.primaryButtonType = PrimaryButtonTypeCustom; @@ -697,8 +701,6 @@ if ((color = [json string:@"disabledBorderColor"])) { self.disabledBorderColor = [UIColor mfGetColorForHex:color]; } - self.validationRequired = [json boolForKey:@"validationRequired"]; - self.requiredFieldsList = [json array:@"requiredFields"]; NSString *size = [json string:@"size"]; if ([size isEqualToString:@"small"]) { @@ -777,6 +779,10 @@ #pragma mark - FormValidationEnableDisableProtocol +- (BOOL) isValidationRequired { + return self.validationRequired; +} + - (NSArray *)requiredFields { return self.requiredFieldsList; } diff --git a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift index 0af41b42..2e109811 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift @@ -29,6 +29,9 @@ import Foundation } @objc public protocol FormValidationEnableDisableProtocol: FormValidationProtocol { + + @objc func isValidationRequired() -> Bool + // Based on the isValidField(), the fields which needs to be enabled can call this method @objc optional func enableField(_ enable: Bool) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 821db784..e1c2b13c 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -13,6 +13,7 @@ import MVMCore @objcMembers public class FormValidator: NSObject { var delegate: FormValidationProtocol? + var extraValidationBlock: (() -> Bool)? var fieldMolecules: [FormValidationFormFieldProtocol] = [] var enableDisableMolecules: [FormValidationEnableDisableProtocol] = [] var radioButtonsModelByGroup: [String: RadioButtonModel] = [:] @@ -21,8 +22,9 @@ import MVMCore if let molecule = molecule as? FormValidationFormFieldProtocol { fieldMolecules.append(molecule) } - if let molecule = molecule as? FormValidationEnableDisableProtocol { - enableDisableMolecules.append(molecule) + if let moleculeT = molecule as? FormValidationEnableDisableProtocol, + moleculeT.isValidationRequired() { + enableDisableMolecules.append(moleculeT) } } @@ -45,6 +47,27 @@ import MVMCore } public func enableByValidation() { + if enableDisableMolecules.count > 1 { + enableByGroup() + } else { + enableByFieldValidation() + } + } + + public func enableByFieldValidation() { + guard let enableMolecule = enableDisableMolecules.first else { + return; + } + + var valid = true + for molecule in fieldMolecules { + valid = valid && molecule.isValidField() + } + let enableField = valid && (extraValidationBlock?() ?? true) + enableMolecule.enableField?(enableField) + } + + func enableByGroup() { var groupValue: [String: Bool] = [:] for molecule in fieldMolecules { let valid = molecule.isValidField() @@ -52,10 +75,7 @@ import MVMCore groupValue[grouName] = valid && (groupValue[grouName] ?? true) } } - shouldEnable(groupValue) - } - - public func shouldEnable(_ groupValue: [String: Bool]) { + for molecule in enableDisableMolecules { var valid = false for groupName in molecule.requiredFields?() ?? [] { @@ -64,6 +84,7 @@ import MVMCore molecule.enableField?(valid) } } + } From bedd05daa6d947224a160bcce2ecdb1e471cb7c2 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 12 Sep 2019 14:42:10 -0400 Subject: [PATCH 21/45] Creation and inclusion of HeadlineBodyButton molecule. --- MVMCoreUI.xcodeproj/project.pbxproj | 5 +- .../Molecules/ActionDetailWithImage.swift | 60 ++------ MVMCoreUI/Molecules/HeadlineBodyButton.swift | 129 ++++++++++++++++++ .../MVMCoreUIMoleculeMappingObject.m | 3 +- 4 files changed, 148 insertions(+), 49 deletions(-) create mode 100644 MVMCoreUI/Molecules/HeadlineBodyButton.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index f606284e..68d9e8f5 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; }; + 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; B8200E152280C4CF007245F4 /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E142280C4CF007245F4 /* ProgressBar.swift */; }; B8200E192281DC1A007245F4 /* CornerLabels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E182281DC1A007245F4 /* CornerLabels.swift */; }; @@ -202,6 +203,7 @@ 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = ""; }; 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = ""; }; 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = ""; }; + 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; 0A804A3C2316CB79009A8656 /* HeadlineBodyPrimaryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyPrimaryButton.swift; sourceTree = ""; }; 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = ""; }; B8200E142280C4CF007245F4 /* ProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = ""; }; @@ -562,6 +564,7 @@ D274CA322236A78900B01B62 /* StandardFooterView.swift */, D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */, + 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */, ); path = Molecules; sourceTree = ""; @@ -1003,6 +1006,7 @@ D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */, DBC4391922442197001AB423 /* DashLine.swift in Sources */, + 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */, D29DF29621E7ADB8003B2FB9 /* StackableViewController.m in Sources */, D2E1FADB2260D3D200AEFD8C /* MVMCoreUIDelegateObject.swift in Sources */, D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */, @@ -1024,7 +1028,6 @@ 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */, D2A5145F2211DDC100345BFB /* MoleculeStackView.swift in Sources */, D29DF27621E79E81003B2FB9 /* MVMCoreUILoggingHandler.m in Sources */, - 0A804A3D2316CB79009A8656 /* HeadlineBodyPrimaryButton.swift in Sources */, D29DF24D21E6A177003B2FB9 /* MFTextField.m in Sources */, D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */, D29DF12B21E6851E003B2FB9 /* MVMCoreUITopAlertExpandableView.m in Sources */, diff --git a/MVMCoreUI/Molecules/ActionDetailWithImage.swift b/MVMCoreUI/Molecules/ActionDetailWithImage.swift index ec91c479..76dde8e6 100644 --- a/MVMCoreUI/Molecules/ActionDetailWithImage.swift +++ b/MVMCoreUI/Molecules/ActionDetailWithImage.swift @@ -14,10 +14,8 @@ import UIKit // MARK: - Outlets //------------------------------------------------------ - let header = HeadlineBody(frame: .zero) - let button = PrimaryButton.primaryTinyButton(false)! + let headlineBodyButton = HeadlineBodyButton(frame: .zero) let imageLoader = MFLoadImageView(pinnedEdges: .all) - let leftContainer = ViewConstrainingView.empty() //------------------------------------------------------ // MARK: - Properties @@ -30,7 +28,6 @@ import UIKit //------------------------------------------------------ var imageLeadingConstraint: NSLayoutConstraint? - var buttonTopConstraint: NSLayoutConstraint? //------------------------------------------------------ // MARK: - Initialization @@ -64,33 +61,20 @@ import UIKit setDefaultState() - addSubview(leftContainer) addSubview(imageLoader) - leftContainer.addSubview(header) - leftContainer.addSubview(button) + addSubview(headlineBodyButton) - leftContainer.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true - leftContainer.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true + headlineBodyButton.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true + headlineBodyButton.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true - layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: leftContainer.bottomAnchor).isActive = true - let leftContainerBottom = leftContainer.bottomAnchor.constraint(equalTo: bottomAnchor) + layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: headlineBodyButton.bottomAnchor).isActive = true + let leftContainerBottom = headlineBodyButton.bottomAnchor.constraint(equalTo: bottomAnchor) leftContainerBottom.priority = UILayoutPriority(249) leftContainerBottom.isActive = true - header.topAnchor.constraint(equalTo: leftContainer.topAnchor).isActive = true - header.leadingAnchor.constraint(equalTo: leftContainer.leadingAnchor).isActive = true - leftContainer.trailingAnchor.constraint(equalTo: header.trailingAnchor).isActive = true - - buttonTopConstraint = button.topAnchor.constraint(equalTo: header.bottomAnchor, constant: buttonHeaderPadding) - buttonTopConstraint?.isActive = true - - button.leadingAnchor.constraint(equalTo: leftContainer.leadingAnchor).isActive = true - leftContainer.bottomAnchor.constraint(equalTo: button.bottomAnchor).isActive = true - leftContainer.trailingAnchor.constraint(greaterThanOrEqualTo: button.trailingAnchor).isActive = true - imageLoader.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true layoutMarginsGuide.trailingAnchor.constraint(equalTo: imageLoader.trailingAnchor).isActive = true - imageLeadingConstraint = imageLoader.leadingAnchor.constraint(greaterThanOrEqualTo: leftContainer.trailingAnchor, constant: 16) + imageLeadingConstraint = imageLoader.leadingAnchor.constraint(greaterThanOrEqualTo: headlineBodyButton.trailingAnchor, constant: 16) imageLeadingConstraint?.isActive = true imageLoader.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor).isActive = true @@ -103,12 +87,8 @@ import UIKit override open func updateView(_ size: CGFloat) { super.updateView(size) - header.updateView(size) - button.updateView(size) + headlineBodyButton.updateView(size) imageLoader.updateView(size) - leftContainer.updateView(size) - - buttonTopConstraint?.constant = header.hasText() ? buttonHeaderPadding : 0 } public override static func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { @@ -121,10 +101,8 @@ import UIKit private func setDefaultState() { - header.headlineLabel.font = MFStyler.fontH3() - header.messageLabel.font = MFStyler.fontB3() - button.setAsSecondaryCustom() - button.isHidden = false + headlineBodyButton.headline.headlineLabel.font = MFStyler.fontH3() + headlineBodyButton.headline.messageLabel.font = MFStyler.fontB3() imageLoader.imageView.contentMode = .scaleAspectFit imageLoader.addSizeConstraintsForAspectRatio = true buttonHeaderPadding = PaddingTwo @@ -133,8 +111,7 @@ import UIKit override open func reset() { super.reset() - header.reset() - button.reset() + headlineBodyButton.reset() imageLeadingConstraint?.constant = 16 imageLoader.reset() setDefaultState() @@ -143,8 +120,7 @@ import UIKit open override func setAsMolecule() { super.setAsMolecule() - header.setAsMolecule() - button.setAsMolecule() + headlineBodyButton.setAsMolecule() imageLoader.setAsMolecule() setDefaultState() } @@ -153,18 +129,8 @@ import UIKit super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) guard let dictionary = json else { return } - - if let padding = dictionary.optionalCGFloatForKey("buttonHeaderPadding") { - buttonHeaderPadding = padding - } - header.setWithJSON(dictionary.optionalDictionaryForKey("headlineBody"), delegateObject: delegateObject, additionalData: additionalData) + headlineBodyButton.setWithJSON(dictionary.optionalDictionaryForKey("headlineBodyButton"), delegateObject: delegateObject, additionalData: additionalData) imageLoader.setWithJSON(dictionary.optionalDictionaryForKey("image"), delegateObject: delegateObject, additionalData: additionalData) - - if let buttonDictionary = dictionary.optionalDictionaryForKey("button") { - button.setWithJSON(buttonDictionary, delegateObject: delegateObject, additionalData: additionalData) - } else { - button.isHidden = true - } } } diff --git a/MVMCoreUI/Molecules/HeadlineBodyButton.swift b/MVMCoreUI/Molecules/HeadlineBodyButton.swift new file mode 100644 index 00000000..df8ae918 --- /dev/null +++ b/MVMCoreUI/Molecules/HeadlineBodyButton.swift @@ -0,0 +1,129 @@ +// +// HeadlineBodyButton.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 9/12/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + + +@objcMembers open class HeadlineBodyButton: ViewConstrainingView { + //------------------------------------------------------ + // MARK: - Outlets + //------------------------------------------------------ + + let headline = HeadlineBody(frame: .zero) + let button = PrimaryButton.primaryTinyButton(false)! + + //------------------------------------------------------ + // MARK: - Properties + //------------------------------------------------------ + + var buttonHeadlinePadding: CGFloat = 16 + + //------------------------------------------------------ + // MARK: - Constraints + //------------------------------------------------------ + + var buttonTopConstraint: NSLayoutConstraint? + + //------------------------------------------------------ + // MARK: - Initialization + //------------------------------------------------------ + + public init() { + super.init(frame: .zero) + } + + public override init(frame: CGRect) { + super.init(frame: frame) + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + public convenience init(json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + self.init() + setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + } + + //------------------------------------------------------ + // MARK: - View Lifecycle + //------------------------------------------------------ + + override open func setupView() { + super.setupView() + + guard subviews.isEmpty else { return } + + setDefaultState() + + addSubview(headline) + addSubview(button) + + headline.topAnchor.constraint(equalTo: topAnchor).isActive = true + headline.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true + trailingAnchor.constraint(equalTo: headline.trailingAnchor).isActive = true + + buttonTopConstraint = button.topAnchor.constraint(equalTo: headline.bottomAnchor, constant: buttonHeadlinePadding) + buttonTopConstraint?.isActive = true + + button.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true + bottomAnchor.constraint(equalTo: button.bottomAnchor).isActive = true + trailingAnchor.constraint(greaterThanOrEqualTo: button.trailingAnchor).isActive = true + } + + override open func updateView(_ size: CGFloat) { + super.updateView(size) + + headline.updateView(size) + button.updateView(size) + + buttonTopConstraint?.constant = headline.hasText() ? buttonHeadlinePadding : 0 + } + private func setDefaultState() { + + headline.headlineLabel.font = MFStyler.fontH3() + headline.messageLabel.font = MFStyler.fontB3() + button.setAsSecondaryCustom() + button.isHidden = false + buttonHeadlinePadding = PaddingTwo + } + + override open func reset() { + super.reset() + + headline.reset() + button.reset() + setDefaultState() + } + + open override func setAsMolecule() { + super.setAsMolecule() + + headline.setAsMolecule() + button.setAsMolecule() + setDefaultState() + } + + open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + guard let dictionary = json else { return } + + if let padding = dictionary.optionalCGFloatForKey("buttonHeadlinePadding") { + buttonHeadlinePadding = padding + } + + headline.setWithJSON(dictionary.optionalDictionaryForKey("headlineBody"), delegateObject: delegateObject, additionalData: additionalData) + + if let buttonDictionary = dictionary.optionalDictionaryForKey("button") { + button.setWithJSON(buttonDictionary, delegateObject: delegateObject, additionalData: additionalData) + } else { + button.isHidden = true + } + } +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 86267332..c80c25d6 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -60,7 +60,8 @@ @"headlineBodySwitch": HeadlineBodySwitch.class, @"headlineBodyTextButton": HeadlineBodyTextButton.class, @"headlineBodyTextButtonSwitch": HeadlineBodyTextButtonSwitch.class, - @"tabsListItem": TabsTableViewCell.class + @"tabsListItem": TabsTableViewCell.class, + @"HeadlineBodyButton": HeadlineBodyButton.class } mutableCopy]; }); return mapping; From ad1def8ddc648b6866f54208302a695a2c4e597f Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 12 Sep 2019 16:38:18 -0400 Subject: [PATCH 22/45] changed default state name. --- MVMCoreUI/Molecules/HeadlineBodyButton.swift | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Molecules/HeadlineBodyButton.swift b/MVMCoreUI/Molecules/HeadlineBodyButton.swift index df8ae918..1d1105c0 100644 --- a/MVMCoreUI/Molecules/HeadlineBodyButton.swift +++ b/MVMCoreUI/Molecules/HeadlineBodyButton.swift @@ -59,7 +59,7 @@ import UIKit guard subviews.isEmpty else { return } - setDefaultState() + defaultState() addSubview(headline) addSubview(button) @@ -84,7 +84,8 @@ import UIKit buttonTopConstraint?.constant = headline.hasText() ? buttonHeadlinePadding : 0 } - private func setDefaultState() { + + private func defaultState() { headline.headlineLabel.font = MFStyler.fontH3() headline.messageLabel.font = MFStyler.fontB3() @@ -93,12 +94,16 @@ import UIKit buttonHeadlinePadding = PaddingTwo } + //------------------------------------------------------ + // MARK: - Molecule + //------------------------------------------------------ + override open func reset() { super.reset() headline.reset() button.reset() - setDefaultState() + defaultState() } open override func setAsMolecule() { @@ -106,7 +111,7 @@ import UIKit headline.setAsMolecule() button.setAsMolecule() - setDefaultState() + defaultState() } open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { From cdc7ae2f1e7e0599e3a9ef09c932120da2cd6784 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 13 Sep 2019 09:08:33 -0400 Subject: [PATCH 23/45] added layoutMarginsGuide. --- MVMCoreUI/Molecules/HeadlineBodyButton.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Molecules/HeadlineBodyButton.swift b/MVMCoreUI/Molecules/HeadlineBodyButton.swift index 1d1105c0..feb0f751 100644 --- a/MVMCoreUI/Molecules/HeadlineBodyButton.swift +++ b/MVMCoreUI/Molecules/HeadlineBodyButton.swift @@ -64,16 +64,16 @@ import UIKit addSubview(headline) addSubview(button) - headline.topAnchor.constraint(equalTo: topAnchor).isActive = true - headline.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true - trailingAnchor.constraint(equalTo: headline.trailingAnchor).isActive = true + headline.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true + headline.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true + layoutMarginsGuide.trailingAnchor.constraint(equalTo: headline.trailingAnchor).isActive = true buttonTopConstraint = button.topAnchor.constraint(equalTo: headline.bottomAnchor, constant: buttonHeadlinePadding) buttonTopConstraint?.isActive = true - button.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true - bottomAnchor.constraint(equalTo: button.bottomAnchor).isActive = true - trailingAnchor.constraint(greaterThanOrEqualTo: button.trailingAnchor).isActive = true + button.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true + layoutMarginsGuide.bottomAnchor.constraint(equalTo: button.bottomAnchor).isActive = true + layoutMarginsGuide.trailingAnchor.constraint(greaterThanOrEqualTo: button.trailingAnchor).isActive = true } override open func updateView(_ size: CGFloat) { From daed451c7afa9022f1ff273be08c8a29cf65a800 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 13 Sep 2019 15:25:13 -0400 Subject: [PATCH 24/45] improvements --- MVMCoreUI/Atoms/TextFields/MFTextField.m | 2 +- .../FormValidationProtocol.swift | 11 ++-- MVMCoreUI/FormUIHelpers/FormValidator.swift | 54 +++++++++---------- 3 files changed, 31 insertions(+), 36 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.m b/MVMCoreUI/Atoms/TextFields/MFTextField.m index 0e9be054..c52c4972 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.m +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.m @@ -303,7 +303,7 @@ return; } - self.formText = [map string:KeyLabel];; + self.formText = [map string:KeyLabel]; self.groupName = [map string:@"groupName"]; self.errMessage = [map string:KeyErrorMessage]; self.fieldKey = [map string:KeyFieldKey]; diff --git a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift index 2e109811..27f3f754 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift @@ -10,26 +10,27 @@ import Foundation @objc public protocol FormValidationProtocol: NSObjectProtocol { - // Getter method to get the FormValidator form the delegate (Mostly from the parent View Controller) + // Getter method to get the FormValidator from the delegate (Mostly from the parent View Controller) @objc optional func formValidatorModel() -> FormValidator? } -@objc public protocol FormValidationFormFieldProtocol: FormValidationProtocol { - // Used to check the validity of the field, to enable/disable the primary button. +@objc public protocol FormValidationFormFieldProtocol: FormValidationProtocol { + // Used to check the validity of the field. For example, to enable/disable the primary button. @objc func isValidField() -> Bool // The Field name key value pair for sending to server @objc func formFieldName() -> String? - // Returns the group name for validation + // Returns the group name for validation. The class should always return a value. @objc func formFieldGroupName() -> String? // The Field value key value pair for sending to server @objc func formFieldValue() -> Any? } -@objc public protocol FormValidationEnableDisableProtocol: FormValidationProtocol { +@objc public protocol FormValidationEnableDisableProtocol: FormValidationProtocol { + // Returns true if the button needs to be enabled/disabled based on the validation @objc func isValidationRequired() -> Bool // Based on the isValidField(), the fields which needs to be enabled can call this method diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index e1c2b13c..c3cc77fa 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -12,8 +12,9 @@ import MVMCore @objcMembers public class FormValidator: NSObject { - var delegate: FormValidationProtocol? var extraValidationBlock: (() -> Bool)? + var dummyGroupName = "dummyGroupName" + weak var delegate: FormValidationProtocol? var fieldMolecules: [FormValidationFormFieldProtocol] = [] var enableDisableMolecules: [FormValidationEnableDisableProtocol] = [] var radioButtonsModelByGroup: [String: RadioButtonModel] = [:] @@ -47,44 +48,37 @@ import MVMCore } public func enableByValidation() { - if enableDisableMolecules.count > 1 { - enableByGroup() - } else { - enableByFieldValidation() + for molecule in enableDisableMolecules { + if let requiredFeilds = molecule.requiredFields?(), requiredFeilds.count > 0 { + enableWithGroupName(requiredFeilds, molecule) + } else { + enableIgnoreGroupName(molecule) + } } } - public func enableByFieldValidation() { - guard let enableMolecule = enableDisableMolecules.first else { - return; + public func enableWithGroupName(_ requiredGroupList: [String], _ enableDisableMolecules: FormValidationEnableDisableProtocol) { + + var groupValidityMap: [String: Bool] = [:] + for molecule in fieldMolecules { + let valid = molecule.isValidField() + let groupName = molecule.formFieldGroupName() ?? dummyGroupName + groupValidityMap[groupName] = valid && (groupValidityMap[groupName] ?? true) } + var valid = false + for groupName in requiredGroupList { + valid = groupValidityMap[groupName] ?? false + } + enableDisableMolecules.enableField?(valid) + } + + public func enableIgnoreGroupName(_ enableDisableMolecules: FormValidationEnableDisableProtocol) { var valid = true for molecule in fieldMolecules { valid = valid && molecule.isValidField() } let enableField = valid && (extraValidationBlock?() ?? true) - enableMolecule.enableField?(enableField) + enableDisableMolecules.enableField?(enableField) } - - func enableByGroup() { - var groupValue: [String: Bool] = [:] - for molecule in fieldMolecules { - let valid = molecule.isValidField() - if let grouName = molecule.formFieldGroupName() { - groupValue[grouName] = valid && (groupValue[grouName] ?? true) - } - } - - for molecule in enableDisableMolecules { - var valid = false - for groupName in molecule.requiredFields?() ?? [] { - valid = groupValue[groupName] ?? false - } - molecule.enableField?(valid) - } - } - - } - From 720d17d7517bb795446d2621c59a67473ac96720 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 17 Oct 2019 15:35:14 -0400 Subject: [PATCH 25/45] revisions made. --- MVMCoreUI.xcodeproj/project.pbxproj | 6 +-- .../Buttons/HeadlineBodyPrimaryButton.swift | 53 ------------------- MVMCoreUI/Molecules/HeadlineBodyButton.swift | 28 +++++----- 3 files changed, 16 insertions(+), 71 deletions(-) delete mode 100644 MVMCoreUI/Atoms/Buttons/HeadlineBodyPrimaryButton.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index ed3c634d..0eca06db 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -18,9 +18,9 @@ 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; }; - 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; 0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */; }; 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; + 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; @@ -207,9 +207,8 @@ 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = ""; }; 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = ""; }; 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = ""; }; - 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; - 0A804A3C2316CB79009A8656 /* HeadlineBodyPrimaryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyPrimaryButton.swift; sourceTree = ""; }; 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = ""; }; + 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = ""; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; @@ -682,7 +681,6 @@ DBC4391A224421A0001AB423 /* CaretButton.swift */, D29DF25821E6A22D003B2FB9 /* MFButtonProtocol.h */, D29DF16B21E69E1F003B2FB9 /* ButtonDelegateProtocol.h */, - 0A804A3C2316CB79009A8656 /* HeadlineBodyPrimaryButton.swift */, D29DF16A21E69E1F003B2FB9 /* MFCustomButton.h */, D29DF17021E69E1F003B2FB9 /* MFCustomButton.m */, D29DF16C21E69E1F003B2FB9 /* PrimaryButton.h */, diff --git a/MVMCoreUI/Atoms/Buttons/HeadlineBodyPrimaryButton.swift b/MVMCoreUI/Atoms/Buttons/HeadlineBodyPrimaryButton.swift deleted file mode 100644 index 029a42c0..00000000 --- a/MVMCoreUI/Atoms/Buttons/HeadlineBodyPrimaryButton.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// HeadlineBodyPrimaryButton.swift -// MVMCoreUI -// -// Created by Kevin Christiano on 8/28/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - - -@objcMembers open class HeadlineBodyPrimaryButton: ViewConstrainingView { - //------------------------------------------------------ - // MARK: - Outlets - //------------------------------------------------------ - - - - //------------------------------------------------------ - // MARK: - Properties - //------------------------------------------------------ - - - - //------------------------------------------------------ - // MARK: - Lifecycle - //------------------------------------------------------ - - open override func setupView() { - super.setupView() - - guard subviews.count == 0 else { return } - - } - - open override func updateView(_ size: CGFloat) { - super.updateView(size) - } - - //------------------------------------------------------ - // MARK: - JSON - //------------------------------------------------------ - - - - open override func reset() { - - } - - open override func setAsMolecule() { - super.setAsMolecule() - } -} diff --git a/MVMCoreUI/Molecules/HeadlineBodyButton.swift b/MVMCoreUI/Molecules/HeadlineBodyButton.swift index feb0f751..2922f0f2 100644 --- a/MVMCoreUI/Molecules/HeadlineBodyButton.swift +++ b/MVMCoreUI/Molecules/HeadlineBodyButton.swift @@ -14,7 +14,7 @@ import UIKit // MARK: - Outlets //------------------------------------------------------ - let headline = HeadlineBody(frame: .zero) + let headlineBody = HeadlineBody(frame: .zero) let button = PrimaryButton.primaryTinyButton(false)! //------------------------------------------------------ @@ -61,14 +61,14 @@ import UIKit defaultState() - addSubview(headline) + addSubview(headlineBody) addSubview(button) - headline.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true - headline.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true - layoutMarginsGuide.trailingAnchor.constraint(equalTo: headline.trailingAnchor).isActive = true + headlineBody.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true + headlineBody.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true + layoutMarginsGuide.trailingAnchor.constraint(equalTo: headlineBody.trailingAnchor).isActive = true - buttonTopConstraint = button.topAnchor.constraint(equalTo: headline.bottomAnchor, constant: buttonHeadlinePadding) + buttonTopConstraint = button.topAnchor.constraint(equalTo: headlineBody.bottomAnchor, constant: buttonHeadlinePadding) buttonTopConstraint?.isActive = true button.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor).isActive = true @@ -79,17 +79,17 @@ import UIKit override open func updateView(_ size: CGFloat) { super.updateView(size) - headline.updateView(size) + headlineBody.updateView(size) button.updateView(size) - buttonTopConstraint?.constant = headline.hasText() ? buttonHeadlinePadding : 0 + buttonTopConstraint?.constant = headlineBody.hasText() && !button.isHidden ? buttonHeadlinePadding : 0 } private func defaultState() { - headline.headlineLabel.font = MFStyler.fontH3() - headline.messageLabel.font = MFStyler.fontB3() - button.setAsSecondaryCustom() + headlineBody.headlineLabel.font = MFStyler.fontH3() + headlineBody.messageLabel.font = MFStyler.fontB3() + button.setAsTiny(true) button.isHidden = false buttonHeadlinePadding = PaddingTwo } @@ -101,7 +101,7 @@ import UIKit override open func reset() { super.reset() - headline.reset() + headlineBody.reset() button.reset() defaultState() } @@ -109,7 +109,7 @@ import UIKit open override func setAsMolecule() { super.setAsMolecule() - headline.setAsMolecule() + headlineBody.setAsMolecule() button.setAsMolecule() defaultState() } @@ -123,7 +123,7 @@ import UIKit buttonHeadlinePadding = padding } - headline.setWithJSON(dictionary.optionalDictionaryForKey("headlineBody"), delegateObject: delegateObject, additionalData: additionalData) + headlineBody.setWithJSON(dictionary.optionalDictionaryForKey("headlineBodyBody"), delegateObject: delegateObject, additionalData: additionalData) if let buttonDictionary = dictionary.optionalDictionaryForKey("button") { button.setWithJSON(buttonDictionary, delegateObject: delegateObject, additionalData: additionalData) From 034610af5ee8a2999f947d03444e10a3ef15bd2a Mon Sep 17 00:00:00 2001 From: panxi Date: Thu, 17 Oct 2019 15:50:25 -0400 Subject: [PATCH 26/45] fixing merging issue --- MVMCoreUI.xcodeproj/project.pbxproj | 5 -- MVMCoreUI/Atoms/Buttons/PrimaryButton.h | 1 - MVMCoreUI/Atoms/Buttons/PrimaryButton.m | 2 +- MVMCoreUI/Atoms/Views/ProgressBar.swift | 81 ------------------------- 4 files changed, 1 insertion(+), 88 deletions(-) delete mode 100644 MVMCoreUI/Atoms/Views/ProgressBar.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 08b9caf0..78207194 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -28,8 +28,6 @@ 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; 9455B19C234F8A0400A574DB /* MVMAnimationFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */; }; 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 948DB67D2326DCD90011F916 /* MultiProgress.swift */; }; - B8200E152280C4CF007245F4 /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E142280C4CF007245F4 /* ProgressBar.swift */; }; - B8200E192281DC1A007245F4 /* CornerLabels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8200E182281DC1A007245F4 /* CornerLabels.swift */; }; D206997721FB8A0B00CAE0DE /* MVMCoreUINavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; }; D206997821FB8A0B00CAE0DE /* MVMCoreUINavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = D206997621FB8A0B00CAE0DE /* MVMCoreUINavigationController.m */; }; D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */; }; @@ -220,8 +218,6 @@ 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = ""; }; 9455B19B234F8A0400A574DB /* MVMAnimationFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MVMAnimationFramework.framework; path = ../SharedFrameworks/MVMAnimationFramework.framework; sourceTree = ""; }; 948DB67D2326DCD90011F916 /* MultiProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiProgress.swift; sourceTree = ""; }; - B8200E142280C4CF007245F4 /* ProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = ""; }; - B8200E182281DC1A007245F4 /* CornerLabels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerLabels.swift; sourceTree = ""; }; D206997521FB8A0B00CAE0DE /* MVMCoreUINavigationController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUINavigationController.h; sourceTree = ""; }; D206997621FB8A0B00CAE0DE /* MVMCoreUINavigationController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUINavigationController.m; sourceTree = ""; }; D20A9A5D2243D3E300ADE781 /* TwoButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonView.swift; sourceTree = ""; }; @@ -706,7 +702,6 @@ D260D7AF22D65BDD007E7233 /* MVMCoreUIPageControl.h */, D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */, D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */, - B8200E142280C4CF007245F4 /* ProgressBar.swift */, 948DB67D2326DCD90011F916 /* MultiProgress.swift */, DBC4391622442196001AB423 /* CaretView.swift */, DBC4391722442197001AB423 /* DashLine.swift */, diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton.h b/MVMCoreUI/Atoms/Buttons/PrimaryButton.h index be780b0f..99929430 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton.h +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton.h @@ -26,7 +26,6 @@ typedef enum : NSUInteger { static CGFloat const PrimaryButtonHeight = 42.0; static CGFloat const PrimaryButtonSmallHeight = 30.0; - @interface PrimaryButton : MFCustomButton @property (nonatomic, readonly, assign) PrimaryButtonType primaryButtonType; //use reset function to set diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m index daeb2751..33cadc8c 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m @@ -779,7 +779,7 @@ #pragma mark - FormValidationEnableDisableProtocol -- (BOOL) isValidationRequired { +- (BOOL)isValidationRequired { return self.validationRequired; } diff --git a/MVMCoreUI/Atoms/Views/ProgressBar.swift b/MVMCoreUI/Atoms/Views/ProgressBar.swift deleted file mode 100644 index a9333966..00000000 --- a/MVMCoreUI/Atoms/Views/ProgressBar.swift +++ /dev/null @@ -1,81 +0,0 @@ -// -// ProgressBar.swift -// MVMCoreUI -// -// Created by Panth Patel on 5/3/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - -@objcMembers open class ProgressBar: UIProgressView, MVMCoreUIMoleculeViewProtocol, MVMCoreViewProtocol { - var isRounded = false - var thickness: CGFloat = 8.0 { - willSet(newValue) { - heightAnchor.constraint(equalToConstant: newValue).isActive = true - if isRounded { - layer.cornerRadius = newValue/2.0 - } else { - progressViewStyle = .bar - } - } - } - - public override init(frame: CGRect) { - super.init(frame: frame) - setupView() - } - - public required init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - setupView() - } - - init() { - super.init(frame: .zero) - setupView() - } - - // MARK: - MVMCoreViewProtocol - public func setupView() { - clipsToBounds = true - translatesAutoresizingMaskIntoConstraints = false - reset() - } - - public func updateView(_ size: CGFloat) { - } - - // MARK: - MVMCoreUIMoleculeViewProtocol - public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { - if let isRounded = json?.optionalBoolForKey("roundedRect") { - self.isRounded = isRounded - } - if let thickness = json?.optionalCGFloatForKey("thickness") { - self.thickness = thickness - } - if let percentage = json?["percent"] as? Float { - progress = percentage/100.0 - } - if let progressColor = json?.optionalStringForKey("progressColor") { - progressTintColor = UIColor.mfGet(forHex: progressColor) - } - if let backgroundColor = json?.optionalStringForKey("backgroundColor") { - trackTintColor = UIColor.mfGet(forHex: backgroundColor) - } - } - - public func reset() { - isRounded = false - thickness = 8 - progress = 0 - progressTintColor = UIColor.mfCerulean() - trackTintColor = UIColor.mfLightSilver() - } - - public static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - return 8 - } -} - - From ed7329cdcfe98b7f04e09d593c003847fbaf7e10 Mon Sep 17 00:00:00 2001 From: panxi Date: Thu, 17 Oct 2019 15:52:38 -0400 Subject: [PATCH 27/45] add progress bar --- MVMCoreUI/Atoms/Views/ProgressBar.swift | 81 +++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 MVMCoreUI/Atoms/Views/ProgressBar.swift diff --git a/MVMCoreUI/Atoms/Views/ProgressBar.swift b/MVMCoreUI/Atoms/Views/ProgressBar.swift new file mode 100644 index 00000000..a9333966 --- /dev/null +++ b/MVMCoreUI/Atoms/Views/ProgressBar.swift @@ -0,0 +1,81 @@ +// +// ProgressBar.swift +// MVMCoreUI +// +// Created by Panth Patel on 5/3/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class ProgressBar: UIProgressView, MVMCoreUIMoleculeViewProtocol, MVMCoreViewProtocol { + var isRounded = false + var thickness: CGFloat = 8.0 { + willSet(newValue) { + heightAnchor.constraint(equalToConstant: newValue).isActive = true + if isRounded { + layer.cornerRadius = newValue/2.0 + } else { + progressViewStyle = .bar + } + } + } + + public override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setupView() + } + + init() { + super.init(frame: .zero) + setupView() + } + + // MARK: - MVMCoreViewProtocol + public func setupView() { + clipsToBounds = true + translatesAutoresizingMaskIntoConstraints = false + reset() + } + + public func updateView(_ size: CGFloat) { + } + + // MARK: - MVMCoreUIMoleculeViewProtocol + public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + if let isRounded = json?.optionalBoolForKey("roundedRect") { + self.isRounded = isRounded + } + if let thickness = json?.optionalCGFloatForKey("thickness") { + self.thickness = thickness + } + if let percentage = json?["percent"] as? Float { + progress = percentage/100.0 + } + if let progressColor = json?.optionalStringForKey("progressColor") { + progressTintColor = UIColor.mfGet(forHex: progressColor) + } + if let backgroundColor = json?.optionalStringForKey("backgroundColor") { + trackTintColor = UIColor.mfGet(forHex: backgroundColor) + } + } + + public func reset() { + isRounded = false + thickness = 8 + progress = 0 + progressTintColor = UIColor.mfCerulean() + trackTintColor = UIColor.mfLightSilver() + } + + public static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return 8 + } +} + + From d94bbc1daee3a3b6cbdd4091cc2867adb362153d Mon Sep 17 00:00:00 2001 From: panxi Date: Thu, 17 Oct 2019 16:33:05 -0400 Subject: [PATCH 28/45] check property back to weak, remove unaided switch files which supposed replaced by mvmcoreuiswitch --- MVMCoreUI/Atoms/TextFields/MFTextField.h | 8 +- MVMCoreUI/Molecules/Switch.swift | 95 --------------- MVMCoreUI/Molecules/SwitchLineItem.swift | 140 ----------------------- 3 files changed, 4 insertions(+), 239 deletions(-) delete mode 100644 MVMCoreUI/Molecules/Switch.swift delete mode 100644 MVMCoreUI/Molecules/SwitchLineItem.swift diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.h b/MVMCoreUI/Atoms/TextFields/MFTextField.h index f7d8803c..abf54942 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.h +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.h @@ -44,10 +44,10 @@ @property (nonatomic,getter=isEnabled) BOOL enabled; // To set the placeholder and text -@property (nullable, strong, nonatomic) NSString *text; -@property (nullable, strong, nonatomic) NSString *formText; -@property (nullable, strong, nonatomic) NSString *fieldKey; -@property (nullable, strong, nonatomic) NSString *groupName; +@property (nullable, weak, nonatomic) NSString *text; +@property (nullable, weak, nonatomic) NSString *formText; +@property (nullable, weak, nonatomic) NSString *fieldKey; +@property (nullable, weak, nonatomic) NSString *groupName; @property (nullable, weak, nonatomic) NSString *placeholder; // will move out in Feb release diff --git a/MVMCoreUI/Molecules/Switch.swift b/MVMCoreUI/Molecules/Switch.swift deleted file mode 100644 index 8cb19909..00000000 --- a/MVMCoreUI/Molecules/Switch.swift +++ /dev/null @@ -1,95 +0,0 @@ -// -// Switch.swift -// MVMCoreUI -// -// Created by Priya on 5/23/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import UIKit - -@objcMembers public class Switch: ViewConstrainingView, FormValidationFormFieldProtocol { - public var mvmSwitch = MVMCoreUISwitch() - var isRequired = false - var delegateObject: DelegateObject? - - @objc func switchChanged() { - let delegate = delegateObject as? MVMCoreUIDelegateObject - if let delegate = delegate { - let formValidator = delegate.formValidationProtocol?.formValidatorModel?() - formValidator?.enableByValidation() - } - } - - open override func setupView() { - super.setupView() - mvmSwitch.addTarget(self, action: #selector(Switch.switchChanged), for: .valueChanged) - self.clipsToBounds = true - addSubview(mvmSwitch) - mvmSwitch.translatesAutoresizingMaskIntoConstraints = false - setupContainerConstraints() - } - - public override func updateView(_ size: CGFloat) { - super.updateView(size) - mvmSwitch.updateView(size) - } - - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - isRequired = json?[KeyRequired] as? Bool ?? false - self.delegateObject = delegateObject - if let delegateObject = delegateObject { - FormValidator.setupValidation(molecule: self, delegate: delegateObject.formValidationProtocol) - } - if let onColorString = json?.optionalStringForKey("onTintColor") { - mvmSwitch.onTintColor = .mfGet(forHex: onColorString) - } - if let offColorString = json?.optionalStringForKey("offTintColor") { - mvmSwitch.offTintColor = .mfGet(forHex: offColorString) - } - if let onKnobColorString = json?.optionalStringForKey("onKnobTintColor") { - mvmSwitch.onKnobTintColor = .mfGet(forHex: onKnobColorString) - } - if let offKnobColorString = json?.optionalStringForKey("offKnobTintColor") { - mvmSwitch.offKnobTintColor = .mfGet(forHex: offKnobColorString) - } - mvmSwitch.setState(json?.optionalBoolForKey("state") ?? false, animated: true) - } - - func setupContainerConstraints() { - mvmSwitch.topAnchor.constraint(equalTo: topAnchor).isActive = true - mvmSwitch.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true - mvmSwitch.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true - mvmSwitch.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true - } - - public func isValidField() -> Bool { - return (isRequired == false) ? true : mvmSwitch.isOn - } - - public func formFieldName() -> String? { - return json?.optionalStringForKey(KeyFieldKey) - } - - public func formFieldValue() -> Any? { - return mvmSwitch.isOn - } - - public func formFieldGroupName() -> String? { - return json?.optionalStringForKey("groupName") - } - - public override func needsToBeConstrained() -> Bool { - return true - } - - public override func alignment() -> UIStackView.Alignment { - return UIStackView.Alignment.leading - } - - public override static func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - return MVMCoreUISwitch.getHeight() - } -} - diff --git a/MVMCoreUI/Molecules/SwitchLineItem.swift b/MVMCoreUI/Molecules/SwitchLineItem.swift deleted file mode 100644 index 54860158..00000000 --- a/MVMCoreUI/Molecules/SwitchLineItem.swift +++ /dev/null @@ -1,140 +0,0 @@ -// -// SwitchLineItem.swift -// MVMCoreUI -// -// Created by Priya on 5/6/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import UIKit - -@objcMembers public class SwitchLineItem: ViewConstrainingView, FormValidationFormFieldProtocol { - - - public var mvmSwitch = Switch() - public var label = Label() - public var leftContainerView = UIView() - public var mfTextButton = MFTextButton(nil, constrainHeight: true, forWidth: 0) - var isRequired = false - var delegateObject: DelegateObject? - - @objc func switchChanged() { - let delegate = delegateObject as? MVMCoreUIDelegateObject - if let delegate = delegate { - let formValidator = delegate.formValidationProtocol?.formValidatorModel?() - formValidator?.enableByValidation() - } - } - - open override func setupView() { - super.setupView() - leftContainerView.addSubview(label) - leftContainerView.addSubview(mfTextButton) - addSubview(leftContainerView) - addSubview(mvmSwitch) - - leftContainerView.translatesAutoresizingMaskIntoConstraints = false - mvmSwitch.translatesAutoresizingMaskIntoConstraints = false - mfTextButton.translatesAutoresizingMaskIntoConstraints = false - label.translatesAutoresizingMaskIntoConstraints = false - setupContainerConstraints() - } - - public override func updateView(_ size: CGFloat) { - super.updateView(size) - label.updateView(size) - mvmSwitch.updateView(size) - mfTextButton.updateView(size) - } - - open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - mvmSwitch.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - label.setWithJSON(json?.optionalDictionaryForKey("label"), delegateObject: delegateObject, additionalData: additionalData) - mfTextButton.setWithJSON(json?.optionalDictionaryForKey("textButton"), delegateObject: delegateObject, additionalData: additionalData) - if (label.text?.count ?? 0) <= 0 && (mfTextButton.titleLabel?.text?.count ?? 0) <= 0 { - mvmSwitch.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0).isActive = true - } - } - - func setupContainerConstraints() { - leftContainerView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true - - var constraint = leftContainerView.topAnchor.constraint(equalTo: topAnchor) - constraint.priority = UILayoutPriority(249) - constraint.isActive = true - - mvmSwitch.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true - - constraint = mvmSwitch.topAnchor.constraint(equalTo: topAnchor) - constraint.priority = UILayoutPriority(249) - constraint.isActive = true - - trailingAnchor.constraint(equalTo: mvmSwitch.trailingAnchor).isActive = true - - constraint = bottomAnchor.constraint(equalTo: mvmSwitch.bottomAnchor) - constraint.priority = UILayoutPriority(249) - constraint.isActive = true - - bottomAnchor.constraint(greaterThanOrEqualTo: mvmSwitch.bottomAnchor).isActive = true - - constraint = bottomAnchor.constraint(equalTo: leftContainerView.bottomAnchor) - constraint.isActive = true - - bottomAnchor.constraint(greaterThanOrEqualTo: leftContainerView.bottomAnchor).isActive = true - leftContainerView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true - - NSLayoutConstraint.constraintPinSubview(leftContainerView, pinCenterX: false, pinCenterY: true) - constraint = mvmSwitch.leadingAnchor.constraint(greaterThanOrEqualTo: leftContainerView.trailingAnchor) - constraint.priority = UILayoutPriority(999) - constraint.isActive = true - NSLayoutConstraint.constraintPinSubview(mvmSwitch, pinCenterX: false, pinCenterY: true) - - leftContainerView.topAnchor.constraint(equalTo: label.topAnchor).isActive = true - leftContainerView.trailingAnchor.constraint(greaterThanOrEqualTo: label.trailingAnchor).isActive = true - - constraint = leftContainerView.trailingAnchor.constraint(equalTo: label.trailingAnchor) - constraint.priority = UILayoutPriority(249) - constraint.isActive = true - - leftContainerView.trailingAnchor.constraint(greaterThanOrEqualTo: mfTextButton.trailingAnchor).isActive = true - - constraint = leftContainerView.trailingAnchor.constraint(equalTo: mfTextButton.trailingAnchor) - constraint.priority = UILayoutPriority(249) - constraint.isActive = true - - leftContainerView.bottomAnchor.constraint(equalTo: mfTextButton.bottomAnchor).isActive = true - mfTextButton.leadingAnchor.constraint(equalTo: leftContainerView.leadingAnchor).isActive = true - label.leadingAnchor.constraint(equalTo: leftContainerView.leadingAnchor).isActive = true - mfTextButton.topAnchor.constraint(equalTo: label.bottomAnchor).isActive = true - leftContainerView.setContentHuggingPriority(.defaultHigh, for: .horizontal) - mvmSwitch.setContentHuggingPriority(.defaultLow, for: .horizontal) - } - - public override func needsToBeConstrained() -> Bool { - return true - } - - public override func alignment() -> UIStackView.Alignment { - return UIStackView.Alignment.leading - } - - - public func isValidField() -> Bool { - return mvmSwitch.isValidField() - } - - public func formFieldName() -> String? { - return mvmSwitch.formFieldName() - } - - public func formFieldGroupName() -> String? { - return mvmSwitch.formFieldGroupName() - } - - public func formFieldValue() -> Any? { - return mvmSwitch.formFieldValue() - } -} - - From 4e1a6ca479afac2939ce0dd1d46813cac2052f1f Mon Sep 17 00:00:00 2001 From: panxi Date: Thu, 17 Oct 2019 16:52:05 -0400 Subject: [PATCH 29/45] update based on scott's comments --- MVMCoreUI/Atoms/TextFields/MFTextField.h | 4 +- .../Strings/es-MX.lproj/Localizable.strings | 5 + .../Strings/es.lproj/Localizable.strings | 7 + .../Templates/MoleculeStackTemplate.swift | 144 +++++++++--------- 4 files changed, 86 insertions(+), 74 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.h b/MVMCoreUI/Atoms/TextFields/MFTextField.h index abf54942..8ccbe22e 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.h +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.h @@ -46,8 +46,8 @@ // To set the placeholder and text @property (nullable, weak, nonatomic) NSString *text; @property (nullable, weak, nonatomic) NSString *formText; -@property (nullable, weak, nonatomic) NSString *fieldKey; -@property (nullable, weak, nonatomic) NSString *groupName; +@property (nullable, strong, nonatomic) NSString *fieldKey; +@property (nullable, strong, nonatomic) NSString *groupName; @property (nullable, weak, nonatomic) NSString *placeholder; // will move out in Feb release diff --git a/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings index d6505503..93c5dda5 100644 --- a/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/es-MX.lproj/Localizable.strings @@ -37,6 +37,11 @@ "checkbox_checked_state" = "Verificado"; "checkbox_unchecked_state" = "Sin marcar"; "checkbox_desc_state" = "%@ Casilla %@"; +// Radio Button +"radio_action_hint" = "Toca dos veces para seleccionar."; +"radio_selected_state" = "Seleccionado"; +"radio_not_selected_state" = "No Seleccionado"; +"radio_desc_state" = "Opción"; // Switch "mfswitch_buttonlabel" = "Botón Cambiar"; "AccOn" = "encendido"; diff --git a/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings b/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings index d6505503..053c4b02 100644 --- a/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings +++ b/MVMCoreUI/SupportingFiles/Strings/es.lproj/Localizable.strings @@ -37,6 +37,13 @@ "checkbox_checked_state" = "Verificado"; "checkbox_unchecked_state" = "Sin marcar"; "checkbox_desc_state" = "%@ Casilla %@"; + +// Radio Button +"radio_action_hint" = "Toca dos veces para seleccionar."; +"radio_selected_state" = "Seleccionado"; +"radio_not_selected_state" = "No Seleccionado"; +"radio_desc_state" = "Opción"; + // Switch "mfswitch_buttonlabel" = "Botón Cambiar"; "AccOn" = "encendido"; diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 8515f9a4..d6f78b05 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -9,76 +9,76 @@ import UIKit open class MoleculeStackTemplate: ThreeLayerViewController { -var observer: NSKeyValueObservation? - -open override var loadObject: MVMCoreLoadObject? { -didSet { -if loadObject != oldValue { -updateRequiredModules() -observer?.invalidate() -if let newObject = loadObject { -observer = newObject.observe(\MVMCoreLoadObject.pageJSON, options: [.old, .new]) { [weak self] (object, change) in -self?.updateRequiredModules() -} -} -} -} -} - -open override func spaceBetweenTopAndMiddle() -> CGFloat? { -return 0 -} - -open override func viewForTop() -> UIView? { -guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { -return nil -} -return molecule -} - -open override func viewForMiddle() -> UIView? { -guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack") else { -return nil -} -let stack = MoleculeStackView(frame: .zero) -stack.useStackSpacingBeforeFirstItem = true -stack.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) -return stack -} - -override open func viewForBottom() -> UIView? { -guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { -return nil -} -return molecule -} - -// MARK: - cache handling -open override func pageTypesToListenFor() -> [Any]? { -guard let pageType = self.pageType else { -return super.pageTypesToListenFor() -} -return [pageType] -} - -open override func modulesToListenFor() -> [Any]? { -return loadObject?.requestParameters?.modules -} - -/// Adds modules from requiredModules() to the MVMCoreViewControllerMapping.requiredModules map. -open func updateRequiredModules() { -if let requiredModules = requiredModules(), let pageType = pageType { -MVMCoreViewControllerMappingObject.shared()?.addRequiredModules(toMapping: requiredModules, forPageType: pageType) -} -} - -/// Gets modules required by the loadObject.pageJSON. -open func requiredModules() -> [Any]? { -let modules: NSMutableArray = [] -let delegate = delegateObject() as? MVMCoreUIDelegateObject -MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: nil) -MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: nil) -MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack"), delegateObject: delegate, moduleList: modules, errorList: nil) -return modules as? [Any] -} + var observer: NSKeyValueObservation? + + open override var loadObject: MVMCoreLoadObject? { + didSet { + if loadObject != oldValue { + updateRequiredModules() + observer?.invalidate() + if let newObject = loadObject { + observer = newObject.observe(\MVMCoreLoadObject.pageJSON, options: [.old, .new]) { [weak self] (object, change) in + self?.updateRequiredModules() + } + } + } + } + } + + open override func spaceBetweenTopAndMiddle() -> CGFloat? { + return 0 + } + + open override func viewForTop() -> UIView? { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("header"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { + return nil + } + return molecule + } + + open override func viewForMiddle() -> UIView? { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack") else { + return nil + } + let stack = MoleculeStackView(frame: .zero) + stack.useStackSpacingBeforeFirstItem = true + stack.setWithJSON(moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, additionalData: nil) + return stack + } + + override open func viewForBottom() -> UIView? { + guard let moleculeJSON = loadObject?.pageJSON?.optionalDictionaryForKey("footer"), let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(forJSON: moleculeJSON, delegateObject: delegateObject() as? MVMCoreUIDelegateObject, constrainIfNeeded: true) else { + return nil + } + return molecule + } + + // MARK: - cache handling + open override func pageTypesToListenFor() -> [Any]? { + guard let pageType = self.pageType else { + return super.pageTypesToListenFor() + } + return [pageType] + } + + open override func modulesToListenFor() -> [Any]? { + return loadObject?.requestParameters?.modules + } + + /// Adds modules from requiredModules() to the MVMCoreViewControllerMapping.requiredModules map. + open func updateRequiredModules() { + if let requiredModules = requiredModules(), let pageType = pageType { + MVMCoreViewControllerMappingObject.shared()?.addRequiredModules(toMapping: requiredModules, forPageType: pageType) + } + } + + /// Gets modules required by the loadObject.pageJSON. + open func requiredModules() -> [Any]? { + let modules: NSMutableArray = [] + let delegate = delegateObject() as? MVMCoreUIDelegateObject + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: nil) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: nil) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack"), delegateObject: delegate, moduleList: modules, errorList: nil) + return modules as? [Any] + } } From f1c319244a1e7c04e9c79e60362714b209f4cfba Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 21 Oct 2019 17:26:33 -0400 Subject: [PATCH 30/45] radioButton and radioButtonWithLabel and code review --- MVMCoreUI.xcodeproj/project.pbxproj | 4 + MVMCoreUI/Atoms/Buttons/PrimaryButton.m | 2 +- MVMCoreUI/Atoms/TextFields/MFTextField.m | 26 ++-- .../FormValidationProtocol.swift | 2 +- MVMCoreUI/FormUIHelpers/FormValidator.swift | 11 +- MVMCoreUI/Molecules/RadioButton.swift | 73 ++--------- .../Molecules/RadioButtonWithLabel.swift | 117 ++++++++++++++++++ .../MVMCoreUIMoleculeMappingObject.m | 1 + 8 files changed, 156 insertions(+), 80 deletions(-) create mode 100644 MVMCoreUI/Molecules/RadioButtonWithLabel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 78207194..2b965e63 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */; }; 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; + 01FC09E3235E246D003AC9B3 /* RadioButtonWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01FC09E2235E246D003AC9B3 /* RadioButtonWithLabel.swift */; }; 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; }; 0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */; }; 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; @@ -212,6 +213,7 @@ 0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = ""; }; 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = ""; }; 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = ""; }; + 01FC09E2235E246D003AC9B3 /* RadioButtonWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonWithLabel.swift; sourceTree = ""; }; 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = ""; }; 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; @@ -573,6 +575,7 @@ D2A514662213885800345BFB /* StandardHeaderView.swift */, D274CA322236A78900B01B62 /* StandardFooterView.swift */, 01004F2F22721C3800991ECC /* RadioButton.swift */, + 01FC09E2235E246D003AC9B3 /* RadioButtonWithLabel.swift */, 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */, D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */, @@ -1059,6 +1062,7 @@ D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */, D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */, D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */, + 01FC09E3235E246D003AC9B3 /* RadioButtonWithLabel.swift in Sources */, D282AACB2243C61700C46919 /* ButtonView.swift in Sources */, D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m index 33cadc8c..e4f889eb 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m @@ -783,7 +783,7 @@ return self.validationRequired; } -- (NSArray *)requiredFields { +- (NSArray *)requiredGroups { return self.requiredFieldsList; } diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField.m b/MVMCoreUI/Atoms/TextFields/MFTextField.m index 28cd5343..cfef9090 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField.m +++ b/MVMCoreUI/Atoms/TextFields/MFTextField.m @@ -301,20 +301,30 @@ return; } - self.formText = [map string:KeyLabel]; - self.groupName = [map string:@"groupName"]; - self.errMessage = [map string:KeyErrorMessage]; - self.fieldKey = [map string:KeyFieldKey]; - - NSString *string = [map stringForKey:KeyValue]; - if (string.length) { + NSString *string = [map string:KeyLabel]; + if (string.length > 0) { + self.formText = string; + } + string = [map string:KeyValue]; + if (string.length > 0) { self.text = string; } - string = [map stringForKey:KeyDisable]; if ([string isEqual:StringY] || [map boolForKey:KeyDisable]) { [self enable:NO]; } + string = [map string:KeyErrorMessage]; + if (string.length > 0) { + self.errMessage = string; + } + + // key used to send text value to server + string = [map string:KeyFieldKey]; + if (string.length > 0) { + self.fieldKey = string; + } + + self.groupName = [map string:@"groupName"]; string = [map string:KeyType]; if ([string isEqualToString:@"dropDown"]) { diff --git a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift index 27f3f754..49cfacc9 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift @@ -37,5 +37,5 @@ import Foundation @objc optional func enableField(_ enable: Bool) // Returns the list of field keys required to enable/disable - @objc optional func requiredFields() -> [String]? + @objc optional func requiredGroups() -> [String]? } diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index c3cc77fa..fe23da84 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -49,15 +49,15 @@ import MVMCore public func enableByValidation() { for molecule in enableDisableMolecules { - if let requiredFeilds = molecule.requiredFields?(), requiredFeilds.count > 0 { - enableWithGroupName(requiredFeilds, molecule) + if let requiredFields = molecule.requiredGroups?(), requiredFields.count > 0 { + enableWithGroups(requiredFields, molecule) } else { enableIgnoreGroupName(molecule) } } } - public func enableWithGroupName(_ requiredGroupList: [String], _ enableDisableMolecules: FormValidationEnableDisableProtocol) { + public func enableWithGroups(_ requiredGroupList: [String], _ enableDisableMolecule: FormValidationEnableDisableProtocol) { var groupValidityMap: [String: Bool] = [:] for molecule in fieldMolecules { @@ -70,13 +70,16 @@ import MVMCore for groupName in requiredGroupList { valid = groupValidityMap[groupName] ?? false } - enableDisableMolecules.enableField?(valid) + enableDisableMolecule.enableField?(valid) } public func enableIgnoreGroupName(_ enableDisableMolecules: FormValidationEnableDisableProtocol) { var valid = true for molecule in fieldMolecules { valid = valid && molecule.isValidField() + if (!valid) { + break + } } let enableField = valid && (extraValidationBlock?() ?? true) enableDisableMolecules.enableField?(enableField) diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index 53fbaefc..a161272a 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -8,19 +8,15 @@ import UIKit - @objcMembers open class RadioButton: ViewConstrainingView, FormValidationFormFieldProtocol { public let radioButton = MFRadioButton() var delegateObject: MVMCoreUIDelegateObject? - var dummyButton: MFCustomButton? - let label = Label() - + var fieldKey: String? var formValue: Bool? var isRequired: Bool = false var radioButtonModel: RadioButtonModel? - lazy var radioGroupName: String? = { [unowned self] in @@ -53,49 +49,11 @@ import UIKit isAccessibilityElement = true accessibilityTraits = .none accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") - - radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true - radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true - bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true - radioButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + NSLayoutConstraint.constraintPinSubview(toSuperview: radioButton) - if let rightView = createRightView() { - addSubview(rightView) - rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true - rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true - - var constraint = rightView.topAnchor.constraint(equalTo: topAnchor, constant: PaddingOne) - constraint.priority = .defaultHigh - constraint.isActive = true - - constraint = bottomAnchor.constraint(equalTo: rightView.bottomAnchor, constant: PaddingOne) - constraint.priority = .defaultHigh - constraint.isActive = true - } - addActionHandler() - } - - func createRightView() -> ViewConstrainingView? { - let rightView = ViewConstrainingView(constrainingView: label) - return rightView - } - - func addActionHandler() { - - guard dummyButton == nil else { - return - } - - let dummyButton = MFCustomButton(frame: .zero) - self.dummyButton = dummyButton - dummyButton.translatesAutoresizingMaskIntoConstraints = false - addSubview(dummyButton) - NSLayoutConstraint.constraintPinSubview(toSuperview: dummyButton) - bringSubviewToFront(dummyButton) - - dummyButton.add({ [weak self] (button) in + radioButton.performActionForCheck = { [weak self] in self?.tapAction() - }, for: .touchUpInside) + } } func tapAction() { @@ -105,7 +63,6 @@ import UIKit radioButton.isSelected = !radioButton.isSelected } FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) - changeAccessibilityLabel() } public func isValidField() -> Bool { @@ -138,28 +95,12 @@ extension RadioButton { } fieldKey = jsonDictionary.optionalStringForKey("fieldKey") - isRequired = jsonDictionary.boolForKey("required") + isRequired = jsonDictionary.boolForKey("required") self.delegateObject = delegateObject let radioButtonModel = RadioButtonModel.setupForRadioButtonGroup(radioButton: self, - formValidator: delegateObject?.formValidationProtocol?.formValidatorModel?()) + formValidator: delegateObject?.formValidationProtocol?.formValidatorModel?()) FormValidator.setupValidation(molecule: radioButtonModel, delegate: delegateObject?.formValidationProtocol) - self.radioButtonModel = radioButtonModel - - label.setWithJSON(jsonDictionary.optionalDictionaryForKey(KeyLabel), - delegateObject: delegateObject, - additionalData: additionalData) - changeAccessibilityLabel() - } -} - -// MARK: Accessibility -extension RadioButton { - func changeAccessibilityLabel() { - let stateString = radioButton.isSelected ? "radio_selected_state" : "radio_not_selected_state" - let localizedStringState = MVMCoreUIUtility.hardcodedString(withKey: stateString) ?? "" - let accebilityString = (label.accessibilityLabel ?? (json?.optionalStringForKey("accessibilityText") ?? "")) - + (MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "") + localizedStringState - accessibilityLabel = accebilityString + self.radioButtonModel = radioButtonModel } } diff --git a/MVMCoreUI/Molecules/RadioButtonWithLabel.swift b/MVMCoreUI/Molecules/RadioButtonWithLabel.swift new file mode 100644 index 00000000..3dc5f6e5 --- /dev/null +++ b/MVMCoreUI/Molecules/RadioButtonWithLabel.swift @@ -0,0 +1,117 @@ +// +// RadioButtonWithLabel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 10/21/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +@objcMembers open class RadioButtonWithLabel: ViewConstrainingView { + + public let radioButton = RadioButton() + var delegateObject: MVMCoreUIDelegateObject? + var dummyButton: MFCustomButton? + let label = Label() + + // MARK: - Inits + public init() { + super.init(frame: .zero) + } + + public override init(frame: CGRect) { + super.init(frame: frame) + } + + required public init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + open override func setupView() { + super.setupView() + guard subviews.count == 0 else { + return + } + + translatesAutoresizingMaskIntoConstraints = false + radioButton.translatesAutoresizingMaskIntoConstraints = false + addSubview(radioButton) + + isAccessibilityElement = true + accessibilityTraits = .none + accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") + + radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true + radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true + bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true + radioButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + + if let rightView = createRightView() { + addSubview(rightView) + rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true + rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true + + var constraint = rightView.topAnchor.constraint(equalTo: topAnchor, constant: PaddingOne) + constraint.priority = .defaultHigh + constraint.isActive = true + + constraint = bottomAnchor.constraint(equalTo: rightView.bottomAnchor, constant: PaddingOne) + constraint.priority = .defaultHigh + constraint.isActive = true + } + addActionHandler() + } + + func createRightView() -> ViewConstrainingView? { + let rightView = ViewConstrainingView(constrainingView: label) + return rightView + } + + func addActionHandler() { + + guard dummyButton == nil else { + return + } + + let dummyButton = MFCustomButton(frame: .zero) + self.dummyButton = dummyButton + dummyButton.translatesAutoresizingMaskIntoConstraints = false + addSubview(dummyButton) + NSLayoutConstraint.constraintPinSubview(toSuperview: dummyButton) + bringSubviewToFront(dummyButton) + + dummyButton.add({ [weak self] (button) in + self?.tapAction() + }, for: .touchUpInside) + } + + func tapAction() { + radioButton.tapAction() + changeAccessibilityLabel() + } +} + +// MARK: - MVMCoreUIMoleculeViewProtocol +extension RadioButtonWithLabel { + @objc open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + self.delegateObject = delegateObject + radioButton.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + label.setWithJSON(json?.optionalDictionaryForKey(KeyLabel), + delegateObject: delegateObject, + additionalData: additionalData) + changeAccessibilityLabel() + } +} + +// MARK: Accessibility +extension RadioButtonWithLabel { + func changeAccessibilityLabel() { + let stateString = radioButton.radioButton.isSelected ? "radio_selected_state" : "radio_not_selected_state" + let localizedStringState = MVMCoreUIUtility.hardcodedString(withKey: stateString) ?? "" + let accebilityString = (label.accessibilityLabel ?? (json?.optionalStringForKey("accessibilityText") ?? "")) + + (MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "") + localizedStringState + accessibilityLabel = accebilityString + } +} diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 27302b20..6c2100f3 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -45,6 +45,7 @@ @"multiProgressBar": MultiProgress.class, @"checkbox": MVMCoreUICheckBox.class, @"radioButton": RadioButton.class, + @"radioButtonLabel": RadioButtonWithLabel.class, @"listItem": MoleculeTableViewCell.class, @"accordionListItem": AccordionMoleculeTableViewCell.class, @"switch": MVMCoreUISwitch.class, From fcb377df33e4645d8c3c8546feb67be1c48af279 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 22 Oct 2019 09:13:07 -0400 Subject: [PATCH 31/45] space --- MVMCoreUI/Molecules/RadioButton.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index a161272a..57115d68 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -70,7 +70,7 @@ import UIKit } public func formFieldName() -> String? { - return json?.optionalStringForKey("fieldKey") + return json?.optionalStringForKey("fieldKey") } public func formFieldGroupName() -> String? { From 4ef662d1cad00adef17d1d111d47dff11d915291 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 22 Oct 2019 09:59:37 -0400 Subject: [PATCH 32/45] reivew --- MVMCoreUI/Molecules/RadioButton.swift | 14 +++++++++++--- MVMCoreUI/Molecules/RadioButtonModel.swift | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Molecules/RadioButton.swift index 57115d68..059bc5b6 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Molecules/RadioButton.swift @@ -16,12 +16,21 @@ import UIKit var fieldKey: String? var formValue: Bool? var isRequired: Bool = false - var radioButtonModel: RadioButtonModel? - + lazy var radioGroupName: String? = { [unowned self] in return json?.optionalStringForKey("radioGroupName") ?? json?.optionalStringForKey("fieldKey") }() + + lazy var radioButtonModel: RadioButtonModel? = { + [unowned self] in + if let radioGroupName = radioGroupName, + let radioButtonModel = delegateObject?.formValidationProtocol?.formValidatorModel?()?.radioButtonsModelByGroup[radioGroupName] { + return radioButtonModel + } else { + return nil + } + }() // MARK: - Inits public init() { @@ -101,6 +110,5 @@ extension RadioButton { let radioButtonModel = RadioButtonModel.setupForRadioButtonGroup(radioButton: self, formValidator: delegateObject?.formValidationProtocol?.formValidatorModel?()) FormValidator.setupValidation(molecule: radioButtonModel, delegate: delegateObject?.formValidationProtocol) - self.radioButtonModel = radioButtonModel } } diff --git a/MVMCoreUI/Molecules/RadioButtonModel.swift b/MVMCoreUI/Molecules/RadioButtonModel.swift index 68e95790..a72bd889 100644 --- a/MVMCoreUI/Molecules/RadioButtonModel.swift +++ b/MVMCoreUI/Molecules/RadioButtonModel.swift @@ -49,6 +49,6 @@ extension RadioButtonModel: FormValidationFormFieldProtocol { } // The field value key value pair for sending to server @objc public func formFieldValue() -> Any? { - return selectedRadioButton != nil ? true : false + return selectedRadioButton != nil ? true : false } } From b79b999910969344b908d81fa5e2d070cc94879c Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 22 Oct 2019 11:04:22 -0400 Subject: [PATCH 33/45] added secondary. --- MVMCoreUI/Molecules/HeadlineBodyButton.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Molecules/HeadlineBodyButton.swift b/MVMCoreUI/Molecules/HeadlineBodyButton.swift index 2922f0f2..e3281d35 100644 --- a/MVMCoreUI/Molecules/HeadlineBodyButton.swift +++ b/MVMCoreUI/Molecules/HeadlineBodyButton.swift @@ -90,6 +90,7 @@ import UIKit headlineBody.headlineLabel.font = MFStyler.fontH3() headlineBody.messageLabel.font = MFStyler.fontB3() button.setAsTiny(true) + button.setAsSecondaryCustom() button.isHidden = false buttonHeadlinePadding = PaddingTwo } From 2248b36ccbd9fd2d51d0389bf359356501a09d7c Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 22 Oct 2019 11:10:06 -0400 Subject: [PATCH 34/45] one less body. --- MVMCoreUI/Molecules/HeadlineBodyButton.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Molecules/HeadlineBodyButton.swift b/MVMCoreUI/Molecules/HeadlineBodyButton.swift index e3281d35..87efc9b6 100644 --- a/MVMCoreUI/Molecules/HeadlineBodyButton.swift +++ b/MVMCoreUI/Molecules/HeadlineBodyButton.swift @@ -124,7 +124,7 @@ import UIKit buttonHeadlinePadding = padding } - headlineBody.setWithJSON(dictionary.optionalDictionaryForKey("headlineBodyBody"), delegateObject: delegateObject, additionalData: additionalData) + headlineBody.setWithJSON(dictionary.optionalDictionaryForKey("headlineBody"), delegateObject: delegateObject, additionalData: additionalData) if let buttonDictionary = dictionary.optionalDictionaryForKey("button") { button.setWithJSON(buttonDictionary, delegateObject: delegateObject, additionalData: additionalData) From 9b86b4449fda763349a289f4c54de908ac3b14d4 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 22 Oct 2019 11:54:13 -0400 Subject: [PATCH 35/45] dcsds --- MVMCoreUI/Molecules/ActionDetailWithImage.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Molecules/ActionDetailWithImage.swift b/MVMCoreUI/Molecules/ActionDetailWithImage.swift index 76dde8e6..86cee41b 100644 --- a/MVMCoreUI/Molecules/ActionDetailWithImage.swift +++ b/MVMCoreUI/Molecules/ActionDetailWithImage.swift @@ -101,8 +101,8 @@ import UIKit private func setDefaultState() { - headlineBodyButton.headline.headlineLabel.font = MFStyler.fontH3() - headlineBodyButton.headline.messageLabel.font = MFStyler.fontB3() + headlineBodyButton.headlineBody.headlineLabel.font = MFStyler.fontH3() + headlineBodyButton.headlineBody.messageLabel.font = MFStyler.fontB3() imageLoader.imageView.contentMode = .scaleAspectFit imageLoader.addSizeConstraintsForAspectRatio = true buttonHeaderPadding = PaddingTwo From 5ee34fb027c26b6d69e099a7b9a8ed001ab8e0d7 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 22 Oct 2019 15:11:16 -0400 Subject: [PATCH 36/45] dummy group --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index fe23da84..d11e4847 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -49,16 +49,16 @@ import MVMCore public func enableByValidation() { for molecule in enableDisableMolecules { - if let requiredFields = molecule.requiredGroups?(), requiredFields.count > 0 { - enableWithGroups(requiredFields, molecule) - } else { - enableIgnoreGroupName(molecule) + var requiredFields = molecule.requiredGroups?() ?? [dummyGroupName] + if requiredFields.count == 0 { + requiredFields = [dummyGroupName] } + enableWithGroups(requiredFields, molecule) } } public func enableWithGroups(_ requiredGroupList: [String], _ enableDisableMolecule: FormValidationEnableDisableProtocol) { - + var groupValidityMap: [String: Bool] = [:] for molecule in fieldMolecules { let valid = molecule.isValidField() @@ -66,9 +66,9 @@ import MVMCore groupValidityMap[groupName] = valid && (groupValidityMap[groupName] ?? true) } - var valid = false + var valid = true for groupName in requiredGroupList { - valid = groupValidityMap[groupName] ?? false + valid = valid && groupValidityMap[groupName] ?? false } enableDisableMolecule.enableField?(valid) } From b8bdf4829ec0efead7ed0f07efe1fde498ca0aa6 Mon Sep 17 00:00:00 2001 From: "Chintakrinda, Arun Kumar (Arun)" Date: Wed, 23 Oct 2019 18:21:38 +0530 Subject: [PATCH 37/45] Fix for label and molecule stack --- MVMCoreUI/Atoms/Views/Label.swift | 2 +- MVMCoreUI/Organisms/MoleculeStackView.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label.swift b/MVMCoreUI/Atoms/Views/Label.swift index 6fc496bd..52ee43d1 100644 --- a/MVMCoreUI/Atoms/Views/Label.swift +++ b/MVMCoreUI/Atoms/Views/Label.swift @@ -308,7 +308,7 @@ public typealias ActionBlock = () -> () guard let actionLabel = label as? Label else { continue } actionLabel.addActionAttributes(range: range, string: attributedString) - let actionBlock = actionLabel.createActionBlockFrom(actionMap: json, additionalData: additionalData, delegateObject: delegate) + let actionBlock = actionLabel.createActionBlockFrom(actionMap: attribute, additionalData: additionalData, delegateObject: delegate) actionLabel.appendActionableClause(range: range, actionBlock: actionBlock) default: diff --git a/MVMCoreUI/Organisms/MoleculeStackView.swift b/MVMCoreUI/Organisms/MoleculeStackView.swift index 14ad9e70..95855f52 100644 --- a/MVMCoreUI/Organisms/MoleculeStackView.swift +++ b/MVMCoreUI/Organisms/MoleculeStackView.swift @@ -190,7 +190,7 @@ public class MoleculeStackView: ViewConstrainingView { return "stack<>" } var name = "stack<" - for case let item as [AnyHashable: AnyHashable] in molecules { + for case let item as [AnyHashable: Any] in molecules { if let molecule = item.optionalDictionaryForKey(KeyMolecule), let moleculeName = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(withJSON: molecule)?.name?(forReuse: molecule, delegateObject: delegateObject) ?? molecule.optionalStringForKey(KeyMoleculeName) { name.append(moleculeName + ",") } From 75632696804d4ebb44e84e07a2d6e1ca659a47b3 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 23 Oct 2019 10:36:32 -0400 Subject: [PATCH 38/45] changes to test --- MVMCoreUI.xcodeproj/project.pbxproj | 18 ++++- .../Views}/RadioButton.swift | 72 +++++++++---------- MVMCoreUI/BaseClasses/Control.swift | 52 ++++++++++++++ MVMCoreUI/BaseClasses/View.swift | 52 ++++++++++++++ MVMCoreUI/Molecules/RadioButtonModel.swift | 4 +- .../Molecules/RadioButtonWithLabel.swift | 4 +- 6 files changed, 160 insertions(+), 42 deletions(-) rename MVMCoreUI/{Molecules => Atoms/Views}/RadioButton.swift (78%) create mode 100644 MVMCoreUI/BaseClasses/Control.swift create mode 100644 MVMCoreUI/BaseClasses/View.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 2b965e63..4389ff65 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -182,6 +182,8 @@ D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A638FC22CA98280052ED1F /* HeadlineBody.swift */; }; D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390022CBB1820052ED1F /* Carousel.swift */; }; D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */; }; + D2B18B7F2360913400A9AEDC /* Control.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B7E2360913400A9AEDC /* Control.swift */; }; + D2B18B812360945C00A9AEDC /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B18B802360945C00A9AEDC /* View.swift */; }; D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */; }; D2C5001821F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */; }; @@ -377,6 +379,8 @@ D2A638FC22CA98280052ED1F /* HeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBody.swift; sourceTree = ""; }; D2A6390022CBB1820052ED1F /* Carousel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Carousel.swift; sourceTree = ""; }; D2A6390422CBCE160052ED1F /* MoleculeCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeCollectionViewCell.swift; sourceTree = ""; }; + D2B18B7E2360913400A9AEDC /* Control.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Control.swift; sourceTree = ""; }; + D2B18B802360945C00A9AEDC /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = ""; }; D2B1E3E422F37D6A0065F95C /* ImageHeadlineBody.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageHeadlineBody.swift; sourceTree = ""; }; D2C5001621F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewControllerMappingObject.h; sourceTree = ""; }; D2C5001721F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIViewControllerMappingObject.m; sourceTree = ""; }; @@ -508,6 +512,7 @@ D29DF0CE21E404D4003B2FB9 /* MVMCoreUI */ = { isa = PBXGroup; children = ( + D2B18B7D236090D500A9AEDC /* BaseClasses */, 01C74D87224298E2009C25A3 /* FormUIHelpers */, D29DF31421ECECA7003B2FB9 /* SupportingFiles */, D29DF27021E79B2C003B2FB9 /* OtherHandlers */, @@ -574,7 +579,6 @@ D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */, D2A514662213885800345BFB /* StandardHeaderView.swift */, D274CA322236A78900B01B62 /* StandardFooterView.swift */, - 01004F2F22721C3800991ECC /* RadioButton.swift */, 01FC09E2235E246D003AC9B3 /* RadioButtonWithLabel.swift */, 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */, D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, @@ -740,6 +744,7 @@ 0198F7A22256A80A0066C936 /* MFRadioButton.m */, 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */, + 01004F2F22721C3800991ECC /* RadioButton.swift */, ); path = Views; sourceTree = ""; @@ -858,6 +863,15 @@ path = Strings; sourceTree = ""; }; + D2B18B7D236090D500A9AEDC /* BaseClasses */ = { + isa = PBXGroup; + children = ( + D2B18B7E2360913400A9AEDC /* Control.swift */, + D2B18B802360945C00A9AEDC /* View.swift */, + ); + path = BaseClasses; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -1033,6 +1047,7 @@ D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, D29DF25321E6A177003B2FB9 /* MFDigitTextField.m in Sources */, + D2B18B7F2360913400A9AEDC /* Control.swift in Sources */, D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */, DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */, D224798C231450C8003FCCF9 /* HeadlineBodySwitch.swift in Sources */, @@ -1059,6 +1074,7 @@ D28B4F8B21FF967C00712C7A /* MVMCoreUIObject.m in Sources */, 0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */, D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */, + D2B18B812360945C00A9AEDC /* View.swift in Sources */, D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */, D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */, D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */, diff --git a/MVMCoreUI/Molecules/RadioButton.swift b/MVMCoreUI/Atoms/Views/RadioButton.swift similarity index 78% rename from MVMCoreUI/Molecules/RadioButton.swift rename to MVMCoreUI/Atoms/Views/RadioButton.swift index 059bc5b6..5b0d0c00 100644 --- a/MVMCoreUI/Molecules/RadioButton.swift +++ b/MVMCoreUI/Atoms/Views/RadioButton.swift @@ -8,9 +8,12 @@ import UIKit -@objcMembers open class RadioButton: ViewConstrainingView, FormValidationFormFieldProtocol { +@objcMembers public class RadioButton: Control, FormValidationFormFieldProtocol { + + var diameter = 30 + var enabledColor = UIColor.black + var disabledColor = UIColor.mfSilver() - public let radioButton = MFRadioButton() var delegateObject: MVMCoreUIDelegateObject? var fieldKey: String? @@ -32,50 +35,25 @@ import UIKit } }() + open override func draw(_ rect: CGRect) { + guard let context = UIGraphicsGetCurrentContext() else { return } + context.addEllipse(in: CGRect(x: bounds.width*0.2, y: bounds.height*0.2, width: bounds.width*0.6, height: bounds.height*0.6)) + context.setFillColor(isUserInteractionEnabled ? enabledColor.cgColor : disabledColor.cgColor) + context.fillPath() + } + // MARK: - Inits - public init() { - super.init(frame: .zero) - } - - public override init(frame: CGRect) { - super.init(frame: frame) - } - - required public init?(coder aDecoder: NSCoder) { - super.init(coder: aDecoder) - } - - open override func setupView() { - super.setupView() - guard subviews.count == 0 else { - return - } - - translatesAutoresizingMaskIntoConstraints = false - radioButton.translatesAutoresizingMaskIntoConstraints = false - addSubview(radioButton) - - isAccessibilityElement = true - accessibilityTraits = .none - accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") - NSLayoutConstraint.constraintPinSubview(toSuperview: radioButton) - - radioButton.performActionForCheck = { [weak self] in - self?.tapAction() - } - } - func tapAction() { if let radioButtonModel = radioButtonModel { radioButtonModel.selected(self) } else { - radioButton.isSelected = !radioButton.isSelected + isSelected = !isSelected } FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) } public func isValidField() -> Bool { - return radioButton.isSelected + return isSelected } public func formFieldName() -> String? { @@ -87,7 +65,27 @@ import UIKit } public func formFieldValue() -> Any? { - return radioButton.isSelected + return isSelected + } + +// MARK: - MVMViewProtocol + open override func setupView() { + super.setupView() + guard subviews.count == 0 else { + return + } + + /*translatesAutoresizingMaskIntoConstraints = false + addSubview(radioButton) + + isAccessibilityElement = true + accessibilityTraits = .none + accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") + NSLayoutConstraint.constraintPinSubview(toSuperview: radioButton) + + radioButton.performActionForCheck = { [weak self] in + self?.tapAction() + }*/ } } diff --git a/MVMCoreUI/BaseClasses/Control.swift b/MVMCoreUI/BaseClasses/Control.swift new file mode 100644 index 00000000..bad1a6c8 --- /dev/null +++ b/MVMCoreUI/BaseClasses/Control.swift @@ -0,0 +1,52 @@ +// +// Control.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 10/23/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +public class Control: UIControl { + var json: [AnyHashable: Any]? + + public override init(frame: CGRect) { + super.init(frame: .zero) + setupView() + } + + init() { + super.init(frame: .zero) + setupView() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + setupView() + } +} + +extension Control: MVMCoreViewProtocol { + public func updateView(_ size: CGFloat) { + } + + public func setupView() { + translatesAutoresizingMaskIntoConstraints = false + insetsLayoutMarginsFromSafeArea = false + } +} + +extension Control: MVMCoreUIMoleculeViewProtocol { + public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + self.json = json + + if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) { + backgroundColor = UIColor.mfGet(forHex: backgroundColorString) + } + } + + public func reset() { + backgroundColor = .clear + } +} diff --git a/MVMCoreUI/BaseClasses/View.swift b/MVMCoreUI/BaseClasses/View.swift new file mode 100644 index 00000000..25b750b0 --- /dev/null +++ b/MVMCoreUI/BaseClasses/View.swift @@ -0,0 +1,52 @@ +// +// View.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 10/23/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + +public class View: UIView { + var json: [AnyHashable: Any]? + + public override init(frame: CGRect) { + super.init(frame: .zero) + setupView() + } + + init() { + super.init(frame: .zero) + setupView() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + setupView() + } +} + +extension View: MVMCoreViewProtocol { + public func updateView(_ size: CGFloat) { + } + + public func setupView() { + translatesAutoresizingMaskIntoConstraints = false + insetsLayoutMarginsFromSafeArea = false + } +} + +extension View: MVMCoreUIMoleculeViewProtocol { + public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { + self.json = json + + if let backgroundColorString = json?.optionalStringForKey(KeyBackgroundColor) { + backgroundColor = UIColor.mfGet(forHex: backgroundColorString) + } + } + + public func reset() { + backgroundColor = .clear + } +} diff --git a/MVMCoreUI/Molecules/RadioButtonModel.swift b/MVMCoreUI/Molecules/RadioButtonModel.swift index a72bd889..e2e6b27b 100644 --- a/MVMCoreUI/Molecules/RadioButtonModel.swift +++ b/MVMCoreUI/Molecules/RadioButtonModel.swift @@ -27,9 +27,9 @@ import UIKit } public func selected(_ radioButton: RadioButton) { - selectedRadioButton?.radioButton.isSelected = false + selectedRadioButton?.isSelected = false selectedRadioButton = radioButton - selectedRadioButton?.radioButton.isSelected = true + selectedRadioButton?.isSelected = true } } diff --git a/MVMCoreUI/Molecules/RadioButtonWithLabel.swift b/MVMCoreUI/Molecules/RadioButtonWithLabel.swift index 3dc5f6e5..4f42067a 100644 --- a/MVMCoreUI/Molecules/RadioButtonWithLabel.swift +++ b/MVMCoreUI/Molecules/RadioButtonWithLabel.swift @@ -8,7 +8,7 @@ import UIKit -@objcMembers open class RadioButtonWithLabel: ViewConstrainingView { +@objcMembers public class RadioButtonWithLabel: ViewConstrainingView { public let radioButton = RadioButton() var delegateObject: MVMCoreUIDelegateObject? @@ -108,7 +108,7 @@ extension RadioButtonWithLabel { // MARK: Accessibility extension RadioButtonWithLabel { func changeAccessibilityLabel() { - let stateString = radioButton.radioButton.isSelected ? "radio_selected_state" : "radio_not_selected_state" + let stateString = radioButton.isSelected ? "radio_selected_state" : "radio_not_selected_state" let localizedStringState = MVMCoreUIUtility.hardcodedString(withKey: stateString) ?? "" let accebilityString = (label.accessibilityLabel ?? (json?.optionalStringForKey("accessibilityText") ?? "")) + (MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "") + localizedStringState From 0b364fa004d0e885dd1c81dc3ba602e999cfcfb0 Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 23 Oct 2019 11:32:34 -0400 Subject: [PATCH 39/45] Radio button changes --- MVMCoreUI/Atoms/Views/RadioButton.swift | 55 +++++++++++++------- MVMCoreUI/Atoms/Views/ViewConstrainingView.m | 12 ++--- MVMCoreUI/BaseClasses/Control.swift | 16 ++++-- MVMCoreUI/BaseClasses/View.swift | 38 +++++++++----- 4 files changed, 77 insertions(+), 44 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/RadioButton.swift b/MVMCoreUI/Atoms/Views/RadioButton.swift index 5b0d0c00..6347a862 100644 --- a/MVMCoreUI/Atoms/Views/RadioButton.swift +++ b/MVMCoreUI/Atoms/Views/RadioButton.swift @@ -10,7 +10,11 @@ import UIKit @objcMembers public class RadioButton: Control, FormValidationFormFieldProtocol { - var diameter = 30 + var diameter: CGFloat = 30 { + didSet { + widthConstraint?.constant = diameter + } + } var enabledColor = UIColor.black var disabledColor = UIColor.mfSilver() @@ -19,6 +23,9 @@ import UIKit var fieldKey: String? var formValue: Bool? var isRequired: Bool = false + + var widthConstraint: NSLayoutConstraint? + var heightConstraint: NSLayoutConstraint? lazy var radioGroupName: String? = { [unowned self] in @@ -37,12 +44,19 @@ import UIKit open override func draw(_ rect: CGRect) { guard let context = UIGraphicsGetCurrentContext() else { return } - context.addEllipse(in: CGRect(x: bounds.width*0.2, y: bounds.height*0.2, width: bounds.width*0.6, height: bounds.height*0.6)) - context.setFillColor(isUserInteractionEnabled ? enabledColor.cgColor : disabledColor.cgColor) - context.fillPath() + let color = isEnabled ? enabledColor.cgColor : disabledColor.cgColor + layer.cornerRadius = bounds.width * 0.5 + layer.borderColor = color + layer.borderWidth = bounds.width * 0.0333 + if isSelected { + // Space around inner circle is 1/5 the size + context.addEllipse(in: CGRect(x: bounds.width*0.2, y: bounds.height*0.2, width: bounds.width*0.6, height: bounds.height*0.6)) + context.setFillColor(color) + context.fillPath() + } } - // MARK: - Inits + /// The action performed when tapped. func tapAction() { if let radioButtonModel = radioButtonModel { radioButtonModel.selected(self) @@ -71,21 +85,24 @@ import UIKit // MARK: - MVMViewProtocol open override func setupView() { super.setupView() - guard subviews.count == 0 else { - return - } - - /*translatesAutoresizingMaskIntoConstraints = false - addSubview(radioButton) - - isAccessibilityElement = true - accessibilityTraits = .none - accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") - NSLayoutConstraint.constraintPinSubview(toSuperview: radioButton) - radioButton.performActionForCheck = { [weak self] in - self?.tapAction() - }*/ + clipsToBounds = true + widthConstraint = widthAnchor.constraint(equalToConstant: 30) + widthConstraint?.isActive = true + heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1) + heightConstraint?.isActive = true + + addTarget(self, action: #selector(tapAction), for: .touchUpInside) + isAccessibilityElement = true + accessibilityTraits = .button + accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") + } +} + +// MARK: - MVMCoreUIViewConstrainingProtocol +extension RadioButton: MVMCoreUIViewConstrainingProtocol { + public func needsToBeConstrained() -> Bool { + return true } } diff --git a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m index 66a3a83d..c6b1023e 100644 --- a/MVMCoreUI/Atoms/Views/ViewConstrainingView.m +++ b/MVMCoreUI/Atoms/Views/ViewConstrainingView.m @@ -314,14 +314,10 @@ [self.molecule updateView:size]; [MFStyler setMarginsForView:self size:size defaultHorizontal:self.updateViewHorizontalDefaults top:(self.updateViewVerticalDefaults ? self.topMarginPadding : 0) bottom:(self.updateViewVerticalDefaults ? self.bottomMarginPadding : 0)]; UIEdgeInsets margins = [MVMCoreUIUtility getMarginsForView:self]; - if (self.updateViewHorizontalDefaults) { - [self setLeftPinConstant:margins.left]; - [self setRightPinConstant:margins.right]; - } - if (self.updateViewVerticalDefaults) { - [self setTopPinConstant:margins.top]; - [self setBottomPinConstant:margins.bottom]; - } + [self setLeftPinConstant:margins.left]; + [self setRightPinConstant:margins.right]; + [self setTopPinConstant:margins.top]; + [self setBottomPinConstant:margins.bottom]; } #pragma mark - MVMCoreUIMoleculeViewProtocol diff --git a/MVMCoreUI/BaseClasses/Control.swift b/MVMCoreUI/BaseClasses/Control.swift index bad1a6c8..fdf8204f 100644 --- a/MVMCoreUI/BaseClasses/Control.swift +++ b/MVMCoreUI/BaseClasses/Control.swift @@ -10,20 +10,29 @@ import UIKit public class Control: UIControl { var json: [AnyHashable: Any]? + + private var initialSetupPerformed = false public override init(frame: CGRect) { super.init(frame: .zero) - setupView() + initialSetup() } init() { super.init(frame: .zero) - setupView() + initialSetup() } public required init?(coder: NSCoder) { super.init(coder: coder) - setupView() + initialSetup() + } + + public func initialSetup() { + if !initialSetupPerformed { + initialSetupPerformed = true + setupView() + } } } @@ -31,6 +40,7 @@ extension Control: MVMCoreViewProtocol { public func updateView(_ size: CGFloat) { } + /// Will be called only once. public func setupView() { translatesAutoresizingMaskIntoConstraints = false insetsLayoutMarginsFromSafeArea = false diff --git a/MVMCoreUI/BaseClasses/View.swift b/MVMCoreUI/BaseClasses/View.swift index 25b750b0..735243df 100644 --- a/MVMCoreUI/BaseClasses/View.swift +++ b/MVMCoreUI/BaseClasses/View.swift @@ -11,26 +11,36 @@ import UIKit public class View: UIView { var json: [AnyHashable: Any]? - public override init(frame: CGRect) { - super.init(frame: .zero) - setupView() - } + private var initialSetupPerformed = false - init() { - super.init(frame: .zero) - setupView() + public override init(frame: CGRect) { + super.init(frame: .zero) + initialSetup() + } + + init() { + super.init(frame: .zero) + initialSetup() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + initialSetup() + } + + public func initialSetup() { + if !initialSetupPerformed { + initialSetupPerformed = true + setupView() + } + } } - - public required init?(coder: NSCoder) { - super.init(coder: coder) - setupView() - } -} extension View: MVMCoreViewProtocol { public func updateView(_ size: CGFloat) { } - + + /// Will be called only once. public func setupView() { translatesAutoresizingMaskIntoConstraints = false insetsLayoutMarginsFromSafeArea = false From 0cc81c3255bc542673fc43096f56de80bbac2c3a Mon Sep 17 00:00:00 2001 From: "Pfeil, Scott Robert" Date: Wed, 23 Oct 2019 11:38:15 -0400 Subject: [PATCH 40/45] default background color --- MVMCoreUI/Atoms/Views/RadioButton.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/Views/RadioButton.swift b/MVMCoreUI/Atoms/Views/RadioButton.swift index 6347a862..23588a4c 100644 --- a/MVMCoreUI/Atoms/Views/RadioButton.swift +++ b/MVMCoreUI/Atoms/Views/RadioButton.swift @@ -64,6 +64,7 @@ import UIKit isSelected = !isSelected } FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) + setNeedsDisplay() } public func isValidField() -> Bool { @@ -85,7 +86,7 @@ import UIKit // MARK: - MVMViewProtocol open override func setupView() { super.setupView() - + backgroundColor = .white clipsToBounds = true widthConstraint = widthAnchor.constraint(equalToConstant: 30) widthConstraint?.isActive = true @@ -126,4 +127,9 @@ extension RadioButton { formValidator: delegateObject?.formValidationProtocol?.formValidatorModel?()) FormValidator.setupValidation(molecule: radioButtonModel, delegate: delegateObject?.formValidationProtocol) } + + public override func reset() { + super.reset() + backgroundColor = .white + } } From 52fca407e3a09212d8731b675df7dbcc490dff34 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 23 Oct 2019 12:37:26 -0400 Subject: [PATCH 41/45] remove tap and accessibility --- .../Molecules/RadioButtonWithLabel.swift | 43 +------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/MVMCoreUI/Molecules/RadioButtonWithLabel.swift b/MVMCoreUI/Molecules/RadioButtonWithLabel.swift index 4f42067a..e7a29186 100644 --- a/MVMCoreUI/Molecules/RadioButtonWithLabel.swift +++ b/MVMCoreUI/Molecules/RadioButtonWithLabel.swift @@ -12,7 +12,6 @@ import UIKit public let radioButton = RadioButton() var delegateObject: MVMCoreUIDelegateObject? - var dummyButton: MFCustomButton? let label = Label() // MARK: - Inits @@ -38,10 +37,6 @@ import UIKit radioButton.translatesAutoresizingMaskIntoConstraints = false addSubview(radioButton) - isAccessibilityElement = true - accessibilityTraits = .none - accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "radio_action_hint") - radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true @@ -60,36 +55,12 @@ import UIKit constraint.priority = .defaultHigh constraint.isActive = true } - addActionHandler() } func createRightView() -> ViewConstrainingView? { let rightView = ViewConstrainingView(constrainingView: label) return rightView } - - func addActionHandler() { - - guard dummyButton == nil else { - return - } - - let dummyButton = MFCustomButton(frame: .zero) - self.dummyButton = dummyButton - dummyButton.translatesAutoresizingMaskIntoConstraints = false - addSubview(dummyButton) - NSLayoutConstraint.constraintPinSubview(toSuperview: dummyButton) - bringSubviewToFront(dummyButton) - - dummyButton.add({ [weak self] (button) in - self?.tapAction() - }, for: .touchUpInside) - } - - func tapAction() { - radioButton.tapAction() - changeAccessibilityLabel() - } } // MARK: - MVMCoreUIMoleculeViewProtocol @@ -100,18 +71,6 @@ extension RadioButtonWithLabel { radioButton.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) label.setWithJSON(json?.optionalDictionaryForKey(KeyLabel), delegateObject: delegateObject, - additionalData: additionalData) - changeAccessibilityLabel() - } -} - -// MARK: Accessibility -extension RadioButtonWithLabel { - func changeAccessibilityLabel() { - let stateString = radioButton.isSelected ? "radio_selected_state" : "radio_not_selected_state" - let localizedStringState = MVMCoreUIUtility.hardcodedString(withKey: stateString) ?? "" - let accebilityString = (label.accessibilityLabel ?? (json?.optionalStringForKey("accessibilityText") ?? "")) - + (MVMCoreUIUtility.hardcodedString(withKey: "radio_desc_state") ?? "") + localizedStringState - accessibilityLabel = accebilityString + additionalData: additionalData) } } From d398a4505418bb56c14b2d3327d99704c4849ed2 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 23 Oct 2019 13:53:58 -0400 Subject: [PATCH 42/45] code review --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++++---- ...onWithLabel.swift => RadioButtonLabel.swift} | 17 +++++++---------- .../MVMCoreUIMoleculeMappingObject.m | 2 +- 3 files changed, 12 insertions(+), 15 deletions(-) rename MVMCoreUI/Molecules/{RadioButtonWithLabel.swift => RadioButtonLabel.swift} (75%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 4389ff65..8ff82cfc 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -16,13 +16,13 @@ 01509D912327ECE600EF99AA /* CornerLabels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D902327ECE600EF99AA /* CornerLabels.swift */; }; 01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D922327ECFB00EF99AA /* ProgressBar.swift */; }; 01509D952327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01509D942327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift */; }; + 017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */; }; 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198F79E225679870066C936 /* FormValidationProtocol.swift */; }; 0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 0198F7A02256A80A0066C936 /* MFRadioButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0198F7A22256A80A0066C936 /* MFRadioButton.m */; }; 01DF55E021F8FAA800CC099B /* MFTextFieldListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */; }; 01DF567021FA5AB300CC099B /* TextFieldListFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */; }; 01E569D3223FFFA500327251 /* ThreeLayerViewController.swift in Headers */ = {isa = PBXBuildFile; fileRef = D2A5146A2214905000345BFB /* ThreeLayerViewController.swift */; settings = {ATTRIBUTES = (Public, ); }; }; - 01FC09E3235E246D003AC9B3 /* RadioButtonWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01FC09E2235E246D003AC9B3 /* RadioButtonWithLabel.swift */; }; 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; }; 0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */; }; 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; @@ -210,12 +210,12 @@ 01509D902327ECE600EF99AA /* CornerLabels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CornerLabels.swift; sourceTree = ""; }; 01509D922327ECFB00EF99AA /* ProgressBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = ""; }; 01509D942327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlineBodyTextButtonSwitch.swift; sourceTree = ""; }; + 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonLabel.swift; sourceTree = ""; }; 0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = ""; }; 0198F7A02256A80A0066C936 /* MFRadioButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFRadioButton.h; sourceTree = ""; }; 0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = ""; }; 01DF55DF21F8FAA800CC099B /* MFTextFieldListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MFTextFieldListView.swift; sourceTree = ""; }; 01DF566F21FA5AB300CC099B /* TextFieldListFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextFieldListFormViewController.swift; sourceTree = ""; }; - 01FC09E2235E246D003AC9B3 /* RadioButtonWithLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonWithLabel.swift; sourceTree = ""; }; 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = ""; }; 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; @@ -568,6 +568,7 @@ D29DF10E21E67A77003B2FB9 /* Molecules */ = { isa = PBXGroup; children = ( + 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */, D22479912316A9EF003FCCF9 /* Items */, D224798F2316A99F003FCCF9 /* LeftRightViews */, D224798E2316A995003FCCF9 /* HorizontalCombinationViews */, @@ -579,7 +580,6 @@ D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */, D2A514662213885800345BFB /* StandardHeaderView.swift */, D274CA322236A78900B01B62 /* StandardFooterView.swift */, - 01FC09E2235E246D003AC9B3 /* RadioButtonWithLabel.swift */, 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */, D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */, @@ -1078,13 +1078,13 @@ D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */, D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */, D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */, - 01FC09E3235E246D003AC9B3 /* RadioButtonWithLabel.swift in Sources */, D282AACB2243C61700C46919 /* ButtonView.swift in Sources */, D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */, 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */, D22479962316AF6E003FCCF9 /* HeadlineBodyTextButton.swift in Sources */, D29DF2AE21E7B3A4003B2FB9 /* MFTextView.m in Sources */, + 017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */, D29DF18121E69E50003B2FB9 /* MFView.m in Sources */, D29DF18321E69E54003B2FB9 /* SeparatorView.m in Sources */, D29DF17A21E69E1F003B2FB9 /* MFCustomButton.m in Sources */, diff --git a/MVMCoreUI/Molecules/RadioButtonWithLabel.swift b/MVMCoreUI/Molecules/RadioButtonLabel.swift similarity index 75% rename from MVMCoreUI/Molecules/RadioButtonWithLabel.swift rename to MVMCoreUI/Molecules/RadioButtonLabel.swift index e7a29186..244a4829 100644 --- a/MVMCoreUI/Molecules/RadioButtonWithLabel.swift +++ b/MVMCoreUI/Molecules/RadioButtonLabel.swift @@ -8,7 +8,7 @@ import UIKit -@objcMembers public class RadioButtonWithLabel: ViewConstrainingView { +@objcMembers public class RadioButtonLabel: ViewConstrainingView { public let radioButton = RadioButton() var delegateObject: MVMCoreUIDelegateObject? @@ -33,13 +33,10 @@ import UIKit return } - translatesAutoresizingMaskIntoConstraints = false - radioButton.translatesAutoresizingMaskIntoConstraints = false addSubview(radioButton) - radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true - radioButton.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: PaddingOne).isActive = true - bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true + radioButton.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: PaddingOne).isActive = true + layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true radioButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true if let rightView = createRightView() { @@ -47,11 +44,11 @@ import UIKit rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true - var constraint = rightView.topAnchor.constraint(equalTo: topAnchor, constant: PaddingOne) + var constraint = rightView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: PaddingOne) constraint.priority = .defaultHigh constraint.isActive = true - constraint = bottomAnchor.constraint(equalTo: rightView.bottomAnchor, constant: PaddingOne) + constraint = layoutMarginsGuide.bottomAnchor.constraint(equalTo: rightView.bottomAnchor, constant: PaddingOne) constraint.priority = .defaultHigh constraint.isActive = true } @@ -64,11 +61,11 @@ import UIKit } // MARK: - MVMCoreUIMoleculeViewProtocol -extension RadioButtonWithLabel { +extension RadioButtonLabel { @objc open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) self.delegateObject = delegateObject - radioButton.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + radioButton.setWithJSON(json?.optionalDictionaryForKey("radioButton"), delegateObject: delegateObject, additionalData: additionalData) label.setWithJSON(json?.optionalDictionaryForKey(KeyLabel), delegateObject: delegateObject, additionalData: additionalData) diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 6c2100f3..323e9d84 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -45,7 +45,7 @@ @"multiProgressBar": MultiProgress.class, @"checkbox": MVMCoreUICheckBox.class, @"radioButton": RadioButton.class, - @"radioButtonLabel": RadioButtonWithLabel.class, + @"radioButtonLabel": RadioButtonLabel.class, @"listItem": MoleculeTableViewCell.class, @"accordionListItem": AccordionMoleculeTableViewCell.class, @"switch": MVMCoreUISwitch.class, From 73342e40d1389fd42183f0302800d87f6f71ae81 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 23 Oct 2019 14:51:35 -0400 Subject: [PATCH 43/45] code optimization --- MVMCoreUI/Atoms/Buttons/PrimaryButton.m | 6 +++--- MVMCoreUI/FormUIHelpers/FormValidator.swift | 24 +++++++++------------ 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m index e4f889eb..35395557 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton.m +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton.m @@ -21,7 +21,7 @@ @interface PrimaryButton() @property (nonatomic) BOOL validationRequired; -@property (nonatomic, strong) NSArray *requiredFieldsList; +@property (nonatomic, strong) NSArray *requiredGroupsList; @property (nonatomic) BOOL smallButton; @property (assign, nonatomic) BOOL tinyButton; @property (nonatomic) CGFloat sizeForSizing; @@ -670,7 +670,7 @@ - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { self.validationRequired = [json boolForKey:@"validationRequired"]; - self.requiredFieldsList = [json array:@"requiredFields"]; + self.requiredGroupsList = [json array:@"requiredGroups"]; [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; self.primaryButtonType = PrimaryButtonTypeCustom; @@ -784,7 +784,7 @@ } - (NSArray *)requiredGroups { - return self.requiredFieldsList; + return self.requiredGroupsList; } - (void)enableField:(BOOL)enable { diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index d11e4847..7f689dd8 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -49,26 +49,22 @@ import MVMCore public func enableByValidation() { for molecule in enableDisableMolecules { - var requiredFields = molecule.requiredGroups?() ?? [dummyGroupName] - if requiredFields.count == 0 { - requiredFields = [dummyGroupName] + var requiredGroups = molecule.requiredGroups?() ?? [dummyGroupName] + if requiredGroups.count == 0 { + requiredGroups = [dummyGroupName] } - enableWithGroups(requiredFields, molecule) + enableWithGroups(requiredGroups, molecule) } } public func enableWithGroups(_ requiredGroupList: [String], _ enableDisableMolecule: FormValidationEnableDisableProtocol) { - - var groupValidityMap: [String: Bool] = [:] - for molecule in fieldMolecules { - let valid = molecule.isValidField() - let groupName = molecule.formFieldGroupName() ?? dummyGroupName - groupValidityMap[groupName] = valid && (groupValidityMap[groupName] ?? true) - } - + let requiredGroupSet = Set(requiredGroupList) var valid = true - for groupName in requiredGroupList { - valid = valid && groupValidityMap[groupName] ?? false + for molecule in fieldMolecules { + let groupName = molecule.formFieldGroupName() ?? dummyGroupName + if requiredGroupSet.contains(groupName) { + valid = valid && molecule.isValidField() + } } enableDisableMolecule.enableField?(valid) } From d2ca3adacf891a0c5f3ecb02fff62b16e5ad25c7 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 23 Oct 2019 15:59:03 -0400 Subject: [PATCH 44/45] code review --- MVMCoreUI/Molecules/RadioButtonLabel.swift | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Molecules/RadioButtonLabel.swift b/MVMCoreUI/Molecules/RadioButtonLabel.swift index 244a4829..5d70b7e4 100644 --- a/MVMCoreUI/Molecules/RadioButtonLabel.swift +++ b/MVMCoreUI/Molecules/RadioButtonLabel.swift @@ -37,20 +37,21 @@ import UIKit radioButton.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor, constant: 0).isActive = true radioButton.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: PaddingOne).isActive = true layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: radioButton.bottomAnchor, constant: PaddingOne).isActive = true - radioButton.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true + radioButton.centerYAnchor.constraint(equalTo: layoutMarginsGuide.centerYAnchor).isActive = true if let rightView = createRightView() { addSubview(rightView) rightView.leftAnchor.constraint(equalTo: radioButton.rightAnchor, constant: PaddingHorizontalBetweenRelatedItems).isActive = true rightView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor, constant: 0).isActive = true - var constraint = rightView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor, constant: PaddingOne) + var constraint = rightView.topAnchor.constraint(greaterThanOrEqualTo: layoutMarginsGuide.topAnchor, constant: PaddingOne) constraint.priority = .defaultHigh constraint.isActive = true - constraint = layoutMarginsGuide.bottomAnchor.constraint(equalTo: rightView.bottomAnchor, constant: PaddingOne) + constraint = layoutMarginsGuide.bottomAnchor.constraint(greaterThanOrEqualTo: rightView.bottomAnchor, constant: PaddingOne) constraint.priority = .defaultHigh constraint.isActive = true + layoutMarginsGuide.centerYAnchor.constraint(equalTo: rightView.centerYAnchor).isActive = true } } @@ -70,4 +71,13 @@ extension RadioButtonLabel { delegateObject: delegateObject, additionalData: additionalData) } + + public override func reset() { + radioButton.reset() + label.reset() + } + + public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return 45 + } } From b8e1389798a360cca3e79c13d17f19433074ffd3 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 23 Oct 2019 17:21:44 -0400 Subject: [PATCH 45/45] review --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 3 +++ MVMCoreUI/Molecules/RadioButtonLabel.swift | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 7f689dd8..77c52249 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -64,6 +64,9 @@ import MVMCore let groupName = molecule.formFieldGroupName() ?? dummyGroupName if requiredGroupSet.contains(groupName) { valid = valid && molecule.isValidField() + if valid == false { + break + } } } enableDisableMolecule.enableField?(valid) diff --git a/MVMCoreUI/Molecules/RadioButtonLabel.swift b/MVMCoreUI/Molecules/RadioButtonLabel.swift index 5d70b7e4..e889b4f2 100644 --- a/MVMCoreUI/Molecules/RadioButtonLabel.swift +++ b/MVMCoreUI/Molecules/RadioButtonLabel.swift @@ -27,6 +27,12 @@ import UIKit super.init(coder: aDecoder) } + public override func updateView(_ size: CGFloat) { + super.updateView(size) + radioButton.updateView(size) + label.updateView(size) + } + open override func setupView() { super.setupView() guard subviews.count == 0 else { @@ -73,6 +79,7 @@ extension RadioButtonLabel { } public override func reset() { + super.reset() radioButton.reset() label.reset() }