Merge branch 'feature/taggingForSelectors' into 'develop'

added action support for selectors and dropDown

See merge request BPHV_MIPS/mvm_core_ui!590
This commit is contained in:
Pfeil, Scott Robert 2020-09-18 18:03:08 -04:00
commit 1bc655192a
14 changed files with 104 additions and 19 deletions

View File

@ -27,6 +27,11 @@ import UIKit
return caret return caret
}() }()
public var baseDropdownEntryFieldModel: BaseDropdownEntryFieldModel? {
return model as? BaseDropdownEntryFieldModel
}
var additionalData: [AnyHashable: Any]?
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Property Observers // MARK: - Property Observers
//-------------------------------------------------- //--------------------------------------------------
@ -75,9 +80,22 @@ import UIKit
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.set(with: model, delegateObject, additionalData) super.set(with: model, delegateObject, additionalData)
self.additionalData = additionalData
guard let model = model as? BaseDropdownEntryFieldModel else { return } guard let model = model as? BaseDropdownEntryFieldModel else { return }
dropDownCaretView.setOptional(with: model.caretView, delegateObject, additionalData) dropDownCaretView.setOptional(with: model.caretView, delegateObject, additionalData)
} }
public override func dismissFieldInput(_ sender: Any?) {
performDropdownAction()
super.dismissFieldInput(sender)
}
func performDropdownAction() {
if let actionModel = baseDropdownEntryFieldModel?.action, let actionMap = actionModel.toJSON() {
var additionalData = self.additionalData ?? [:]
additionalData[KeySourceModel] = baseDropdownEntryFieldModel
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject)
}
}
} }

View File

@ -12,6 +12,7 @@
//-------------------------------------------------- //--------------------------------------------------
public var caretView: CaretViewModel? public var caretView: CaretViewModel?
public var action: ActionModelProtocol?
public override class var identifier: String { public override class var identifier: String {
return "" return ""
@ -24,6 +25,7 @@
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
case caretView case caretView
case action
} }
//-------------------------------------------------- //--------------------------------------------------
@ -34,6 +36,7 @@
try super.init(from: decoder) try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
caretView = try typeContainer.decodeIfPresent(CaretViewModel.self, forKey: .caretView) caretView = try typeContainer.decodeIfPresent(CaretViewModel.self, forKey: .caretView)
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
@ -41,5 +44,6 @@
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(caretView, forKey: .caretView) try container.encode(caretView, forKey: .caretView)
try container.encodeModelIfPresent(action, forKey: .action)
} }
} }

View File

@ -109,8 +109,8 @@ open class ItemDropdownEntryField: BaseDropdownEntryField {
pickerData = model.options pickerData = model.options
setPickerDelegates(delegate: self) setPickerDelegates(delegate: self)
if let pickerView = pickerView { if let pickerView = pickerView, let index = model.selectedIndex {
self.pickerView(pickerView, didSelectRow: model.selectedIndex, inComponent: 0) self.pickerView(pickerView, didSelectRow: index, inComponent: 0)
} }
} }
} }

View File

@ -16,11 +16,14 @@
} }
public var options: [String] = [] public var options: [String] = []
public var selectedIndex: Int = 0 public var selectedIndex: Int?
public override func formFieldValue() -> AnyHashable? { public override func formFieldValue() -> AnyHashable? {
guard !options.isEmpty else { return nil } guard !options.isEmpty,
return options[selectedIndex] let index = selectedIndex
else { return nil }
return options[index]
} }
//-------------------------------------------------- //--------------------------------------------------
@ -45,13 +48,16 @@
if let selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) { if let selectedIndex = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) {
self.selectedIndex = selectedIndex self.selectedIndex = selectedIndex
} }
baseValue = options.indices.contains(selectedIndex) ? options[selectedIndex] : nil
if let index = selectedIndex {
baseValue = options.indices.contains(index) ? options[index] : nil
}
} }
public override func encode(to encoder: Encoder) throws { public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder) try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(options, forKey: .options) try container.encode(options, forKey: .options)
try container.encode(options, forKey: .selectedIndex) try container.encodeIfPresent(options, forKey: .selectedIndex)
} }
} }

