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:
Kruthika KP 2020-04-17 13:13:52 +05:30
commit 7a40bb1dc9
13 changed files with 86 additions and 50 deletions

View File

@ -32,7 +32,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormGroupW
public var disabledFillColor: Color?
public var disabledTextColor: Color?
public var disabledBorderColor: Color?
public var groupName: String = FormValidator.defaultGroupName
public var groupName: String = ""
public func setValidity(_ valid: Bool, group: FormGroupRule) {
enabled = valid

View File

@ -39,7 +39,7 @@ open class RadioBox: Control {
super.setupView()
layer.delegate = self
layer.borderColor = UIColor.black.cgColor
layer.borderColor = UIColor.mvmCoolGray6.cgColor
layer.borderWidth = 1
label.numberOfLines = 1
@ -60,7 +60,7 @@ open class RadioBox: Control {
// 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)
guard let model = model as? RadioBoxModel else { return }
isSelected = model.selected
@ -69,6 +69,15 @@ open class RadioBox: Control {
subTextLabel.text = model.subText
isOutOfStock = model.strikethrough
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
@ -77,11 +86,12 @@ open class RadioBox: Control {
// Draw the strikethrough
strikeLayer?.removeFromSuperlayer()
if isOutOfStock {
let line = getStrikeThrough(color: .black, thickness: 1)
let line = getStrikeThrough(color: isSelected ? .black : .mvmCoolGray6, thickness: 1)
layer.addSublayer(line)
strikeLayer = line
}
// Draw the border
borderLayer?.removeFromSuperlayer()
if isSelected {
@ -98,6 +108,7 @@ open class RadioBox: Control {
if !isEnabled {
let mask = getMaskLayer()
layer.mask = mask
maskLayer = mask
}
}
@ -108,6 +119,7 @@ open class RadioBox: Control {
}
@objc open func selectBox() {
guard isEnabled else { return }
isSelected = true
radioBoxModel?.selected = isSelected
layer.setNeedsDisplay()
@ -131,7 +143,7 @@ open class RadioBox: Control {
let topLineLayer = CAShapeLayer()
topLineLayer.fillColor = nil
topLineLayer.strokeColor = UIColor.mvmRed.cgColor
topLineLayer.strokeColor = accentColor.cgColor
topLineLayer.lineWidth = 4
topLineLayer.path = topLinePath.cgPath
layer.addSublayer(topLineLayer)

View File

@ -8,7 +8,12 @@
import Foundation
open class RadioBoxCollectionViewCell: CollectionViewCell {
let radioBox = RadioBox()
public let radioBox = RadioBox()
open override func reset() {
super.reset()
backgroundColor = .clear
}
open override func setupView() {
super.setupView()

View File

@ -11,8 +11,8 @@ import Foundation
public static var identifier: String = "radioBox"
public var text: String
public var subText: String?
public var backgroundColor: Color? = Color(uiColor: .white)
public var selectedAccentColor = Color(uiColor: .mvmRed)
public var backgroundColor: Color?
public var selectedAccentColor: Color?
public var selected: Bool = false
public var enabled: Bool = true
public var strikethrough: Bool = false
@ -34,12 +34,8 @@ import Foundation
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
text = try typeContainer.decode(String.self, forKey: .text)
subText = try typeContainer.decodeIfPresent(String.self, forKey: .subText)
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor) {
selectedAccentColor = color
}
if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) {
backgroundColor = color
}
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
if let isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .selected) {
selected = isSelected
}
@ -58,7 +54,7 @@ import Foundation
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(text, forKey: .text)
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.encode(selected, forKey: .selected)
try container.encode(enabled, forKey: .enabled)

View File

@ -15,7 +15,11 @@ open class RadioBoxes: View {
private let boxWidth: CGFloat = 151.0
private let boxHeight: CGFloat = 64.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?
/// The models for the molecules.
@ -42,7 +46,7 @@ open class RadioBoxes: View {
}
// 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)
self.delegateObject = delegateObject
@ -94,7 +98,7 @@ open class RadioBoxes: View {
}
// 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)
collectionViewHeight?.constant = height
}
@ -102,7 +106,7 @@ open class RadioBoxes: View {
extension RadioBoxes: UICollectionViewDelegateFlowLayout {
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)
}
}
@ -117,7 +121,16 @@ extension RadioBoxes: UICollectionViewDataSource {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RadioBoxCollectionViewCell", for: indexPath) as? RadioBoxCollectionViewCell else {
fatalError()
}
cell.reset()
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.updateView(size ?? collectionView.bounds.width)
if molecule.selected {
@ -129,13 +142,18 @@ extension RadioBoxes: UICollectionViewDataSource {
}
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 }
cell.radioBox.selectBox()
_ = 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 }
cell.radioBox.deselectBox()
}

View File

@ -9,9 +9,10 @@
import Foundation
@objcMembers public class RadioBoxesModel: MoleculeModelProtocol, FormFieldProtocol {
public static var identifier: String = "radioBoxes"
public var boxes: [RadioBoxModel]
public var backgroundColor: Color?
public var selectedAccentColor: Color?
public var boxes: [RadioBoxModel]
public var boxesColor: Color?
public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable?
@ -28,6 +29,7 @@ import Foundation
case moleculeName
case selectedAccentColor
case backgroundColor
case boxesColor
case boxes
case fieldKey
case groupName
@ -37,6 +39,7 @@ import Foundation
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
selectedAccentColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedAccentColor)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
boxesColor = try typeContainer.decodeIfPresent(Color.self, forKey: .boxesColor)
boxes = try typeContainer.decode([RadioBoxModel].self, forKey: .boxes)
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {

View File

@ -276,7 +276,7 @@ import UIKit
let fallbackImageName = customFallbackImage ?? MVMCoreUIUtility.localizedImageName("fallback")
if let format = format, format.lowercased().contains("gif") {
// 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 {
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)
}

View File

@ -266,9 +266,7 @@ import UIKit
}
// 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() {
@ -292,8 +290,10 @@ import UIKit
open override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Update the navigation bar ui when view is appearing
setNavigationController()
// Update the navigation bar ui when view is appearing. Can remove check in the future, see viewControllerReady
if manager == nil {
setNavigationController()
}
}
open override func viewDidAppear(_ animated: Bool) {
@ -326,6 +326,10 @@ import UIKit
// MARK: - MVMCoreViewManagerViewControllerProtocol
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.
MVMCoreUISession.sharedGlobal()?.currentPageType = pageType
MVMCoreUILoggingHandler.shared()?.defaultLogPageState(forController: self)

View File

@ -89,7 +89,7 @@ import MVMCore
// Validate each rule.
var valid = true
for rule in group.rules {
valid = valid && validateRule(rule)
valid = valid && rule.validate(fields)
}
// Notify the group watchers of validity.
@ -98,19 +98,6 @@ import MVMCore
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
}
}

View File

@ -35,7 +35,7 @@ public class RuleAnyRequiredModel: RulesProtocol {
return false
}
public func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
for formKey in fields {
guard let formField = fieldMolecules[formKey] else { continue }

View File

@ -26,16 +26,13 @@ public class RuleAnyValueChangedModel: RulesProtocol {
return formField.baseValue != formField.formFieldValue()
}
public func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
for formKey in fields {
guard let formField = fieldMolecules[formKey] else { continue }
if isValid(formField) {
return true
}
}
}
return false
}
}

View File

@ -26,8 +26,7 @@ public class RuleEqualsModel: RulesProtocol {
return false
}
public func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
public func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
var valid = true
var compareValue: AnyHashable?

View File

@ -22,6 +22,9 @@ public protocol RulesProtocol: ModelProtocol {
// Returns if a given field is valid according to the rule
func isValid(_ formField: FormFieldProtocol) -> Bool
// Validates the rule and returns the result.
func validate(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool
}
public extension RulesProtocol {
@ -37,4 +40,16 @@ public extension RulesProtocol {
static var categoryName: String {
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
}
}