Merge branch 'develop' into feature/list_rightvariable_pricechange_alltextlinks
* develop: final clean Code cleanup model keys Updated updated Code as per confluence page color changes button will set groupname only when validation is required clean color code, move function hot fix number of columns per row updated number of columns variable added border related issues fixed spelling bugfix for load gif file form different bundle more fixes any required fixes
This commit is contained in:
commit
7a40bb1dc9
@ -32,7 +32,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
|
|||||||
public var disabledFillColor: Color?
|
public var disabledFillColor: Color?
|
||||||
public var disabledTextColor: Color?
|
public var disabledTextColor: Color?
|
||||||
public var disabledBorderColor: Color?
|
public var disabledBorderColor: Color?
|
||||||
public var groupName: String = FormValidator.defaultGroupName
|
public var groupName: String = ""
|
||||||
|
|
||||||
public func setValidity(_ valid: Bool, group: FormGroupRule) {
|
public func setValidity(_ valid: Bool, group: FormGroupRule) {
|
||||||
enabled = valid
|
enabled = valid
|
||||||
|
|||||||
@ -39,7 +39,7 @@ open class RadioBox: Control {
|
|||||||
super.setupView()
|
super.setupView()
|
||||||
|
|
||||||
layer.delegate = self
|
layer.delegate = self
|
||||||
layer.borderColor = UIColor.black.cgColor
|
layer.borderColor = UIColor.mvmCoolGray6.cgColor
|
||||||
layer.borderWidth = 1
|
layer.borderWidth = 1
|
||||||
|
|
||||||
label.numberOfLines = 1
|
label.numberOfLines = 1
|
||||||
@ -60,7 +60,7 @@ open class RadioBox: Control {
|
|||||||
|
|
||||||
// MARK: - MoleculeViewProtocol
|
// MARK: - MoleculeViewProtocol
|
||||||
|
|
||||||
public 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)
|
super.set(with: model, delegateObject, additionalData)
|
||||||
guard let model = model as? RadioBoxModel else { return }
|
guard let model = model as? RadioBoxModel else { return }
|
||||||
isSelected = model.selected
|
isSelected = model.selected
|
||||||
@ -69,6 +69,15 @@ open class RadioBox: Control {
|
|||||||
subTextLabel.text = model.subText
|
subTextLabel.text = model.subText
|
||||||
isOutOfStock = model.strikethrough
|
isOutOfStock = model.strikethrough
|
||||||
subTextLabelHeightConstraint?.isActive = (subTextLabel.text?.count ?? 0) == 0
|
subTextLabelHeightConstraint?.isActive = (subTextLabel.text?.count ?? 0) == 0
|
||||||
|
if let color = model.selectedAccentColor?.uiColor {
|
||||||
|
accentColor = color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func reset() {
|
||||||
|
super.reset()
|
||||||
|
backgroundColor = .white
|
||||||
|
accentColor = .mvmRed
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - State Handling
|
// MARK: - State Handling
|
||||||
@ -77,11 +86,12 @@ open class RadioBox: Control {
|
|||||||
// Draw the strikethrough
|
// Draw the strikethrough
|
||||||
strikeLayer?.removeFromSuperlayer()
|
strikeLayer?.removeFromSuperlayer()
|
||||||
if isOutOfStock {
|
if isOutOfStock {
|
||||||
let line = getStrikeThrough(color: .black, thickness: 1)
|
let line = getStrikeThrough(color: isSelected ? .black : .mvmCoolGray6, thickness: 1)
|
||||||
layer.addSublayer(line)
|
layer.addSublayer(line)
|
||||||
strikeLayer = line
|
strikeLayer = line
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Draw the border
|
// Draw the border
|
||||||
borderLayer?.removeFromSuperlayer()
|
borderLayer?.removeFromSuperlayer()
|
||||||
if isSelected {
|
if isSelected {
|
||||||
@ -98,6 +108,7 @@ open class RadioBox: Control {
|
|||||||
if !isEnabled {
|
if !isEnabled {
|
||||||
let mask = getMaskLayer()
|
let mask = getMaskLayer()
|
||||||
layer.mask = mask
|
layer.mask = mask
|
||||||
|
maskLayer = mask
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,6 +119,7 @@ open class RadioBox: Control {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc open func selectBox() {
|
@objc open func selectBox() {
|
||||||
|
guard isEnabled else { return }
|
||||||
isSelected = true
|
isSelected = true
|
||||||
radioBoxModel?.selected = isSelected
|
radioBoxModel?.selected = isSelected
|
||||||
layer.setNeedsDisplay()
|
layer.setNeedsDisplay()
|
||||||
@ -131,7 +143,7 @@ open class RadioBox: Control {
|
|||||||
|
|
||||||
let topLineLayer = CAShapeLayer()
|
let topLineLayer = CAShapeLayer()
|
||||||
topLineLayer.fillColor = nil
|
topLineLayer.fillColor = nil
|
||||||
topLineLayer.strokeColor = UIColor.mvmRed.cgColor
|
topLineLayer.strokeColor = accentColor.cgColor
|
||||||
topLineLayer.lineWidth = 4
|
topLineLayer.lineWidth = 4
|
||||||
topLineLayer.path = topLinePath.cgPath
|
topLineLayer.path = topLinePath.cgPath
|
||||||
layer.addSublayer(topLineLayer)
|
layer.addSublayer(topLineLayer)
|
||||||
|
|||||||
@ -8,7 +8,12 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
open class RadioBoxCollectionViewCell: CollectionViewCell {
|
open class RadioBoxCollectionViewCell: CollectionViewCell {
|
||||||
let radioBox = RadioBox()
|
public let radioBox = RadioBox()
|
||||||
|
|
||||||
|
open override func reset() {
|
||||||
|
super.reset()
|
||||||
|
backgroundColor = .clear
|
||||||
|
}
|
||||||
|
|
||||||
open override func setupView() {
|
open override func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
|
|||||||
@ -11,8 +11,8 @@ import Foundation
|
|||||||
public static var identifier: String = "radioBox"
|
public static var identifier: String = "radioBox"
|
||||||
public var text: String
|
public var text: String
|
||||||
public var subText: String?
|
public var subText: String?
|
||||||
public var backgroundColor: Color? = Color(uiColor: .white)
|
public var backgroundColor: Color?
|
||||||
public var selectedAccentColor = Color(uiColor: .mvmRed)
|
public var selectedAccentColor: Color?
|
||||||
public var selected: Bool = false
|
public var selected: Bool = false
|
||||||
public var enabled: Bool = true
|
public var enabled: Bool = true
|
||||||
public var strikethrough: Bool = false
|
public var strikethrough: Bool = false
|
||||||
@ -34,12 +34,8 @@ import Foundation
|
|||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
text = try typeContainer.decode(String.self, forKey: .text)
|
text = try typeContainer.decode(String.self, forKey: .text)
|
||||||
subText = try typeContainer.decodeIfPresent(String.self, forKey: .subText)
|
subText = try typeContainer.decodeIfPresent(String.self, forKey: .subText)
|
||||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor) {
|
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
|
||||||
selectedAccentColor = color
|
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||||
}
|
|
||||||
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) {
|
|
||||||
backgroundColor = color
|
|
||||||
}
|
|
||||||
if let isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
|
if let isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
|
||||||
selected = isSelected
|
selected = isSelected
|
||||||
}
|
}
|
||||||
@ -58,7 +54,7 @@ import Foundation
|
|||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encode(text, forKey: .text)
|
try container.encode(text, forKey: .text)
|
||||||
try container.encodeIfPresent(subText, forKey: .subText)
|
try container.encodeIfPresent(subText, forKey: .subText)
|
||||||
try container.encode(selectedAccentColor, forKey: .selectedAccentColor)
|
try container.encodeIfPresent(selectedAccentColor, forKey: .selectedAccentColor)
|
||||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||||
try container.encode(selected, forKey: .selected)
|
try container.encode(selected, forKey: .selected)
|
||||||
try container.encode(enabled, forKey: .enabled)
|
try container.encode(enabled, forKey: .enabled)
|
||||||
|
|||||||
@ -15,7 +15,11 @@ open class RadioBoxes: View {
|
|||||||
private let boxWidth: CGFloat = 151.0
|
private let boxWidth: CGFloat = 151.0
|
||||||
private let boxHeight: CGFloat = 64.0
|
private let boxHeight: CGFloat = 64.0
|
||||||
private let itemSpacing: CGFloat = 8.0
|
private let itemSpacing: CGFloat = 8.0
|
||||||
|
private var numberOfColumns: CGFloat = 2.0
|
||||||
|
private var radioBoxesModel: RadioBoxesModel? {
|
||||||
|
return model as? RadioBoxesModel
|
||||||
|
}
|
||||||
|
|
||||||
private var delegateObject: MVMCoreUIDelegateObject?
|
private var delegateObject: MVMCoreUIDelegateObject?
|
||||||
|
|
||||||
/// The models for the molecules.
|
/// The models for the molecules.
|
||||||
@ -42,7 +46,7 @@ open class RadioBoxes: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - MoleculeViewProtocol
|
// MARK: - MoleculeViewProtocol
|
||||||
public 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)
|
super.set(with: model, delegateObject, additionalData)
|
||||||
self.delegateObject = delegateObject
|
self.delegateObject = delegateObject
|
||||||
|
|
||||||
@ -94,7 +98,7 @@ open class RadioBoxes: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the height
|
// Calculate the height
|
||||||
let rows = ceil(CGFloat(boxes.count) / 2.0)
|
let rows = ceil(CGFloat(boxes.count) / numberOfColumns)
|
||||||
let height = (rows * boxHeight) + ((rows - 1) * itemSpacing)
|
let height = (rows * boxHeight) + ((rows - 1) * itemSpacing)
|
||||||
collectionViewHeight?.constant = height
|
collectionViewHeight?.constant = height
|
||||||
}
|
}
|
||||||
@ -102,7 +106,7 @@ open class RadioBoxes: View {
|
|||||||
|
|
||||||
extension RadioBoxes: UICollectionViewDelegateFlowLayout {
|
extension RadioBoxes: UICollectionViewDelegateFlowLayout {
|
||||||
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
|
||||||
let itemWidth: CGFloat = (collectionView.bounds.width - itemSpacing) / 2
|
let itemWidth: CGFloat = (collectionView.bounds.width - itemSpacing) / numberOfColumns
|
||||||
return CGSize(width: itemWidth, height: boxHeight)
|
return CGSize(width: itemWidth, height: boxHeight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,7 +121,16 @@ extension RadioBoxes: UICollectionViewDataSource {
|
|||||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioBoxCollectionViewCell", for: indexPath) as? RadioBoxCollectionViewCell else {
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioBoxCollectionViewCell", for: indexPath) as? RadioBoxCollectionViewCell else {
|
||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
|
cell.reset()
|
||||||
cell.radioBox.isUserInteractionEnabled = false
|
cell.radioBox.isUserInteractionEnabled = false
|
||||||
|
|
||||||
|
if let color = radioBoxesModel?.boxesColor {
|
||||||
|
cell.radioBox.backgroundColor = color.uiColor
|
||||||
|
}
|
||||||
|
if let color = radioBoxesModel?.selectedAccentColor {
|
||||||
|
cell.radioBox.accentColor = color.uiColor
|
||||||
|
}
|
||||||
|
|
||||||
cell.set(with: molecule, delegateObject, nil)
|
cell.set(with: molecule, delegateObject, nil)
|
||||||
cell.updateView(size ?? collectionView.bounds.width)
|
cell.updateView(size ?? collectionView.bounds.width)
|
||||||
if molecule.selected {
|
if molecule.selected {
|
||||||
@ -129,13 +142,18 @@ extension RadioBoxes: UICollectionViewDataSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension RadioBoxes: UICollectionViewDelegate {
|
extension RadioBoxes: UICollectionViewDelegate {
|
||||||
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
open func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
|
||||||
|
guard let molecule = boxes?[indexPath.row] else { return false }
|
||||||
|
return molecule.enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioBoxCollectionViewCell else { return }
|
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioBoxCollectionViewCell else { return }
|
||||||
cell.radioBox.selectBox()
|
cell.radioBox.selectBox()
|
||||||
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
open func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
||||||
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioBoxCollectionViewCell else { return }
|
guard let cell = collectionView.cellForItem(at: indexPath) as? RadioBoxCollectionViewCell else { return }
|
||||||
cell.radioBox.deselectBox()
|
cell.radioBox.deselectBox()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,9 +9,10 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
@objcMembers public class RadioBoxesModel: MoleculeModelProtocol, FormFieldProtocol {
|
@objcMembers public class RadioBoxesModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||||
public static var identifier: String = "radioBoxes"
|
public static var identifier: String = "radioBoxes"
|
||||||
|
public var boxes: [RadioBoxModel]
|
||||||
public var backgroundColor: Color?
|
public var backgroundColor: Color?
|
||||||
public var selectedAccentColor: Color?
|
public var selectedAccentColor: Color?
|
||||||
public var boxes: [RadioBoxModel]
|
public var boxesColor: Color?
|
||||||
public var fieldKey: String?
|
public var fieldKey: String?
|
||||||
public var groupName: String = FormValidator.defaultGroupName
|
public var groupName: String = FormValidator.defaultGroupName
|
||||||
public var baseValue: AnyHashable?
|
public var baseValue: AnyHashable?
|
||||||
@ -28,6 +29,7 @@ import Foundation
|
|||||||
case moleculeName
|
case moleculeName
|
||||||
case selectedAccentColor
|
case selectedAccentColor
|
||||||
case backgroundColor
|
case backgroundColor
|
||||||
|
case boxesColor
|
||||||
case boxes
|
case boxes
|
||||||
case fieldKey
|
case fieldKey
|
||||||
case groupName
|
case groupName
|
||||||
@ -37,6 +39,7 @@ import Foundation
|
|||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
|
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
|
||||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||||
|
boxesColor = try typeContainer.decodeIfPresent(Color.self, forKey: .boxesColor)
|
||||||
boxes = try typeContainer.decode([RadioBoxModel].self, forKey: .boxes)
|
boxes = try typeContainer.decode([RadioBoxModel].self, forKey: .boxes)
|
||||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||||
|
|||||||
@ -276,7 +276,7 @@ import UIKit
|
|||||||
let fallbackImageName = customFallbackImage ?? MVMCoreUIUtility.localizedImageName("fallback")
|
let fallbackImageName = customFallbackImage ?? MVMCoreUIUtility.localizedImageName("fallback")
|
||||||
if let format = format, format.lowercased().contains("gif") {
|
if let format = format, format.lowercased().contains("gif") {
|
||||||
// Gifs aren't supported by default and need special handling
|
// Gifs aren't supported by default and need special handling
|
||||||
MVMCoreCache.shared()?.getGif(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, completionHandler: finishedLoadingBlock)
|
MVMCoreCache.shared()?.getGif(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock)
|
||||||
} else {
|
} else {
|
||||||
MVMCoreCache.shared()?.getImage(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock)
|
MVMCoreCache.shared()?.getImage(imageName, useWidth: width != nil, widthForS7: width?.intValue ?? 0, useHeight: height != nil, heightForS7: height?.intValue ?? 0, format: format, localFallbackImageName: fallbackImageName, allowServerQueryParameters: allowServerParameters, localBundle: localBundle, completionHandler: finishedLoadingBlock)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -266,9 +266,7 @@ import UIKit
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle data for first load. Dispatched to allow subclasses to finish their view did load implementations.
|
// Handle data for first load. Dispatched to allow subclasses to finish their view did load implementations.
|
||||||
DispatchQueue.main.async {
|
self.handleNewDataAndUpdateUI()
|
||||||
self.handleNewDataAndUpdateUI()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func viewDidLayoutSubviews() {
|
open override func viewDidLayoutSubviews() {
|
||||||
@ -292,8 +290,10 @@ import UIKit
|
|||||||
open override func viewWillAppear(_ animated: Bool) {
|
open override func viewWillAppear(_ animated: Bool) {
|
||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
|
|
||||||
// Update the navigation bar ui when view is appearing
|
// Update the navigation bar ui when view is appearing. Can remove check in the future, see viewControllerReady
|
||||||
setNavigationController()
|
if manager == nil {
|
||||||
|
setNavigationController()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func viewDidAppear(_ animated: Bool) {
|
open override func viewDidAppear(_ animated: Bool) {
|
||||||
@ -326,6 +326,10 @@ import UIKit
|
|||||||
|
|
||||||
// MARK: - MVMCoreViewManagerViewControllerProtocol
|
// MARK: - MVMCoreViewManagerViewControllerProtocol
|
||||||
open func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) {
|
open func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) {
|
||||||
|
// TODO: This check and set aren't technically needed anymore. The one in viewwillappear should be enough. However, there is a timing issue with the manager where the screen lays out before the menu shows, so the screen grows off the screen. Can fix in the future.
|
||||||
|
if let _ = self.view {
|
||||||
|
setNavigationController()
|
||||||
|
}
|
||||||
// Janky way to track current page.
|
// Janky way to track current page.
|
||||||
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
|
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
|
||||||
MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self)
|
MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self)
|
||||||
|
|||||||
@ -89,7 +89,7 @@ import MVMCore
|
|||||||
// Validate each rule.
|
// Validate each rule.
|
||||||
var valid = true
|
var valid = true
|
||||||
for rule in group.rules {
|
for rule in group.rules {
|
||||||
valid = valid && validateRule(rule)
|
valid = valid && rule.validate(fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify the group watchers of validity.
|
// Notify the group watchers of validity.
|
||||||
@ -98,19 +98,6 @@ import MVMCore
|
|||||||
watcher.setValidity(valid, group: group)
|
watcher.setValidity(valid, group: group)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return valid
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Validates a given rule. Returns if valid.
|
|
||||||
public func validateRule(_ rule: RulesProtocol) -> Bool {
|
|
||||||
var valid = true
|
|
||||||
for formKey in rule.fields {
|
|
||||||
guard let formField = fields[formKey] else { continue }
|
|
||||||
let fieldValidity = rule.isValid(formField)
|
|
||||||
(formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: rule)
|
|
||||||
valid = valid && fieldValidity
|
|
||||||
}
|
|
||||||
return valid
|
return valid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,7 @@ public class RuleAnyRequiredModel: RulesProtocol {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
public func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
|
public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
|
||||||
|
|
||||||
for formKey in fields {
|
for formKey in fields {
|
||||||
guard let formField = fieldMolecules[formKey] else { continue }
|
guard let formField = fieldMolecules[formKey] else { continue }
|
||||||
|
|||||||
@ -26,16 +26,13 @@ public class RuleAnyValueChangedModel: RulesProtocol {
|
|||||||
return formField.baseValue != formField.formFieldValue()
|
return formField.baseValue != formField.formFieldValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
|
public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
|
||||||
|
|
||||||
for formKey in fields {
|
for formKey in fields {
|
||||||
guard let formField = fieldMolecules[formKey] else { continue }
|
guard let formField = fieldMolecules[formKey] else { continue }
|
||||||
|
|
||||||
if isValid(formField) {
|
if isValid(formField) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,8 +26,7 @@ public class RuleEqualsModel: RulesProtocol {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
public func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
|
public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
|
||||||
|
|
||||||
var valid = true
|
var valid = true
|
||||||
var compareValue: AnyHashable?
|
var compareValue: AnyHashable?
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,9 @@ public protocol RulesProtocol: ModelProtocol {
|
|||||||
|
|
||||||
// Returns if a given field is valid according to the rule
|
// Returns if a given field is valid according to the rule
|
||||||
func isValid(_ formField: FormFieldProtocol) -> Bool
|
func isValid(_ formField: FormFieldProtocol) -> Bool
|
||||||
|
|
||||||
|
// Validates the rule and returns the result.
|
||||||
|
func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension RulesProtocol {
|
public extension RulesProtocol {
|
||||||
@ -37,4 +40,16 @@ public extension RulesProtocol {
|
|||||||
static var categoryName: String {
|
static var categoryName: String {
|
||||||
return "\(RulesProtocol.self)"
|
return "\(RulesProtocol.self)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Individual rule can override the function to validate based on the rule type.
|
||||||
|
func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
|
||||||
|
var valid = true
|
||||||
|
for formKey in fields {
|
||||||
|
guard let formField = fieldMolecules[formKey] else { continue }
|
||||||
|
let fieldValidity = isValid(formField)
|
||||||
|
(formField as? FormRuleWatcherFieldProtocol)?.setValidity(fieldValidity, rule: self)
|
||||||
|
valid = valid && fieldValidity
|
||||||
|
}
|
||||||
|
return valid
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user