View File

@ -24,6 +24,10 @@ import MVMCore
var groupName: String? var groupName: String?
var delegateObject: MVMCoreUIDelegateObject? var delegateObject: MVMCoreUIDelegateObject?
public var checkboxModel: CheckboxModel? {
return model as? CheckboxModel
}
public static let defaultHeightWidth: CGFloat = 18.0 public static let defaultHeightWidth: CGFloat = 18.0
/// If true the border of this checkbox will be circular. /// If true the border of this checkbox will be circular.
@ -381,7 +385,7 @@ import MVMCore
checkWidth = 2 checkWidth = 2
checkAndBypassAnimations(selected: false) checkAndBypassAnimations(selected: false)
} }
public override func updateView(_ size: CGFloat) { public override func updateView(_ size: CGFloat) {
super.updateView(size) super.updateView(size)
@ -391,6 +395,14 @@ import MVMCore
} }
} }
private func performCheckboxAction(with actionModel: ActionModelProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
if let actionMap = actionModel.toJSON() {
var additionalDatatoUpdate = additionalData ?? [:]
additionalDatatoUpdate[KeySourceModel] = checkboxModel
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalDatatoUpdate, delegateObject: delegateObject)
}
}
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public 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
@ -422,10 +434,15 @@ import MVMCore
isEnabled = model.enabled isEnabled = model.enabled
if let action = model.action { if (model.action != nil || model.offAction != nil) {
actionBlock = { actionBlock = { [weak self] in
if let actionMap = action.toJSON() { guard let self = self else { return }
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject)
if let offAction = model.offAction, !self.isSelected {
self.performCheckboxAction(with: offAction, delegateObject: delegateObject, additionalData: additionalData)
} else if let action = model.action {
self.performCheckboxAction(with: action, delegateObject: delegateObject, additionalData: additionalData)
} }
} }
} }

View File

@ -32,6 +32,7 @@ import Foundation
public var invertedColor: Color = Color(uiColor: .mvmWhite) public var invertedColor: Color = Color(uiColor: .mvmWhite)
public var invertedBackgroundColor: Color = Color(uiColor: .mvmBlack) public var invertedBackgroundColor: Color = Color(uiColor: .mvmBlack)
public var action: ActionModelProtocol? public var action: ActionModelProtocol?
public var offAction: ActionModelProtocol?
public var fieldKey: String? public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName public var groupName: String = FormValidator.defaultGroupName
@ -61,6 +62,7 @@ import Foundation
case action case action
case fieldKey case fieldKey
case groupName case groupName
case offAction
} }
//-------------------------------------------------- //--------------------------------------------------
@ -155,6 +157,7 @@ import Foundation
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName self.groupName = groupName
} }
offAction = try typeContainer.decodeModelIfPresent(codingKey: .offAction)
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -179,5 +182,6 @@ import Foundation
try container.encodeIfPresent(enabled, forKey: .enabled) try container.encodeIfPresent(enabled, forKey: .enabled)
try container.encodeModelIfPresent(action, forKey: .action) try container.encodeModelIfPresent(action, forKey: .action)
try container.encodeIfPresent(groupName, forKey: .groupName) try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encodeModelIfPresent(offAction, forKey: .offAction)
} }
} }

View File

