diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 8755bfac..1971e571 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -143,6 +143,8 @@ 8D4687E4242E2DF300802879 /* ListFourColumnDataUsageListItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */; }; 8DD1E36E243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */; }; 8DD1E370243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */; }; + 8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */; }; + 8DEFA95E243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */; }; 942C372E241149170066E45E /* NHaasGroteskDSStd-75Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */; }; 942C372F241149170066E45E /* NHaasGroteskDSStd-55Rg.otf in Resources */ = {isa = PBXBuildFile; fileRef = 942C372D241149170066E45E /* NHaasGroteskDSStd-55Rg.otf */; }; 942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 942C378B2412F4FA0066E45E /* ModalMoleculeListTemplate.swift */; }; @@ -554,6 +556,8 @@ 8D4687E3242E2DF300802879 /* ListFourColumnDataUsageListItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageListItem.swift; sourceTree = ""; }; 8DD1E36D243B3CFB00D8F2DF /* ListThreeColumnInternationalDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalDataModel.swift; sourceTree = ""; }; 8DD1E36F243B3D0500D8F2DF /* ListThreeColumnInternationalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnInternationalData.swift; sourceTree = ""; }; + 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDividerModel.swift; sourceTree = ""; }; + 8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnDataUsageDivider.swift; sourceTree = ""; }; 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = ""; }; 942C372C241149170066E45E /* NHaasGroteskDSStd-75Bd.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-75Bd.otf"; sourceTree = ""; }; 942C372D241149170066E45E /* NHaasGroteskDSStd-55Rg.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "NHaasGroteskDSStd-55Rg.otf"; sourceTree = ""; }; @@ -1340,6 +1344,8 @@ 8D3BA9BE2433789900D341BA /* ListThreeColumnInternationalDataDivider.swift */, AA1EC59624373985003D6F50 /* ListThreeColumnSpeedTestDividerModel.swift */, AA1EC59824373994003D6F50 /* ListThreeColumnSpeedTestDivider.swift */, + 8DEFA95B243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift */, + 8DEFA95D243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift */, ); path = ThreeColumn; sourceTree = ""; @@ -2118,6 +2124,7 @@ 5248BFEC23F12E350059236A /* ListThreeColumnPlanDataDivider.swift in Sources */, 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */, 0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */, + 8DEFA95C243DAC20000D27E5 /* ListThreeColumnDataUsageDividerModel.swift in Sources */, 94F217B723E0BF6100A47C06 /* PrimaryButtonView.m in Sources */, 0A1B4A96233BB18F005B3FB4 /* CheckboxLabel.swift in Sources */, 0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */, @@ -2198,6 +2205,7 @@ D2FB151B23A2B65B00C20E10 /* MoleculeContainer.swift in Sources */, 279B1569242BBC2F00921D6C /* ActionModelAdapter.swift in Sources */, BB6C6AC0242232DF005F7224 /* ListOneColumnTextWithWhitespaceDividerTallModel.swift in Sources */, + 8DEFA95E243DAC2F000D27E5 /* ListThreeColumnDataUsageDivider.swift in Sources */, D2A638FD22CA98280052ED1F /* HeadlineBody.swift in Sources */, D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */, AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButton.swift b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButton.swift index b73ddc8b..1e520cc2 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButton.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButton.swift @@ -19,9 +19,9 @@ import UIKit widthConstraint?.constant = diameter } } - + public var enabledColor: UIColor = .mvmBlack - public var disabledColor: UIColor = .mvmCoolGray6 + public var disabledColor: UIColor = .mvmCoolGray3 public var delegateObject: MVMCoreUIDelegateObject? public var radioModel: RadioButtonModel? { @@ -41,6 +41,13 @@ import UIKit } }() + public override var isEnabled: Bool { + didSet { + isUserInteractionEnabled = isEnabled + setNeedsDisplay() + } + } + //-------------------------------------------------- // MARK: - Constraints //-------------------------------------------------- @@ -72,7 +79,7 @@ import UIKit } //-------------------------------------------------- - // MARK: - Methods + // MARK: - Validation //-------------------------------------------------- /// The action performed when tapped. @@ -129,11 +136,12 @@ import UIKit self.delegateObject = delegateObject isSelected = model.state + isEnabled = model.enabled RadioButtonSelectionHelper.setupForRadioButtonGroup(model, self, delegateObject: delegateObject) } public override func reset() { super.reset() - backgroundColor = .white + backgroundColor = .mvmWhite } } diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonModel.swift b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonModel.swift index 579c0ed9..ee408bb4 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonModel.swift @@ -51,7 +51,7 @@ open class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { } //-------------------------------------------------- - // MARK: - Method + // MARK: - Validation //-------------------------------------------------- public func formFieldValue() -> AnyHashable? { diff --git a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonSelectionHelper.swift b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonSelectionHelper.swift index c7208802..8730a9c3 100644 --- a/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonSelectionHelper.swift +++ b/MVMCoreUI/Atomic/Atoms/Buttons/RadioButtonSelectionHelper.swift @@ -19,7 +19,7 @@ import Foundation private var selectedRadioButton: RadioButton? private var fieldGroupName: String? public var baseValue: AnyHashable? - + //-------------------------------------------------- // MARK: - Initializer //-------------------------------------------------- @@ -29,7 +29,7 @@ import Foundation } //-------------------------------------------------- - // MARK: - Methods + // MARK: - Functions //-------------------------------------------------- public static func setupForRadioButtonGroup(_ radioButtonModel: RadioButtonModel, _ radioButton: RadioButton, delegateObject: MVMCoreUIDelegateObject?) { diff --git a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift index 3028955d..b55d9b60 100644 --- a/MVMCoreUI/Atomic/MoleculeObjectMapping.swift +++ b/MVMCoreUI/Atomic/MoleculeObjectMapping.swift @@ -157,6 +157,7 @@ import Foundation MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnInternationalDataDivider.self, viewModelClass: ListThreeColumnInternationalDataDividerModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnSpeedTestDivider.self, viewModelClass: ListThreeColumnSpeedTestDividerModel.self) MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnBillChangesDivider.self, viewModelClass: ListThreeColumnBillChangesDividerModel.self) + MoleculeObjectMapping.shared()?.register(viewClass: ListThreeColumnDataUsageDivider.self, viewModelClass: ListThreeColumnDataUsageDividerModel.self) // Designed Headers MoleculeObjectMapping.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self) diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift index 9517acf0..4597a0b9 100644 --- a/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/List/LeftVariable/ListLeftVariableRadioButtonAndPaymentMethod.swift @@ -8,12 +8,13 @@ import UIKit + @objcMembers open class ListLeftVariableRadioButtonAndPaymentMethod: TableViewCell { //----------------------------------------------------- // MARK: - Outlets //----------------------------------------------------- - let radioButton = RadioButton(frame: .zero) + let radioButton = RadioButton() let leftImage = MFLoadImageView(pinnedEdges: .all) let eyebrowHeadlineBodyLink = EyebrowHeadlineBodyLink() var stack: Stack @@ -57,7 +58,7 @@ import UIKit // MARK: - Molecule //---------------------------------------------------- - open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) guard let model = model as? ListLeftVariableRadioButtonAndPaymentMethodModel else { return} radioButton.set(with: model.radioButton, delegateObject, additionalData) @@ -69,7 +70,10 @@ import UIKit return 90 } - public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { - radioButton.tapAction() + public override func didSelectCell(at index: IndexPath, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + + if radioButton.isEnabled { + radioButton.tapAction() + } } } diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnDataUsageDivider.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnDataUsageDivider.swift new file mode 100644 index 00000000..eab5e8be --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnDataUsageDivider.swift @@ -0,0 +1,61 @@ +// +// ListThreeColumnDataUsageDivider.swift +// MVMCoreUI +// +// Created by Kruthika KP on 20/03/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers open class ListThreeColumnDataUsageDivider: TableViewCell { + + //----------------------------------------------------- + // MARK: - Outlets + //------------------------------------------------------- + public let leftLabel = Label.createLabelBoldBodySmall(true) + public let centerLabel = Label.createLabelBoldBodySmall(true) + public let rightLabel = Label.createLabelBoldBodySmall(true) + var stack: Stack + + //------------------------------------------------------ + // MARK: - Initializers + //------------------------------------------------------ + public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + stack = Stack.createStack(with: [(view: leftLabel, model: StackItemModel(percent: 40, horizontalAlignment: .leading)), + (view: centerLabel, model: StackItemModel(percent: 37, horizontalAlignment: .leading)), + (view: rightLabel, model: StackItemModel(percent: 23, horizontalAlignment: .leading))], + axis: .horizontal) + super.init(style: style, reuseIdentifier: reuseIdentifier) + } + + public required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + open override func setupView() { + super.setupView() + addMolecule(stack) + stack.restack() + } + + // MARK: - ModelMoleculeViewProtocol + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { + super.set(with: model, delegateObject, additionalData) + guard let model = model as? ListThreeColumnDataUsageDividerModel else { return } + leftLabel.set(with: model.leftLabel, delegateObject, additionalData) + centerLabel.set(with: model.centerLabel, delegateObject, additionalData) + rightLabel.set(with: model.rightLabel, delegateObject, additionalData) + } + + open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { + return 121 + } + + open override func reset() { + super.reset() + leftLabel.styleBoldBodySmall(true) + centerLabel.styleBoldBodySmall(true) + rightLabel.styleBoldBodySmall(true) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnDataUsageDividerModel.swift b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnDataUsageDividerModel.swift new file mode 100644 index 00000000..f57bdf01 --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/DesignedComponents/SectionDividers/ThreeColumn/ListThreeColumnDataUsageDividerModel.swift @@ -0,0 +1,51 @@ +// +// ListThreeColumnDataUsageDividerModel.swift +// MVMCoreUI +// +// Created by Kruthika KP on 20/03/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class ListThreeColumnDataUsageDividerModel: ListItemModel, MoleculeModelProtocol { + public static var identifier: String = "list3CDataUsgDiv" + public let leftLabel: LabelModel + public let centerLabel: LabelModel + public let rightLabel: LabelModel + + public init(leftLabel: LabelModel, centerLabel: LabelModel, rightLabel: LabelModel) { + self.leftLabel = leftLabel + self.centerLabel = centerLabel + self.rightLabel = rightLabel + super.init() + } + + override public func setDefaults() { + super.setDefaults() + style = "tallDivider" + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case leftLabel + case centerLabel + case rightLabel + } + + required init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel) + centerLabel = try typeContainer.decode(LabelModel.self, forKey: .centerLabel) + rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel) + try super.init(from:decoder) + } + + public override func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encode(leftLabel, forKey: .leftLabel) + try container.encode(centerLabel, forKey: .centerLabel) + try container.encode(rightLabel, forKey: .rightLabel) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift b/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift index 9365125a..9a00a94d 100644 --- a/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/Items/ListItemModel.swift @@ -9,6 +9,7 @@ import Foundation + @objcMembers open class ListItemModel: ContainerModel, ListItemModelProtocol { //-------------------------------------------------- // MARK: - Properties diff --git a/MVMCoreUI/BaseClasses/Control.swift b/MVMCoreUI/BaseClasses/Control.swift index ebb88977..d8acb6f6 100644 --- a/MVMCoreUI/BaseClasses/Control.swift +++ b/MVMCoreUI/BaseClasses/Control.swift @@ -8,6 +8,7 @@ import UIKit + @objcMembers open class Control: UIControl, MoleculeViewProtocol { //-------------------------------------------------- // MARK: - Properties diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index 592132f5..06c8cdf1 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -9,8 +9,12 @@ import UIKit import MVMCore -@objcMembers public class FormValidator: NSObject { +@objcMembers public class FormValidator: NSObject { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + static var defaultGroupName: String = "default" var formRules: [FormGroupRule]? weak var delegate: FormHolderProtocol? @@ -18,10 +22,18 @@ import MVMCore var groupWatchers: [FormGroupWatcherFieldProtocol] = [] var radioButtonsModelByGroup: [String: RadioButtonSelectionHelper] = [:] + //-------------------------------------------------- + // MARK: - Initializer + //-------------------------------------------------- + public init(_ formRules: [FormGroupRule]?) { self.formRules = formRules } + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + /// Adds the form field to the validator. public func add(_ field: FormFieldProtocol) { if let fieldKey = field.fieldKey { diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift index 042243db..7cf24cd5 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift @@ -8,25 +8,34 @@ import Foundation -public class RuleAnyValueChangedModel: RulesProtocol { +public class RuleAnyValueChangedModel: RulesProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + public static var identifier: String = "anyValueChanged" public var type: String = RuleAnyValueChangedModel.identifier public var fields: [String] + //-------------------------------------------------- + // MARK: - Validation + //-------------------------------------------------- + public func isValid(_ formField: FormFieldProtocol) -> Bool { return formField.baseValue != formField.formFieldValue() } public func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { + for formKey in fields { - guard let formField = fieldMolecules[formKey] else { - continue - } + guard let formField = fieldMolecules[formKey] else { continue } + if isValid(formField) { return true } } + return false } }