diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 50773104..e1c2c1bb 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -104,6 +104,7 @@ 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */; }; 94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */; }; 94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */; }; + C003506123AA94CD00B6AC29 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = C003506023AA94CD00B6AC29 /* Button.swift */; }; C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */; }; C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A69323C9909000BFB94E /* DoughnutChartModel.swift */; }; C695A69623C990BC00BFB94E /* DoughnutChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = C695A69523C990BC00BFB94E /* DoughnutChart.swift */; }; @@ -151,6 +152,7 @@ D28A838B23CCDA6B00DFE4FC /* ButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */; }; D28A838D23CCDCC200DFE4FC /* PrimaryButton+MoleculeProtocolExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838C23CCDCC200DFE4FC /* PrimaryButton+MoleculeProtocolExtension.swift */; }; D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */; }; + D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D28A839023CD4FD400DFE4FC /* CornerLabelsModel.swift */; }; D296E14722A5984C0051EBE7 /* MVMCoreUIViewConstrainingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; D29770C821F7C4AE00B2F0D0 /* TopLabelsView.m in Sources */ = {isa = PBXBuildFile; fileRef = D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */; }; D29770C921F7C4AE00B2F0D0 /* TopLabelsView.h in Headers */ = {isa = PBXBuildFile; fileRef = D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -374,6 +376,7 @@ 94C2D9A623872DA90006CF46 /* LabelAttributeColorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeColorModel.swift; sourceTree = ""; }; 94C2D9A823872E5E0006CF46 /* LabelAttributeImageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeImageModel.swift; sourceTree = ""; }; 94C2D9AA23872EB50006CF46 /* LabelAttributeActionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelAttributeActionModel.swift; sourceTree = ""; }; + C003506023AA94CD00B6AC29 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; C7192E7C23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadLineBodyCaretLinkImage.swift; sourceTree = ""; }; C695A69323C9909000BFB94E /* DoughnutChartModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoughnutChartModel.swift; sourceTree = ""; }; C695A69523C990BC00BFB94E /* DoughnutChart.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoughnutChart.swift; sourceTree = ""; }; @@ -420,6 +423,7 @@ D28A838A23CCDA6B00DFE4FC /* ButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonModel.swift; sourceTree = ""; }; D28A838C23CCDCC200DFE4FC /* PrimaryButton+MoleculeProtocolExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PrimaryButton+MoleculeProtocolExtension.swift"; sourceTree = ""; }; D28A838E23CCDEDE00DFE4FC /* TwoButtonViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwoButtonViewModel.swift; sourceTree = ""; }; + D28A839023CD4FD400DFE4FC /* CornerLabelsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerLabelsModel.swift; sourceTree = ""; }; D296E14622A597490051EBE7 /* MVMCoreUIViewConstrainingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIViewConstrainingProtocol.h; sourceTree = ""; }; D29770C621F7C4AE00B2F0D0 /* TopLabelsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TopLabelsView.m; sourceTree = ""; }; D29770C721F7C4AE00B2F0D0 /* TopLabelsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopLabelsView.h; sourceTree = ""; }; @@ -785,6 +789,7 @@ D224798F2316A99F003FCCF9 /* LeftRightViews */ = { isa = PBXGroup; children = ( + D28A839023CD4FD400DFE4FC /* CornerLabelsModel.swift */, 01509D902327ECE600EF99AA /* CornerLabels.swift */, D224798823142BF2003FCCF9 /* SwitchMolecules */, ); @@ -1233,6 +1238,7 @@ D2B18B7D236090D500A9AEDC /* BaseClasses */ = { isa = PBXGroup; children = ( + C003506023AA94CD00B6AC29 /* Button.swift */, D2B18B7E2360913400A9AEDC /* Control.swift */, D2B18B802360945C00A9AEDC /* View.swift */, 0AE14F63238315D2005417F8 /* TextField.swift */, @@ -1563,9 +1569,12 @@ 011B58F423A2CCC80085F53C /* DropDownModel.swift in Sources */, D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */, D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */, + D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */, 012A88F123985E0100FE3DA1 /* Color.swift in Sources */, 012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */, D29770FC21F7C77400B2F0D0 /* MVMCoreUITextFieldView.m in Sources */, + C003506123AA94CD00B6AC29 /* Button.swift in Sources */, + D29DF25121E6A177003B2FB9 /* MFDigitTextBox.m in Sources */, DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */, 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */, 0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index 9d9ad9c3..03eb7fc3 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -36,8 +36,8 @@ public class ButtonModel: MoleculeProtocol { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) title = try typeContainer.decode(String.self, forKey: .title) - action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.type) - style = try typeContainer.decode(ButtonStyle.self, forKey: .style) + action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) + style = try typeContainer.decodeIfPresent(ButtonStyle.self, forKey: .style) } public func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Atoms/Buttons/CaretButton.swift b/MVMCoreUI/Atoms/Buttons/CaretButton.swift index 3c7b956c..6c8e4d31 100644 --- a/MVMCoreUI/Atoms/Buttons/CaretButton.swift +++ b/MVMCoreUI/Atoms/Buttons/CaretButton.swift @@ -45,10 +45,8 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI super.layoutSubviews() } - public func setEnabled(_ enabled: Bool) { - super.isEnabled = enabled - - changeCaretColor() + override public var isEnabled: Bool { + didSet { changeCaretColor() } } public func updateView(_ size: CGFloat) { } @@ -85,7 +83,7 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI caretView.widthAnchor.constraint(equalToConstant: width).isActive = true caretView.heightAnchor.constraint(equalToConstant: height).isActive = true - let caretLabelSpacing = NSLayoutConstraint(item: caretView, attribute: .left, relatedBy: .equal, toItem: titleLabel, attribute: .right, multiplier: 1.0, constant: 4.0) + let caretLabelSpacing = NSLayoutConstraint(item: caretView, attribute: .left, relatedBy: .equal, toItem: titleLabel, attribute: .right, multiplier: 1.0, constant: 4) caretLabelSpacing.isActive = true caretSpacingConstraint = caretLabelSpacing @@ -119,6 +117,14 @@ open class CaretButton: MFCustomButton, MVMCoreUIMoleculeViewProtocol, MVMCoreUI guard let dictionary = json else { return } + if let title = dictionary.optionalStringForKey(KeyTitle) { + setTitle(title, for: .normal) + } + + if let disableButtonAsAny = dictionary[KeyDisableButton], let isDisabled = disableButtonAsAny as? Bool { + isEnabled = !isDisabled + } + if let backgroundColorHex = dictionary[KeyBackgroundColor] as? String { backgroundColor = UIColor.mfGet(forHex: backgroundColorHex) } diff --git a/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift b/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift index 3cc77a54..db2de2b0 100644 --- a/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/CaretLinkModel.swift @@ -45,7 +45,7 @@ public class CaretLinkModel: MoleculeProtocol { if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { self.enabled = enabled } - action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.type) + action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) } public func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Atoms/Buttons/LinkModel.swift b/MVMCoreUI/Atoms/Buttons/LinkModel.swift index 6b3ff39e..e2fca66c 100644 --- a/MVMCoreUI/Atoms/Buttons/LinkModel.swift +++ b/MVMCoreUI/Atoms/Buttons/LinkModel.swift @@ -33,7 +33,7 @@ public class LinkModel: MoleculeProtocol { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) title = try typeContainer.decode(String.self, forKey: .title) - action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.type) + action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { self.enabled = enabled } diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index a206953a..50571e30 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -454,7 +454,7 @@ import MVMCore isEnabled(enabled) } - if let actionMap = dictionary.optionalDictionaryForKey("actionMap") { + if let actionMap = dictionary.optionalDictionaryForKey("action") { actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } } } diff --git a/MVMCoreUI/Atoms/Views/DashLine.swift b/MVMCoreUI/Atoms/Views/DashLine.swift index 8bf563d1..de4d6d4a 100644 --- a/MVMCoreUI/Atoms/Views/DashLine.swift +++ b/MVMCoreUI/Atoms/Views/DashLine.swift @@ -19,6 +19,8 @@ open class DashLine: View { get { return model as? DashLineModel } } + // Legacy + @objc public var dashColor: UIColor? @objc private var dashLayer: CAShapeLayer? //------------------------------------------------------ @@ -35,7 +37,6 @@ open class DashLine: View { required public init?(coder: NSCoder) { super.init(coder: coder) - fatalError("DashLine xib not supported") } //------------------------------------------------------ @@ -69,7 +70,7 @@ open class DashLine: View { dashLayer.lineCap = .round dashLayer.lineDashPattern = [NSNumber(value: 2), NSNumber(value: 2)] dashLayer.path = path.cgPath - dashLayer.strokeColor = dashModel?.dashColor.uiColor.cgColor ?? UIColor.mfLighterGray().cgColor + dashLayer.strokeColor = dashModel?.dashColor.uiColor.cgColor ?? dashColor?.cgColor ?? UIColor.mfLighterGray().cgColor dashLayer.fillColor = UIColor.clear.cgColor dashLayer.backgroundColor = backgroundColor?.cgColor ?? UIColor.white.cgColor self.dashLayer = dashLayer diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m index 33874a8d..4b66d519 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m +++ b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch.m @@ -171,7 +171,7 @@ const CGFloat SwitchShakeIntensity = 2; [self setState:[json boolForKey:@"state"] animated:false]; - NSDictionary *actionMap = [json dict:@"actionMap"]; + NSDictionary *actionMap = [json dict:@"action"]; if (actionMap) { [self addTarget:self action:@selector(addCustomAction) forControlEvents:UIControlEventTouchUpInside]; } diff --git a/MVMCoreUI/Atoms/Views/MultiProgress.swift b/MVMCoreUI/Atoms/Views/MultiProgress.swift index e5978c9c..38945134 100644 --- a/MVMCoreUI/Atoms/Views/MultiProgress.swift +++ b/MVMCoreUI/Atoms/Views/MultiProgress.swift @@ -30,7 +30,7 @@ import UIKit let view = UIView(frame: .zero) view.translatesAutoresizingMaskIntoConstraints = false addSubview(view) - view.backgroundColor = progressObject.color.uiColor + view.backgroundColor = progressObject.progressColor.uiColor view.widthAnchor.constraint(equalTo: widthAnchor, multiplier: progressObject.progress).isActive = true view.leadingAnchor.constraint(equalTo: previous?.trailingAnchor ?? leadingAnchor).isActive = true previous = view diff --git a/MVMCoreUI/Atoms/Views/MultiProgressModel.swift b/MVMCoreUI/Atoms/Views/MultiProgressModel.swift index b0251ff6..497fc9d5 100644 --- a/MVMCoreUI/Atoms/Views/MultiProgressModel.swift +++ b/MVMCoreUI/Atoms/Views/MultiProgressModel.swift @@ -10,11 +10,11 @@ import Foundation @objcMembers public class SingleProgressBarModel: Codable { @Percent var progress: CGFloat - var color: Color + var progressColor: Color init(_ progress: CGFloat, color: Color) { self.progress = progress - self.color = color + self.progressColor = color } } diff --git a/MVMCoreUI/BaseClasses/Button.swift b/MVMCoreUI/BaseClasses/Button.swift new file mode 100644 index 00000000..1d5d743e --- /dev/null +++ b/MVMCoreUI/BaseClasses/Button.swift @@ -0,0 +1,133 @@ +// +// Button.swift +// MVMCoreUI +// +// Created by Robinson, Blake on 12/18/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +public typealias ButtonBlock = (Button) -> () + + +@objcMembers open class Button: UIButton, MFButtonProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- + + public var json: [AnyHashable: Any]? + public var actionMap: [AnyHashable: Any]? + + private var initialSetupPerformed = false + + private var buttonBlock: ButtonBlock? + + //-------------------------------------------------- + // MARK: - Delegate + //-------------------------------------------------- + + public weak var buttonDelegate: ButtonDelegateProtocol? + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + + public override init(frame: CGRect) { + super.init(frame: .zero) + initialSetup() + } + + public convenience init() { + self.init(frame: .zero) + initialSetup() + } + + public required init?(coder: NSCoder) { + super.init(coder: coder) + fatalError("Button does not support xib.") + } + + //-------------------------------------------------- + // MARK: - Setup + //-------------------------------------------------- + + public func initialSetup() { + + if !initialSetupPerformed { + initialSetupPerformed = true + setupView() + } + } + + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + + public func addBlock( event: Event, _ buttonBlock: @escaping ButtonBlock) { + self.buttonBlock = buttonBlock + addTarget(self, action: #selector(callBlock(_:)), for: event) + } + + func callBlock(_ sender: Button) { + buttonBlock?(self) + } + + public func setWithActionMap(_ actionMap: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + self.actionMap = actionMap + + buttonDelegate = delegateObject?.buttonDelegate + + addBlock(event: .touchUpInside) { [weak self] sender in + guard let self = self else { return } + + if self.buttonDelegate?.button?(self, shouldPerformActionWithMap: actionMap, additionalData: additionalData) ?? true { + MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) + } + } + } +} + +// MARK: - MVMCoreUIMoleculeViewProtocol +extension Button: MVMCoreUIMoleculeViewProtocol { + + public func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + self.json = json + + guard let dictionary = json else { return } + + if let backgroundColorString = dictionary[KeyBackgroundColor] as? String { + backgroundColor = UIColor.mfGet(forHex: backgroundColorString) + } + + if let title = dictionary[KeyTitle] as? String { + setTitle(title, for: .normal) + } + } + + public func reset() { + backgroundColor = .clear + } +} + + +// MARK: - MVMCoreViewProtocol +extension Button: MVMCoreViewProtocol { + + public func updateView(_ size: CGFloat) {} + + /// Will be called only once. + public func setupView() { + + translatesAutoresizingMaskIntoConstraints = false + insetsLayoutMarginsFromSafeArea = false + titleLabel?.numberOfLines = 0 + titleLabel?.lineBreakMode = .byWordWrapping + } +} + +// MARK: AppleGuidelinesProtocol +extension Button: AppleGuidelinesProtocol { + + override open func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + return Self.acceptablyOutsideBounds(point: point, bounds: bounds) + } +} diff --git a/MVMCoreUI/BaseControllers/MFViewController+Model.swift b/MVMCoreUI/BaseControllers/MFViewController+Model.swift index 88f05360..3468748b 100644 --- a/MVMCoreUI/BaseControllers/MFViewController+Model.swift +++ b/MVMCoreUI/BaseControllers/MFViewController+Model.swift @@ -32,6 +32,6 @@ extension MFViewController: MoleculeDelegateProtocol { } public extension MFViewController { - @objc func parsePageJSON() { + @objc func parsePageJSON() throws { } } diff --git a/MVMCoreUI/BaseControllers/MFViewController.m b/MVMCoreUI/BaseControllers/MFViewController.m index 1d97efd9..d2ff7cda 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.m +++ b/MVMCoreUI/BaseControllers/MFViewController.m @@ -96,7 +96,15 @@ - (BOOL)shouldFinishProcessingLoad:(nonnull MVMCoreLoadObject *)loadObject error:(MVMCoreErrorObject *_Nonnull *_Nonnull)error { self.pageType = loadObject.pageType; self.loadObject = loadObject; - [self parsePageJSON]; + + NSError *parseError = nil; + [self parsePageJSONAndReturnError:&parseError]; + if (parseError) { + if (error) { + *error = [MVMCoreErrorObject createErrorObjectForNSError:parseError location:[[MVMCoreLoadHandler sharedGlobal] errorLocationForRequest:loadObject]]; + } + return false; + } // Verifies all modules needed are loaded. return [MFViewController verifyRequiredModulesLoadedForLoadObject:loadObject error:error]; @@ -250,7 +258,8 @@ - (BOOL)newPageLoaded:(nonnull NSDictionary *)page { self.loadObject.pageJSON = page; - [self parsePageJSON]; + NSError *parseError = nil; + [self parsePageJSONAndReturnError:&parseError]; return YES; } diff --git a/MVMCoreUI/Models/ModelProtocols/TemplateProtocol.swift b/MVMCoreUI/Models/ModelProtocols/TemplateProtocol.swift index eb4463d5..0498ec5d 100644 --- a/MVMCoreUI/Models/ModelProtocols/TemplateProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/TemplateProtocol.swift @@ -14,15 +14,11 @@ public protocol TemplateProtocol: class { } public extension TemplateProtocol where Self: MFViewController { - func parseTemplateJSON() { + func parseTemplateJSON() throws { guard let pageJSON = self.loadObject?.pageJSON else { return } - do { - let data = try JSONSerialization.data(withJSONObject: pageJSON) - let decoder = JSONDecoder() - let templateModel = try decoder.decode(TemplateModel.self, from: data) - self.templateModel = templateModel - } catch { - MVMCoreUILoggingHandler.logDebugMessage(withDelegate: "error: \(error)") - } + let data = try JSONSerialization.data(withJSONObject: pageJSON) + let decoder = JSONDecoder() + let templateModel = try decoder.decode(TemplateModel.self, from: data) + self.templateModel = templateModel } } diff --git a/MVMCoreUI/Models/Template/ListPageTemplateModel.swift b/MVMCoreUI/Models/Template/ListPageTemplateModel.swift index 61729c99..c3b2a120 100644 --- a/MVMCoreUI/Models/Template/ListPageTemplateModel.swift +++ b/MVMCoreUI/Models/Template/ListPageTemplateModel.swift @@ -10,7 +10,7 @@ import Foundation @objcMembers public class ListPageTemplateModel: TemplateModelProtocol { - public static var identifier: String = "listTemplate" + public static var identifier: String = "list" public var pageType: String public var screenHeading: String? diff --git a/MVMCoreUI/Models/Template/StackPageTemplateModel.swift b/MVMCoreUI/Models/Template/StackPageTemplateModel.swift index 9cce36ab..0e5e4488 100644 --- a/MVMCoreUI/Models/Template/StackPageTemplateModel.swift +++ b/MVMCoreUI/Models/Template/StackPageTemplateModel.swift @@ -10,7 +10,7 @@ import Foundation @objcMembers public class StackPageTemplateModel: TemplateModelProtocol { - public static var identifier: String = "moleculeStack" + public static var identifier: String = "stack" public var pageType: String diff --git a/MVMCoreUI/Molecules/Items/ListItemModel.swift b/MVMCoreUI/Molecules/Items/ListItemModel.swift index bef2cb84..7208a2ce 100644 --- a/MVMCoreUI/Molecules/Items/ListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/ListItemModel.swift @@ -28,7 +28,7 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: ListItemCodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.type) + action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) hideArrow = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideArrow) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) style = try typeContainer.decodeIfPresent(String.self, forKey: .style) diff --git a/MVMCoreUI/Molecules/LeftRightViews/CornerLabels.swift b/MVMCoreUI/Molecules/LeftRightViews/CornerLabels.swift index 9b7dc062..bde3ab6f 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/CornerLabels.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/CornerLabels.swift @@ -178,3 +178,21 @@ import UIKit return 34 } } + +extension CornerLabels: MoleculeViewProtocol { + public func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let model = model as? CornerLabelsModel, + let data = try? model.encode(using: JSONEncoder()), + let json = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.init()) as? [AnyHashable: Any] else { + return + } + self.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) +// topLeftLabel.setWithModel(model.topLeftLabel, delegateObject, additionalData) +// topRightLabel.setWithModel(model.topRightLabel, delegateObject, additionalData) +// bottomLeftLabel.setWithModel(model.bottomLeftLabel, delegateObject, additionalData) +// bottomRightLabel.setWithModel(model.bottomRightLabel, delegateObject, additionalData) +// +// topLabelToMoleculeConstraint?.constant = (molecule != nil && (topLeftLabel.hasText || topRightLabel.hasText)) ? spaceAboveMolecule : 0 +// bottomLabelToMoleculeConstraint?.constant = (molecule != nil && (bottomLeftLabel.hasText || bottomRightLabel.hasText)) ? spaceBelowMolecule : 0 + } +} diff --git a/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift b/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift new file mode 100644 index 00000000..c61bd408 --- /dev/null +++ b/MVMCoreUI/Molecules/LeftRightViews/CornerLabelsModel.swift @@ -0,0 +1,52 @@ +// +// CornerLabelsModel.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 1/13/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + +public class CornerLabelsModel: MoleculeProtocol { + public static var identifier: String = "cornerLabels" + public var backgroundColor: Color? + public var topLeftLabel: LabelModel? + public var topRightLabel: LabelModel? + public var bottomLeftLabel: LabelModel? + public var bottomRightLabel: LabelModel? + public var molecule: MoleculeProtocol + + init(with molecule: MoleculeProtocol) { + self.molecule = molecule + } + + enum CodingKeys: String, CodingKey { + case backgroundColor + case topLeftLabel + case topRightLabel + case bottomLeftLabel + case bottomRightLabel + case molecule + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + molecule = try typeContainer.decodeMolecule(codingKey: .molecule) + topLeftLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .topLeftLabel) + topRightLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .topRightLabel) + bottomLeftLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .bottomLeftLabel) + bottomRightLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .bottomRightLabel) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encodeModelIfPresent(molecule, forKey: .molecule) + try container.encodeIfPresent(topLeftLabel, forKey: .topLeftLabel) + try container.encodeIfPresent(topRightLabel, forKey: .topRightLabel) + try container.encodeIfPresent(bottomLeftLabel, forKey: .bottomLeftLabel) + try container.encodeIfPresent(bottomRightLabel, forKey: .bottomRightLabel) + } +} diff --git a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodySwitch.swift b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodySwitch.swift index eca878ab..fee32b2f 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodySwitch.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodySwitch.swift @@ -39,8 +39,6 @@ import UIKit open override func setWithModel(_ model: MoleculeProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) -// guard let headlineModel = model as? headlinebodyswitch -// headlineBody.setWithModel(mode, <#T##delegateObject: MVMCoreUIDelegateObject?##MVMCoreUIDelegateObject?#>, <#T##additionalData: [String : AnyHashable]?##[String : AnyHashable]?#>) } public static func estimatedHeight(forRow molecule: MoleculeProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { @@ -52,7 +50,7 @@ import UIKit open override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) headlineBody.setWithJSON(json?.optionalDictionaryForKey("headlineBody"), delegateObject: delegateObject, additionalData: additionalData) - mvmSwitch.setWithJSON(json?.optionalDictionaryForKey("switch"), delegateObject: delegateObject, additionalData: additionalData) + mvmSwitch.setWithJSON(json?.optionalDictionaryForKey("toggle"), delegateObject: delegateObject, additionalData: additionalData) } open class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { diff --git a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodyTextButtonSwitch.swift b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodyTextButtonSwitch.swift index b0cf6956..5ee9c41f 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodyTextButtonSwitch.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/HeadlineBodyTextButtonSwitch.swift @@ -37,8 +37,8 @@ import UIKit // MARK: - MVMCoreUIMoleculeViewProtocol public override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - headlineBodyTextButton.setWithJSON(json?.optionalDictionaryForKey("headlineBodyTextButton"), delegateObject: delegateObject, additionalData: additionalData) - mvmSwitch.setWithJSON(json?.optionalDictionaryForKey("switch"), delegateObject: delegateObject, additionalData: additionalData) + headlineBodyTextButton.setWithJSON(json?.optionalDictionaryForKey("headlineBodyLink"), delegateObject: delegateObject, additionalData: additionalData) + mvmSwitch.setWithJSON(json?.optionalDictionaryForKey("toggle"), delegateObject: delegateObject, additionalData: additionalData) } public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { diff --git a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelSwitch.swift b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelSwitch.swift index f60202b3..50c19c1d 100644 --- a/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelSwitch.swift +++ b/MVMCoreUI/Molecules/LeftRightViews/SwitchMolecules/LabelSwitch.swift @@ -38,7 +38,7 @@ import UIKit public override func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) label.setWithJSON(json?.optionalDictionaryForKey("label"), delegateObject: delegateObject, additionalData: additionalData) - mvmSwitch.setWithJSON(json?.optionalDictionaryForKey("switch"), delegateObject: delegateObject, additionalData: additionalData) + mvmSwitch.setWithJSON(json?.optionalDictionaryForKey("toggle"), delegateObject: delegateObject, additionalData: additionalData) } public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { diff --git a/MVMCoreUI/Molecules/StandardHeaderView.swift b/MVMCoreUI/Molecules/StandardHeaderView.swift index c13638d8..ad231597 100644 --- a/MVMCoreUI/Molecules/StandardHeaderView.swift +++ b/MVMCoreUI/Molecules/StandardHeaderView.swift @@ -37,7 +37,7 @@ public class StandardHeaderView: MoleculeContainer { // MARK: - MVMCoreUIMoleculeViewProtocol open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - if let separatorJSON = json?.optionalDictionaryForKey("separator") { + if let separatorJSON = json?.optionalDictionaryForKey("line") { line?.setWithJSON(separatorJSON, delegateObject: delegateObject, additionalData: additionalData) } } diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyTextButton.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyTextButton.swift index 7c24cff4..ca696f1a 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyTextButton.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyTextButton.swift @@ -66,7 +66,7 @@ import UIKit open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) headlineBody.setWithJSON(json?.optionalDictionaryForKey("headlineBody"), delegateObject: delegateObject, additionalData: additionalData) - textButton.setWithJSON(json?.optionalDictionaryForKey("textButton"), delegateObject: delegateObject, additionalData: additionalData) + textButton.setWithJSON(json?.optionalDictionaryForKey("link"), delegateObject: delegateObject, additionalData: additionalData) } open override func reset() { diff --git a/MVMCoreUI/Organisms/MoleculeStackModel.swift b/MVMCoreUI/Organisms/MoleculeStackModel.swift index 73c7c0a5..2a149e73 100644 --- a/MVMCoreUI/Organisms/MoleculeStackModel.swift +++ b/MVMCoreUI/Organisms/MoleculeStackModel.swift @@ -9,7 +9,7 @@ import Foundation @objcMembers public class MoleculeStackModel: ContainerModel, MoleculeProtocol { - public static var identifier: String = "moleculeStack" + public static var identifier: String = "stack" public var backgroundColor: Color? public var molecules: [StackItemModel] public var axis: NSLayoutConstraint.Axis = .vertical @@ -29,7 +29,7 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: StackCodingKeys.self) - molecules = try typeContainer.decodeMolecules(codingKey: .molecules) as! [StackItemModel] + molecules = try typeContainer.decode([StackItemModel].self, forKey: .molecules) if let axisString = try typeContainer.decodeIfPresent(String.self, forKey: .axis), let optionalAxis = NSLayoutConstraint.Axis(rawValue: axisString) { axis = optionalAxis } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index f68f20e0..79a09aa9 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -29,9 +29,9 @@ @"label": Label.class, @"line": Line.class, @"button": PrimaryButton.class, - @"textButton": MFTextButton.class, + @"link": MFTextButton.class, @"header": StandardHeaderView.class, - @"moleculeStack": MoleculeStackView.class, + @"stack": MoleculeStackView.class, @"twoButtonView": TwoButtonView.class, @"footer": StandardFooterView.class, @"caretView": CaretView.class, @@ -44,7 +44,7 @@ @"itemDropdownEntryField": ItemDropdownEntryField.class, @"dateDropdownEntryField": DateDropdownEntryField.class, @"checkbox": Checkbox.class, - @"checkboxWithLabel": CheckboxWithLabelView.class, + @"checkboxLabel": CheckboxWithLabelView.class, @"cornerLabels" : CornerLabels.class, @"progressbar": ProgressBar.class, @"circleProgress": GraphView.class, @@ -53,7 +53,7 @@ @"radioButtonLabel": RadioButtonLabel.class, @"listItem": MoleculeTableViewCell.class, @"accordionListItem": AccordionMoleculeTableViewCell.class, - @"switch": MVMCoreUISwitch.class, + @"toggle": MVMCoreUISwitch.class, @"leftRightLabelView": LeftRightLabelView.class, @"actionDetailWithImage": ActionDetailWithImage.class, @"image": MFLoadImageView.class, @@ -64,10 +64,10 @@ @"barsPager": MVMCoreUIPageControl.class, @"scroller": Scroller.class, @"imageHeadlineBody": ImageHeadlineBody.class, - @"labelSwitch": LabelSwitch.class, - @"headlineBodySwitch": HeadlineBodySwitch.class, - @"headlineBodyTextButton": HeadlineBodyTextButton.class, - @"headlineBodyTextButtonSwitch": HeadlineBodyTextButtonSwitch.class, + @"labelToggle": LabelSwitch.class, + @"headlineBodyToggle": HeadlineBodySwitch.class, + @"headlineBodyLink": HeadlineBodyTextButton.class, + @"headlineBodyLinkToggle": HeadlineBodyTextButtonSwitch.class, @"tabsListItem": TabsTableViewCell.class, @"dropDownListItem": DropDownFilterTableViewCell.class, @"headlineBodyButton": HeadlineBodyButton.class, diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m index 2bc1a0dd..7bdccc8e 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIViewControllerMappingObject.m @@ -19,9 +19,9 @@ static NSMutableDictionary *viewControllerMapping; dispatch_once(&onceToken, ^{ viewControllerMapping = [@{ - @"moleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]], + @"stack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackTemplate class]], @"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]], - @"moleculeList" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]], + @"list" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]], @"threeLayer" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]] } mutableCopy]; diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 32df6b99..79e2c46e 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -23,10 +23,12 @@ import Foundation ModelRegistry.register(ImageViewModel.self) ModelRegistry.register(TabsModel.self) ModelRegistry.register(ScrollerModel.self) - // buttons + ModelRegistry.register(CornerLabelsModel.self) ModelRegistry.register(LineModel.self) + // buttons ModelRegistry.register(ButtonModel.self) ModelRegistry.register(TwoButtonViewModel.self) + ModelRegistry.register(LinkModel.self) // list items ModelRegistry.register(ListItemModel.self) ModelRegistry.register(DropDownListItemModel.self) diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 03f4e0fc..3a551a79 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -14,8 +14,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol var observer: NSKeyValueObservation? public var templateModel: ListPageTemplateModel? - public override func parsePageJSON() { - parseTemplateJSON() + @objc public override func parsePageJSON() throws { + try parseTemplateJSON() } open override var loadObject: MVMCoreLoadObject? { diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index 3dc9a58c..74eae770 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -12,8 +12,8 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { var observer: NSKeyValueObservation? public var templateModel: StackPageTemplateModel? - public override func parsePageJSON() { - parseTemplateJSON() + public override func parsePageJSON() throws { + try parseTemplateJSON() } open override var loadObject: MVMCoreLoadObject? { @@ -88,7 +88,7 @@ open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { let delegate = delegateObject() as? MVMCoreUIDelegateObject MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("header"), delegateObject: delegate, moduleList: modules, errorList: nil) MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("footer"), delegateObject: delegate, moduleList: modules, errorList: nil) - MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("moleculeStack"), delegateObject: delegate, moduleList: modules, errorList: nil) + MVMCoreUIMoleculeMappingObject.addRequiredModules(forJSON: loadObject?.pageJSON?.optionalDictionaryForKey("stack"), delegateObject: delegate, moduleList: modules, errorList: nil) return modules as? [Any] } } diff --git a/MVMCoreUI/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Templates/ThreeLayerTemplate.swift index 67326d09..472985e3 100644 --- a/MVMCoreUI/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Templates/ThreeLayerTemplate.swift @@ -11,8 +11,8 @@ import UIKit @objcMembers open class ThreeLayerTemplate: ThreeLayerViewController, TemplateProtocol { public var templateModel: ThreeLayerPageTemplateModel? - public override func parsePageJSON() { - parseTemplateJSON() + @objc public override func parsePageJSON() throws { + try parseTemplateJSON() } override open func viewDidLoad() {