@ -8,7 +8,7 @@
import Foundation import Foundation
open class RadioBox: Control { open class RadioBox: Control, MFButtonProtocol {
public let label = Label(fontStyle: .RegularBodySmall) public let label = Label(fontStyle: .RegularBodySmall)
public let subTextLabel = Label(fontStyle: .RegularMicro) public let subTextLabel = Label(fontStyle: .RegularMicro)
public var isOutOfStock = false public var isOutOfStock = false
@ -22,6 +22,9 @@ open class RadioBox: Control {
public var subTextLabelHeightConstraint: NSLayoutConstraint? public var subTextLabelHeightConstraint: NSLayoutConstraint?
private var delegateObject: MVMCoreUIDelegateObject?
var additionalData: [AnyHashable: Any]?
public var radioBoxModel: RadioBoxModel? { public var radioBoxModel: RadioBoxModel? {
return model as? RadioBoxModel return model as? RadioBoxModel
} }
@ -77,6 +80,8 @@ open class RadioBox: Control {
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) super.set(with: model, delegateObject, additionalData)
guard let model = model as? RadioBoxModel else { return } guard let model = model as? RadioBoxModel else { return }
self.delegateObject = delegateObject
self.additionalData = additionalData
label.text = model.text label.text = model.text
subTextLabel.text = model.subText subTextLabel.text = model.subText
isOutOfStock = model.strikethrough isOutOfStock = model.strikethrough
@ -135,6 +140,11 @@ open class RadioBox: Control {
guard isEnabled else { return } guard isEnabled else { return }
isSelected = true isSelected = true
radioBoxModel?.selected = isSelected radioBoxModel?.selected = isSelected
if let actionModel = radioBoxModel?.action {
var additionalData = self.additionalData ?? [:]
additionalData[KeySourceModel] = radioBoxModel
Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData)
}
layer.setNeedsDisplay() layer.setNeedsDisplay()
} }

View File

@ -17,6 +17,7 @@ import Foundation
public var enabled: Bool = true public var enabled: Bool = true
public var strikethrough: Bool = false public var strikethrough: Bool = false
public var fieldValue: String? public var fieldValue: String?
public var action: ActionModelProtocol?
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
@ -28,6 +29,7 @@ import Foundation
case enabled case enabled
case strikethrough case strikethrough
case fieldValue case fieldValue
case action
} }
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
@ -47,6 +49,7 @@ import Foundation
} }
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -60,5 +63,6 @@ import Foundation
try container.encode(enabled, forKey: .enabled) try container.encode(enabled, forKey: .enabled)
try container.encode(strikethrough, forKey: .strikethrough) try container.encode(strikethrough, forKey: .strikethrough)
try container.encodeIfPresent(fieldValue, forKey: .fieldValue) try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
try container.encodeModelIfPresent(action, forKey: .action)
} }
} }

View File

@ -30,6 +30,7 @@ import UIKit
public var enabledColor: UIColor = .mvmBlack public var enabledColor: UIColor = .mvmBlack
public var disabledColor: UIColor = .mvmCoolGray3 public var disabledColor: UIColor = .mvmCoolGray3
public var delegateObject: MVMCoreUIDelegateObject? public var delegateObject: MVMCoreUIDelegateObject?
var additionalData: [AnyHashable: Any]?
public var radioModel: RadioButtonModel? { public var radioModel: RadioButtonModel? {
return model as? RadioButtonModel return model as? RadioButtonModel
@ -100,7 +101,9 @@ import UIKit
isSelected = !isSelected isSelected = !isSelected
} }
if let actionModel = radioModel?.action, isSelected { if let actionModel = radioModel?.action, isSelected {
Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: nil) var additionalData = self.additionalData ?? [:]
additionalData[KeySourceModel] = radioModel
Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData)
} }
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
setNeedsDisplay() setNeedsDisplay()
@ -158,6 +161,7 @@ import UIKit
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { public 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
self.additionalData = additionalData
guard let model = model as? RadioButtonModel else { return } guard let model = model as? RadioButtonModel else { return }

View File

@ -9,7 +9,7 @@
import UIKit import UIKit
open class RadioSwatch: Control { open class RadioSwatch: Control, MFButtonProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -20,6 +20,9 @@ open class RadioSwatch: Control {
private var strikeLayer: CALayer? private var strikeLayer: CALayer?
private var maskLayer: CALayer? private var maskLayer: CALayer?
private var delegateObject: MVMCoreUIDelegateObject?
var additionalData: [AnyHashable: Any]?
public var radioSwatchModel: RadioSwatchModel? { public var radioSwatchModel: RadioSwatchModel? {
return model as? RadioSwatchModel return model as? RadioSwatchModel
} }
@ -57,6 +60,8 @@ open class RadioSwatch: Control {
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) super.set(with: model, delegateObject, additionalData)
guard let model = model as? RadioSwatchModel else { return } guard let model = model as? RadioSwatchModel else { return }
self.delegateObject = delegateObject
self.additionalData = additionalData
bottomText.text = model.text bottomText.text = model.text
isSelected = model.selected isSelected = model.selected
isEnabled = model.enabled isEnabled = model.enabled
@ -117,6 +122,11 @@ open class RadioSwatch: Control {
guard isEnabled else { return } guard isEnabled else { return }
isSelected = true isSelected = true
radioSwatchModel?.selected = isSelected radioSwatchModel?.selected = isSelected
if let actionModel = radioSwatchModel?.action {
var additionalData = self.additionalData ?? [:]
additionalData[KeySourceModel] = radioSwatchModel
Button.performButtonAction(with: actionModel, button: self, delegateObject: delegateObject, additionalData: additionalData)
}
layer.setNeedsDisplay() layer.setNeedsDisplay()
} }

View File

@ -17,6 +17,7 @@ import Foundation
public var enabled: Bool = true public var enabled: Bool = true
public var strikethrough: Bool = false public var strikethrough: Bool = false
public var fieldValue: String? public var fieldValue: String?
public var action: ActionModelProtocol?
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case moleculeName case moleculeName
@ -27,6 +28,7 @@ import Foundation
case enabled case enabled
case strikethrough case strikethrough
case fieldValue case fieldValue
case action
} }
required public init(from decoder: Decoder) throws { required public init(from decoder: Decoder) throws {
@ -46,6 +48,7 @@ import Foundation
self.strikethrough = strikethrough self.strikethrough = strikethrough
} }
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -58,6 +61,7 @@ import Foundation
try container.encode(enabled, forKey: .enabled) try container.encode(enabled, forKey: .enabled)
try container.encode(strikethrough, forKey: .strikethrough) try container.encode(strikethrough, forKey: .strikethrough)
try container.encodeIfPresent(fieldValue, forKey: .fieldValue) try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
try container.encodeModelIfPresent(action, forKey: .action)
} }
} }

