Merge remote-tracking branch 'origin/develop' into feature/view_masking
This commit is contained in:
commit
691bb1a781
@ -584,6 +584,8 @@
|
||||
EAA0CFAF275E7D8000D65EB0 /* FormFieldEffectProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */; };
|
||||
EAA0CFB1275E823A00D65EB0 /* HideFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */; };
|
||||
EAA0CFB3275E831E00D65EB0 /* DisableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */; };
|
||||
EAB14BC127D935F00012AB2C /* RuleCompareModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC027D935F00012AB2C /* RuleCompareModelProtocol.swift */; };
|
||||
EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */; };
|
||||
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* FormLabel.swift */; };
|
||||
EABFC152276913E800E78B40 /* FormLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC151276913E800E78B40 /* FormLabelModel.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
@ -1169,6 +1171,8 @@
|
||||
EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormFieldEffectProtocol.swift; sourceTree = "<group>"; };
|
||||
EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HideFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||
EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||
EAB14BC027D935F00012AB2C /* RuleCompareModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleCompareModelProtocol.swift; sourceTree = "<group>"; };
|
||||
EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModelProtocol.swift; sourceTree = "<group>"; };
|
||||
EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = "<group>"; };
|
||||
EABFC151276913E800E78B40 /* FormLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabelModel.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@ -1214,12 +1218,14 @@
|
||||
children = (
|
||||
011D95A4240455DC000E3791 /* FormGroupRule.swift */,
|
||||
011D958424042432000E3791 /* RulesProtocol.swift */,
|
||||
011D959A240451E3000E3791 /* RuleRequiredModel.swift */,
|
||||
011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */,
|
||||
EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */,
|
||||
EAB14BC027D935F00012AB2C /* RuleCompareModelProtocol.swift */,
|
||||
011D959E240453A1000E3791 /* RuleAllValueChangedModel.swift */,
|
||||
011D95A0240453D0000E3791 /* RuleEqualsModel.swift */,
|
||||
011D959A240451E3000E3791 /* RuleRequiredModel.swift */,
|
||||
011D95A2240453F8000E3791 /* RuleRegexModel.swift */,
|
||||
011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */,
|
||||
0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */,
|
||||
011D95A0240453D0000E3791 /* RuleEqualsModel.swift */,
|
||||
0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */,
|
||||
);
|
||||
name = Rules;
|
||||
@ -2672,6 +2678,7 @@
|
||||
D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */,
|
||||
D2B18B7F2360913400A9AEDC /* Control.swift in Sources */,
|
||||
D253BB8A24574CC5002DE544 /* StackModel.swift in Sources */,
|
||||
EAB14BC127D935F00012AB2C /* RuleCompareModelProtocol.swift in Sources */,
|
||||
011D95A924057AC7000E3791 /* FormGroupWatcherFieldProtocol.swift in Sources */,
|
||||
BB2BF0EA2452A9BB001D0FC2 /* ListDeviceComplexButtonSmall.swift in Sources */,
|
||||
D20C700B250BFDE40095B21C /* MVMCoreUITopAlertView+Extension.swift in Sources */,
|
||||
@ -2876,6 +2883,7 @@
|
||||
BB55B51D244482C1002001AD /* ListRightVariablePriceChangeBodyText.swift in Sources */,
|
||||
017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */,
|
||||
323AC96C24C837FF00F8E4C4 /* ListThreeColumnBillChanges.swift in Sources */,
|
||||
EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */,
|
||||
0A0FEC7825D42A8500AF2548 /* BaseItemPickerEntryFieldModel.swift in Sources */,
|
||||
D28A837923C7D5BC00DFE4FC /* PageModelProtocol.swift in Sources */,
|
||||
D2351C7C24A4D4C3007DF0BC /* ListRightVariableToggleAllTextAndLinks.swift in Sources */,
|
||||
|
||||
@ -38,29 +38,6 @@ import UIKit
|
||||
// Default dimensions of the DigitBox
|
||||
static let size: CGSize = CGSize(width: 39, height: 44)
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Computed Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public override var showError: Bool {
|
||||
get { super.showError }
|
||||
set (error) {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.borderStrokeColor = error ? .mvmOrange : .mvmCoolGray3
|
||||
|
||||
let barHeight: CGFloat = self.showError ? 4 : 1
|
||||
self.bottomBar?.frame = CGRect(x: 0, y: self.bounds.height - barHeight, width: self.bounds.width, height: barHeight)
|
||||
self.bottomBar?.backgroundColor = self.showError ? UIColor.mvmOrange.cgColor : UIColor.mvmBlack.cgColor
|
||||
|
||||
self.setNeedsDisplay()
|
||||
self.layoutIfNeeded()
|
||||
}
|
||||
super.showError = error
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Delegate
|
||||
//--------------------------------------------------
|
||||
|
||||
@ -105,7 +105,7 @@ import UIKit
|
||||
super.isLocked = locked
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override var placeholder: String? {
|
||||
get {
|
||||
var string = ""
|
||||
@ -311,7 +311,6 @@ import UIKit
|
||||
//--------------------------------------------------
|
||||
|
||||
@objc override func startEditing() {
|
||||
|
||||
selectedDigitBox?.isSelected = true
|
||||
selectedDigitBox?.digitField.becomeFirstResponder()
|
||||
}
|
||||
@ -328,7 +327,6 @@ import UIKit
|
||||
}
|
||||
|
||||
@objc public override func dismissFieldInput(_ sender: Any?) {
|
||||
|
||||
digitBoxes.forEach {
|
||||
if $0.isSelected {
|
||||
$0.digitField.resignFirstResponder()
|
||||
@ -398,7 +396,6 @@ extension DigitEntryField {
|
||||
digitEntryModel?.text = text
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@ -411,9 +408,9 @@ extension DigitEntryField {
|
||||
}
|
||||
|
||||
@objc public func textFieldDidBeginEditing(_ textField: UITextField) {
|
||||
|
||||
digitBoxes.forEach {
|
||||
if $0.digitField === textField {
|
||||
startEditing()
|
||||
selectedDigitBox = $0
|
||||
$0.isSelected = true
|
||||
return
|
||||
@ -429,15 +426,15 @@ extension DigitEntryField {
|
||||
}
|
||||
|
||||
@objc public func textFieldDidEndEditing(_ textField: UITextField) {
|
||||
|
||||
// There should only be one digitBox to deselect.
|
||||
selectedDigitBox?.isSelected = false
|
||||
selectedDigitBox = nil
|
||||
|
||||
if !switchFieldsAutomatically && validateWhenDoneEditing {
|
||||
validateText()
|
||||
endInputing()
|
||||
}
|
||||
|
||||
|
||||
proprietorTextDelegate?.textFieldDidEndEditing?(textField)
|
||||
}
|
||||
|
||||
|
||||
@ -96,9 +96,9 @@ import Foundation
|
||||
return text
|
||||
}
|
||||
|
||||
public func setValidity(_ valid: Bool, rule: RulesProtocol) {
|
||||
public func setValidity(_ valid: Bool, errorMessage: String?) {
|
||||
|
||||
if let fieldKey = fieldKey, let ruleErrorMessage = rule.errorMessage?[fieldKey] {
|
||||
if let ruleErrorMessage = errorMessage, fieldKey != nil {
|
||||
self.errorMessage = ruleErrorMessage
|
||||
}
|
||||
|
||||
|
||||
@ -29,3 +29,19 @@ public extension FormFieldProtocol {
|
||||
|
||||
var baseValue: AnyHashable? { nil }
|
||||
}
|
||||
|
||||
public class FormFieldValidity{
|
||||
public var fieldKey: String
|
||||
public var valid: Bool = true
|
||||
public var errorMessages: [String] = []
|
||||
|
||||
public init(_ fieldKey: String){
|
||||
self.fieldKey = fieldKey
|
||||
}
|
||||
|
||||
public func addError(message: String?){
|
||||
if let message = message {
|
||||
self.errorMessages.append(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,5 +10,5 @@
|
||||
import Foundation
|
||||
|
||||
public protocol FormRuleWatcherFieldProtocol {
|
||||
func setValidity(_ valid: Bool, rule: RulesProtocol)
|
||||
func setValidity(_ valid: Bool, errorMessage: String?)
|
||||
}
|
||||
|
||||
@ -133,11 +133,10 @@ import MVMCore
|
||||
let tuple = group.validate(fields)
|
||||
|
||||
//set the validity for the fields
|
||||
group.rules.forEach { rule in
|
||||
for formKey in rule.fields {
|
||||
guard let formField = fields[formKey] as? FormRuleWatcherFieldProtocol,
|
||||
let fieldValidity = tuple.fieldValidity[formKey] else { continue }
|
||||
formField.setValidity(fieldValidity, rule: rule)
|
||||
fields.forEach { (key: String, value: FormFieldProtocol) in
|
||||
if let formField = value as? FormRuleWatcherFieldProtocol,
|
||||
let fieldValidity = tuple.fieldValidity[key] {
|
||||
formField.setValidity(fieldValidity.valid, errorMessage: fieldValidity.errorMessages.last)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
//
|
||||
// RuleAnyModelProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Matt Bruce on 3/9/22.
|
||||
// Copyright © 2022 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// RuleAnyModelProtocol was abstracted to 1 place since this code was currently
|
||||
/// duplicated in 2 classes.
|
||||
/// This protocol should be used for the rules that need to Loop through all of the fields
|
||||
/// and if ANY formField's isValid == TRUE, the Rule is then TRUE
|
||||
public protocol RuleAnyModelProtocol: RulesProtocol{}
|
||||
|
||||
extension RuleAnyModelProtocol {
|
||||
|
||||
/// Overriding the RulesProtocol default implementation
|
||||
public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: FormFieldValidity]) -> (valid: Bool, fieldValidity: [String: FormFieldValidity]) {
|
||||
|
||||
for formKey in fields {
|
||||
guard let formField = fieldMolecules[formKey] else { continue }
|
||||
|
||||
var fieldValidity = isValid(formField)
|
||||
// If past rule is invalid for a field, the current rule should not flip the validity of a field
|
||||
if let validity = previousFieldValidity[formKey], !validity.valid, fieldValidity {
|
||||
fieldValidity = false
|
||||
}
|
||||
|
||||
// If TRUE the RULE is TRUE, even if there are many fields to check.
|
||||
if fieldValidity {
|
||||
return (true, previousFieldValidity)
|
||||
}
|
||||
}
|
||||
|
||||
// if the rule breaks all fields should be set to false
|
||||
fields.forEach { (formKey) in
|
||||
previousFieldValidity[formKey]?.valid = false
|
||||
previousFieldValidity[formKey]?.addError(message: errorMessage?[formKey])
|
||||
}
|
||||
return (valid: false, fieldValidity: previousFieldValidity)
|
||||
}
|
||||
|
||||
}
|
||||
@ -8,8 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
|
||||
public class RuleAnyRequiredModel: RulesProtocol {
|
||||
public class RuleAnyRequiredModel: RuleAnyModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -37,27 +36,4 @@ public class RuleAnyRequiredModel: RulesProtocol {
|
||||
return false
|
||||
}
|
||||
|
||||
public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) {
|
||||
|
||||
var previousValidity: [String: Bool] = [:]
|
||||
for formKey in fields {
|
||||
guard let formField = fieldMolecules[formKey] else { continue }
|
||||
|
||||
var fieldValidity = isValid(formField)
|
||||
// If past rule is invalid for a field, the current rule should not flip the validity of a field
|
||||
if let validity = previousFieldValidity[formKey], !validity, fieldValidity {
|
||||
fieldValidity = false
|
||||
}
|
||||
|
||||
if fieldValidity {
|
||||
return (fieldValidity, previousValidity)
|
||||
}
|
||||
}
|
||||
|
||||
// if the rule breaks all fields should be set to false
|
||||
fields.forEach { (formKey) in
|
||||
previousValidity[formKey] = false
|
||||
}
|
||||
return (valid: false, fieldValidity: previousValidity)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,8 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
public class RuleAnyValueChangedModel: RulesProtocol {
|
||||
public class RuleAnyValueChangedModel: RuleAnyModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -27,26 +26,4 @@ public class RuleAnyValueChangedModel: RulesProtocol {
|
||||
public func isValid(_ formField: FormFieldProtocol) -> Bool {
|
||||
return formField.baseValue != formField.formFieldValue()
|
||||
}
|
||||
|
||||
public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) {
|
||||
var previousValidity: [String: Bool] = [:]
|
||||
for formKey in fields {
|
||||
guard let formField = fieldMolecules[formKey] else { continue }
|
||||
var fieldValidity = isValid(formField)
|
||||
// If past rule is invalid for a field, the current rule should not flip the validity of a field
|
||||
if let validity = previousFieldValidity[formKey], !validity, fieldValidity {
|
||||
fieldValidity = false
|
||||
}
|
||||
|
||||
if fieldValidity {
|
||||
return (true, previousValidity)
|
||||
}
|
||||
}
|
||||
|
||||
// if the rule breaks all fields should be set to false
|
||||
fields.forEach { (formKey) in
|
||||
previousValidity[formKey] = false
|
||||
}
|
||||
return (valid: false, fieldValidity: previousValidity)
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
//
|
||||
// RuleCompareModelProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Matt Bruce on 3/9/22.
|
||||
// Copyright © 2022 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// RuleCompareModelProtocol is meant to be used for rules that compare
|
||||
/// 2 FormField's values. It is up to the Implementing class to determine what
|
||||
/// occurs within the "compare" method that is required. This can be anything
|
||||
/// that returns a Bool. More than likley it will be a <,>, <=, =>, == comparison.
|
||||
public protocol RuleCompareModelProtocol: RulesProtocol {
|
||||
associatedtype CompareType
|
||||
func compare(lhs: CompareType?, rhs: CompareType?) -> Bool
|
||||
}
|
||||
|
||||
extension RuleCompareModelProtocol {
|
||||
|
||||
/// This overrides the RulesProtocol default implementation to then use your class implementation's "compare" method.
|
||||
/// A requirement of this rule is that the fields array contains at least 2 fieldKeys and it will pull out these formFields with ONLY
|
||||
/// the first 2 keys to send to the compare method your class will be implementing.
|
||||
public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: FormFieldValidity]) -> (valid: Bool, fieldValidity: [String: FormFieldValidity]) {
|
||||
var valid = false
|
||||
|
||||
guard fields.count > 1, let firstFormField = fieldMolecules[fields[0]],
|
||||
let secondFormField = fieldMolecules[fields[1]] else {
|
||||
return (valid: true, previousFieldValidity)
|
||||
}
|
||||
|
||||
let result = compare(lhs: firstFormField.formFieldValue() as? CompareType, rhs: secondFormField.formFieldValue() as? CompareType)
|
||||
|
||||
let formKey = fields[1]
|
||||
|
||||
//only check the 2nd value
|
||||
if result {
|
||||
valid = true
|
||||
|
||||
// If past rule is invalid for a field, the current rule should not flip the validity of a field
|
||||
if let validity = previousFieldValidity[formKey], !validity.valid, valid {
|
||||
valid = false
|
||||
}
|
||||
previousFieldValidity[formKey]?.valid = valid
|
||||
|
||||
} else { //false
|
||||
previousFieldValidity[formKey]?.valid = valid
|
||||
previousFieldValidity[formKey]?.addError(message: errorMessage?[formKey])
|
||||
}
|
||||
|
||||
return (valid: valid, fieldValidity: previousFieldValidity)
|
||||
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public class RuleEqualsIgnoreCaseModel: RulesProtocol {
|
||||
public class RuleEqualsIgnoreCaseModel: RuleCompareModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -27,35 +27,12 @@ public class RuleEqualsIgnoreCaseModel: RulesProtocol {
|
||||
public func isValid(_ formField: FormFieldProtocol) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) {
|
||||
var valid = false
|
||||
var compareText: String?
|
||||
|
||||
var previousValidity: [String: Bool] = [:]
|
||||
for formKey in fields {
|
||||
guard let formField = fieldMolecules[formKey] else { continue }
|
||||
|
||||
guard let compareString = compareText else {
|
||||
compareText = formField.formFieldValue() as? String
|
||||
continue
|
||||
}
|
||||
|
||||
if let fieldValue = formField.formFieldValue() as? String,
|
||||
compareString.caseInsensitiveCompare(fieldValue) == .orderedSame {
|
||||
valid = true
|
||||
|
||||
var fieldValidity = valid
|
||||
// If past rule is invalid for a field, the current rule should not flip the validity of a field
|
||||
if let validity = previousFieldValidity[formKey], !validity, fieldValidity {
|
||||
fieldValidity = false
|
||||
}
|
||||
previousValidity[formKey] = valid
|
||||
break
|
||||
}
|
||||
|
||||
previousValidity[formKey] = valid
|
||||
|
||||
///RuleCompareModelProtocol Method
|
||||
public func compare(lhs: String?, rhs: String?) -> Bool {
|
||||
guard let rhs = rhs else {
|
||||
return false
|
||||
}
|
||||
return (valid: valid, fieldValidity: previousValidity)
|
||||
return lhs?.caseInsensitiveCompare(rhs) == .orderedSame
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,8 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
public class RuleEqualsModel: RulesProtocol {
|
||||
public class RuleEqualsModel: RuleCompareModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -27,33 +26,10 @@ public class RuleEqualsModel: RulesProtocol {
|
||||
public func isValid(_ formField: FormFieldProtocol) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
public func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) {
|
||||
var valid = true
|
||||
var compareValue: AnyHashable?
|
||||
var previousValidity: [String: Bool] = [:]
|
||||
|
||||
for formKey in fields {
|
||||
guard let formField = fieldMolecules[formKey] else { continue }
|
||||
|
||||
if compareValue == nil {
|
||||
compareValue = formField.formFieldValue()
|
||||
continue
|
||||
}
|
||||
|
||||
if compareValue != formField.formFieldValue() {
|
||||
valid = false
|
||||
previousValidity[formKey] = valid
|
||||
break
|
||||
} else {
|
||||
var fieldValidity = valid
|
||||
// If past rule is invalid for a field, the current rule should not flip the validity of a field
|
||||
if let validity = previousFieldValidity[formKey], !validity, fieldValidity {
|
||||
fieldValidity = false
|
||||
}
|
||||
previousValidity[formKey] = valid
|
||||
}
|
||||
}
|
||||
return (valid: valid, fieldValidity: previousValidity)
|
||||
|
||||
///RuleCompareModelProtocol Method
|
||||
public func compare(lhs: AnyHashable?, rhs: AnyHashable?) -> Bool {
|
||||
return lhs == rhs
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ public protocol RulesProtocol: ModelProtocol {
|
||||
func isValid(_ formField: FormFieldProtocol) -> Bool
|
||||
|
||||
// Validates the rule and returns the result.
|
||||
func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool])
|
||||
func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: FormFieldValidity]) -> (valid: Bool, fieldValidity: [String: FormFieldValidity])
|
||||
}
|
||||
|
||||
public extension RulesProtocol {
|
||||
@ -42,21 +42,30 @@ public extension RulesProtocol {
|
||||
static var categoryName: String { "\(RulesProtocol.self)" }
|
||||
|
||||
// Individual rule can override the function to validate based on the rule type.
|
||||
func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: Bool]) -> (valid: Bool, fieldValidity: [String: Bool]) {
|
||||
func validate(_ fieldMolecules: [String: FormFieldProtocol],_ previousFieldValidity: [String: FormFieldValidity]) -> (valid: Bool, fieldValidity: [String: FormFieldValidity]) {
|
||||
var valid = true
|
||||
var previousValidity: [String: Bool] = [:]
|
||||
for formKey in fields {
|
||||
guard let formField = fieldMolecules[formKey] else { continue }
|
||||
|
||||
//check the field isValid
|
||||
var fieldValidity = isValid(formField)
|
||||
|
||||
//add the error message if it exists
|
||||
if fieldValidity == false {
|
||||
previousFieldValidity[formKey]?.addError(message: errorMessage?[formKey])
|
||||
}
|
||||
|
||||
// If past rule is invalid for a field, the current rule should not flip the validity of a field
|
||||
if let validity = previousFieldValidity[formKey], !validity, fieldValidity {
|
||||
if let validity = previousFieldValidity[formKey], !validity.valid, fieldValidity {
|
||||
fieldValidity = false
|
||||
}
|
||||
//set the valid for the field
|
||||
previousFieldValidity[formKey]?.valid = fieldValidity
|
||||
|
||||
//set the full validity
|
||||
valid = valid && fieldValidity
|
||||
previousValidity[formKey] = fieldValidity
|
||||
}
|
||||
return (valid: valid, fieldValidity: previousValidity)
|
||||
return (valid: valid, fieldValidity: previousFieldValidity)
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,16 +82,16 @@ public extension RulesContainerProtocol {
|
||||
/// - Returns: Tuple(valid, fieldValidity)
|
||||
/// - valid: bool for all rules
|
||||
/// - fieldValidity: accumulation of all fieldKey: valid
|
||||
func validate(_ fields: [String: FormFieldProtocol]) -> (valid: Bool, fieldValidity: [String:Bool] ) {
|
||||
func validate(_ fields: [String: FormFieldProtocol]) -> (valid: Bool, fieldValidity: [String:FormFieldValidity]) {
|
||||
// Validate each rule.
|
||||
var valid = true
|
||||
var previousValidity: [String: Bool] = [:]
|
||||
var previousValidity: [String: FormFieldValidity] = [:]
|
||||
fields.keys.forEach { key in
|
||||
previousValidity[key] = FormFieldValidity(key)
|
||||
}
|
||||
for rule in self.rules {
|
||||
//validate the rule against the fields
|
||||
let tuple = rule.validate(fields, previousValidity)
|
||||
|
||||
//merge the fieldValidity
|
||||
previousValidity = previousValidity.merging(tuple.fieldValidity) { (_, new) in new }
|
||||
valid = valid && tuple.valid
|
||||
}
|
||||
return (valid: valid, fieldValidity: previousValidity)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user