View File

@ -395,17 +395,19 @@ public typealias ActionBlockConfirmation = () -> (Bool)
let actionMap = model.action?.toJSON() let actionMap = model.action?.toJSON()
let alternateActionMap = model.alternateAction?.toJSON() let alternateActionMap = model.alternateAction?.toJSON()
if actionMap != nil || alternateActionMap != nil { if actionMap != nil || alternateActionMap != nil {
var additionalDatatoUpdate = additionalData ?? [:]
additionalDatatoUpdate[KeySourceModel] = model
didToggleAction = { [weak self] in didToggleAction = { [weak self] in
guard let self = self else { return } guard let self = self else { return }
if self.isOn { if self.isOn {
if actionMap != nil { if actionMap != nil {
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalDatatoUpdate, delegateObject: delegateObject)
} }
} else { } else {
if alternateActionMap != nil { if alternateActionMap != nil {
MVMCoreActionHandler.shared()?.handleAction(with: alternateActionMap, additionalData: additionalData, delegateObject: delegateObject) MVMCoreActionHandler.shared()?.handleAction(with: alternateActionMap, additionalData: additionalDatatoUpdate, delegateObject: delegateObject)
} else if actionMap != nil { } else if actionMap != nil {
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalDatatoUpdate, delegateObject: delegateObject)
} }
} }
} }

View File

@ -42,6 +42,7 @@ extern NSString * const KeyIsOpaque;
extern NSString * const KeyFieldKey; extern NSString * const KeyFieldKey;
extern NSString * const KeyRequired; extern NSString * const KeyRequired;
extern NSString * const KeySourceModel;
#pragma mark - Values #pragma mark - Values

View File

@ -40,6 +40,7 @@ NSString * const KeyTextColor = @"textColor";
NSString * const KeyIsHidden = @"isHidden"; NSString * const KeyIsHidden = @"isHidden";
NSString * const KeyIsOpaque = @"isOpaque"; NSString * const KeyIsOpaque = @"isOpaque";
NSString * const KeySourceModel = @"sourceModel";
#pragma mark - Values #pragma mark - Values