diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 5d073043..3e539a83 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -62,6 +62,7 @@ 01F2A03223A4498200D954D8 /* CaretButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01F2A03123A4498200D954D8 /* CaretButtonModel.swift */; }; 0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */; }; 0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */; }; + 0A209CD323A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A209CD223A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift */; }; 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; 0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; }; 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; }; @@ -313,6 +314,7 @@ 01EB368D23609801006832FA /* HeadlineBodyModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeadlineBodyModel.swift; sourceTree = ""; }; 01F2A03123A4498200D954D8 /* CaretButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaretButtonModel.swift; sourceTree = ""; }; 0A12149F22C11A17007C7030 /* ActionDetailWithImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionDetailWithImage.swift; sourceTree = ""; }; + 0A209CD223A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackViewAlignment+Extension.swift"; sourceTree = ""; }; 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = ""; }; 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; @@ -920,6 +922,7 @@ D29DF2A721E7B2F9003B2FB9 /* MVMCoreUIConstants.h */, D29DF2A821E7B2F9003B2FB9 /* MVMCoreUIConstants.m */, 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */, + 0A209CD223A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift */, ); path = Utility; sourceTree = ""; @@ -1304,6 +1307,7 @@ D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */, D224799B231965AD003FCCF9 /* AccordionMoleculeTableViewCell.swift in Sources */, D22D1F1F220343560077CEC0 /* MVMCoreUICheckMarkView.m in Sources */, + 0A209CD323A7E2810068F8B0 /* UIStackViewAlignment+Extension.swift in Sources */, 01004F3022721C3800991ECC /* RadioButton.swift in Sources */, D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */, 017BEB3C2361EA1D0024EF95 /* MFViewController+Model.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/CaretButtonModel.swift b/MVMCoreUI/Atoms/Buttons/CaretButtonModel.swift index c3946788..cf21a19b 100644 --- a/MVMCoreUI/Atoms/Buttons/CaretButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/CaretButtonModel.swift @@ -39,14 +39,14 @@ public class CaretButtonModel: MoleculeProtocol { enabledColor = try typeContainer.decodeIfPresent(String.self, forKey: .enabledColor) disabledColor = try typeContainer.decodeIfPresent(String.self, forKey: .disabledColor) enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) - action = try typeContainer.decode(codingKey: .action, typeCodingKey: ActionCodingKey.type) + action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.type) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(label, forKey: .label) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - try container.encodeIfPresent(action, forKey: .action) + try container.encodeModel(action, forKey: .action) try container.encodeIfPresent(enabledColor, forKey: .enabledColor) try container.encodeIfPresent(disabledColor, forKey: .disabledColor) try container.encodeIfPresent(enabled, forKey: .enabled) diff --git a/MVMCoreUI/Atoms/Views/LabelModel/LabelModel.swift b/MVMCoreUI/Atoms/Views/LabelModel/LabelModel.swift index d2c7947f..2b87186f 100644 --- a/MVMCoreUI/Atoms/Views/LabelModel/LabelModel.swift +++ b/MVMCoreUI/Atoms/Views/LabelModel/LabelModel.swift @@ -57,7 +57,7 @@ import Foundation self.fontName = try typeContainer.decodeIfPresent(String.self, forKey: .fontName) self.fontSize = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .fontSize) self.textAlignment = try typeContainer.decodeIfPresent(String.self, forKey: .textAlignment) - self.attributes = try typeContainer.decodeArrayIfPresent(codingKey: .attributes, typeCodingKey: AttributeTypeKey.type) as? [LabelAttributeModel] + self.attributes = try typeContainer.decodeModelsIfPresent(codingKey: .attributes, typeCodingKey: AttributeTypeKey.type) as? [LabelAttributeModel] self.html = try typeContainer.decodeIfPresent(String.self, forKey: .html) self.hero = try typeContainer.decodeIfPresent(Int.self, forKey: .hero) self.makeWholeViewClickable = try typeContainer.decodeIfPresent(Bool.self, forKey: .makeWholeViewClickable) diff --git a/MVMCoreUI/Models/Extensions/ModelHelper.swift b/MVMCoreUI/Models/Extensions/ModelHelper.swift index b4d0b1e2..66ed89ab 100644 --- a/MVMCoreUI/Models/Extensions/ModelHelper.swift +++ b/MVMCoreUI/Models/Extensions/ModelHelper.swift @@ -13,22 +13,22 @@ extension KeyedDecodingContainer where Key : CodingKey { case moleculeName } - public func decode(codingKey: KeyedDecodingContainer.Key) throws -> MoleculeProtocol { - return try decode(codingKey: codingKey, typeCodingKey: TypeCodingKey.moleculeName) + public func decodeMolecule(codingKey: KeyedDecodingContainer.Key) throws -> MoleculeProtocol { + return try decodeModel(codingKey: codingKey, typeCodingKey: TypeCodingKey.moleculeName) } - public func decodeIfPresent(codingKey: KeyedDecodingContainer.Key) throws -> MoleculeProtocol? { - return try decodeIfPresent(codingKey: codingKey, typeCodingKey: TypeCodingKey.moleculeName) + public func decodeMoleculeIfPresent(codingKey: KeyedDecodingContainer.Key) throws -> MoleculeProtocol? { + return try decodeModelIfPresent(codingKey: codingKey, typeCodingKey: TypeCodingKey.moleculeName) } - public func decodeArray(codingKey: KeyedDecodingContainer.Key) throws -> [MoleculeProtocol] { - guard let models = try decodeArray(codingKey: codingKey, typeCodingKey: TypeCodingKey.moleculeName) as? [MoleculeProtocol] else { + public func decodeMolecules(codingKey: KeyedDecodingContainer.Key) throws -> [MoleculeProtocol] { + guard let models = try decodeModels(codingKey: codingKey, typeCodingKey: TypeCodingKey.moleculeName) as? [MoleculeProtocol] else { throw ModelRegistry.Error.decoderError } return models } public func decodeArrayIfPresent(codingKey: KeyedDecodingContainer.Key) throws -> [MoleculeProtocol]? { - return try decodeArrayIfPresent(codingKey: codingKey, typeCodingKey: TypeCodingKey.moleculeName) as? [MoleculeProtocol] + return try decodeModelsIfPresent(codingKey: codingKey, typeCodingKey: TypeCodingKey.moleculeName) as? [MoleculeProtocol] } } diff --git a/MVMCoreUI/Models/Molecules/CarouselItemModel.swift b/MVMCoreUI/Models/Molecules/CarouselItemModel.swift index eb9df665..bb45f29c 100644 --- a/MVMCoreUI/Models/Molecules/CarouselItemModel.swift +++ b/MVMCoreUI/Models/Molecules/CarouselItemModel.swift @@ -25,14 +25,14 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - molecule = try typeContainer.decode(codingKey: .molecule) + molecule = try typeContainer.decodeMolecule(codingKey: .molecule) + //(codingKey: .molecule) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(backgroundColor, forKey: .backgroundColor) - try container.encode(molecule, forKey: .molecule) - try container.encodeIfPresent(self.molecule, forKey: .molecule) + try container.encodeModel(molecule, forKey: .molecule) } } diff --git a/MVMCoreUI/Models/Molecules/CarouselModel.swift b/MVMCoreUI/Models/Molecules/CarouselModel.swift index 60f2b27c..e735d516 100644 --- a/MVMCoreUI/Models/Molecules/CarouselModel.swift +++ b/MVMCoreUI/Models/Molecules/CarouselModel.swift @@ -54,7 +54,7 @@ import UIKit self.height = try typeContainer.decode(Float.self, forKey: .height) self.itemWidthPercent = try typeContainer.decode(Float.self, forKey: .itemWidthPercent) self.itemAlignment = try typeContainer.decode(String.self, forKey: .itemAlignment) - self.pagingMolecule = try typeContainer.decodeIfPresent(codingKey: .pagingMolecule) as? PagingMoleculeProtocol + self.pagingMolecule = try typeContainer.decodeMoleculeIfPresent(codingKey: .pagingMolecule) as? PagingMoleculeProtocol } public func encode(to encoder: Encoder) throws { @@ -67,6 +67,6 @@ import UIKit try container.encode(height, forKey: .height) try container.encode(itemWidthPercent, forKey: .itemWidthPercent) try container.encode(itemAlignment, forKey: .itemAlignment) - try container.encodeIfPresent(self.pagingMolecule, forKey: .pagingMolecule) + try container.encodeModelIfPresent(pagingMolecule, forKey: .pagingMolecule) } } diff --git a/MVMCoreUI/Models/Molecules/DropDownListItemModel.swift b/MVMCoreUI/Models/Molecules/DropDownListItemModel.swift index 70a9c662..13ed71e2 100644 --- a/MVMCoreUI/Models/Molecules/DropDownListItemModel.swift +++ b/MVMCoreUI/Models/Molecules/DropDownListItemModel.swift @@ -33,7 +33,7 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - molecule = try typeContainer.decode(codingKey: .molecule) + molecule = try typeContainer.decodeMolecule(codingKey: .molecule) self.molecules = try typeContainer.decode([[ListItemModel]].self, forKey: .molecules) self.separator = try typeContainer.decode(LineModel.self, forKey: .separator) self.backgroundColor = try typeContainer.decodeIfPresent(String.self, forKey: .backgroundColor) @@ -42,7 +42,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(molecule, forKey: .molecule) + try container.encodeModel(molecule, forKey: .molecule) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(molecules, forKey: .molecules) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Models/Molecules/FooterModel.swift b/MVMCoreUI/Models/Molecules/FooterModel.swift index 33751aa0..fe8f688e 100644 --- a/MVMCoreUI/Models/Molecules/FooterModel.swift +++ b/MVMCoreUI/Models/Molecules/FooterModel.swift @@ -30,14 +30,13 @@ import Foundation let typeContainer = try decoder.container(keyedBy: CodingKeys.self) self.moleculeName = try typeContainer.decode(String.self, forKey: .moleculeName) self.backgroundColor = try typeContainer.decodeIfPresent(String.self, forKey: .backgroundColor) - self.molecule = try typeContainer.decode(codingKey: .molecule) + self.molecule = try typeContainer.decodeMolecule(codingKey: .molecule) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encodeIfPresent(self.molecule, forKey: .molecule) try container.encodeIfPresent(self.backgroundColor, forKey: .backgroundColor) - try container.encode(molecule, forKey: .molecule) + try container.encodeModel(self.molecule, forKey: .moleculeName) } } diff --git a/MVMCoreUI/Models/Molecules/HeaderModel.swift b/MVMCoreUI/Models/Molecules/HeaderModel.swift index 5212de7c..63ff20fa 100644 --- a/MVMCoreUI/Models/Molecules/HeaderModel.swift +++ b/MVMCoreUI/Models/Molecules/HeaderModel.swift @@ -30,16 +30,15 @@ import Foundation let typeContainer = try decoder.container(keyedBy: CodingKeys.self) self.moleculeName = try typeContainer.decode(String.self, forKey: .moleculeName) self.backgroundColor = try typeContainer.decodeIfPresent(String.self, forKey: .backgroundColor) - self.molecule = try typeContainer.decode(codingKey: .molecule) + self.molecule = try typeContainer.decodeMolecule(codingKey: .molecule) self.seperator = try typeContainer.decodeIfPresent(LineModel.self, forKey: .separator) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encodeIfPresent(self.molecule, forKey: .molecule) + try container.encodeModelIfPresent(molecule, forKey: .molecule) try container.encodeIfPresent(self.backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(self.seperator, forKey: .separator) - try container.encode(molecule, forKey: .molecule) } } diff --git a/MVMCoreUI/Models/Molecules/ListItemModel.swift b/MVMCoreUI/Models/Molecules/ListItemModel.swift new file mode 100644 index 00000000..70dcf379 --- /dev/null +++ b/MVMCoreUI/Models/Molecules/ListItemModel.swift @@ -0,0 +1,40 @@ +// +// ListItem.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 10/3/19. +// Copyright © 2019 Suresh, Kamlesh. All rights reserved. +// + +import Foundation + +@objcMembers public class ListItemModel: MoleculeProtocol { + public static var identifier: String = "listItem" + public var molecule: MoleculeProtocol? + public var backgroundColor: String? + public var action: ActionModel? + + public init(molecule: MoleculeProtocol?, actionMap: ActionModel?) { + self.molecule = molecule + self.action = actionMap + } + + enum CodingKeys: String, CodingKey { + case moleculeName + case molecule + case action + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + self.molecule = try typeContainer.decodeMoleculeIfPresent(codingKey: .molecule) + self.action = try typeContainer.decodeIfPresent(ActionModel.self, forKey: .action) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(moleculeName, forKey: .moleculeName) + try container.encodeModelIfPresent(self.molecule, forKey: .molecule) + try container.encodeIfPresent(action, forKey: .action) + } +} diff --git a/MVMCoreUI/Models/Molecules/MoleculeStackItemModel.swift b/MVMCoreUI/Models/Molecules/MoleculeStackItemModel.swift index 1a7e6f73..f9f92c05 100644 --- a/MVMCoreUI/Models/Molecules/MoleculeStackItemModel.swift +++ b/MVMCoreUI/Models/Molecules/MoleculeStackItemModel.swift @@ -40,7 +40,7 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - self.molecule = try typeContainer.decodeIfPresent(codingKey: .molecule) + self.molecule = try typeContainer.decodeMoleculeIfPresent(codingKey: .molecule) self.spacing = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .spacing) self.percentage = try typeContainer.decodeIfPresent(Int.self, forKey: .percentage) @@ -52,12 +52,6 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encodeIfPresent(self.molecule, forKey: .molecule) - - try container.encode(spacing, forKey: .spacing) - try container.encode(percentage, forKey: .percentage) - try container.encode(verticalAlignment, forKey: .verticalAlignment) - try container.encode(horizontalAlignment, forKey: .horizontalAlignment) - try container.encode(gone, forKey: .gone) + try container.encodeModelIfPresent(self.molecule, forKey: .molecule) } } diff --git a/MVMCoreUI/Models/Template/ListPageTemplateModel.swift b/MVMCoreUI/Models/Template/ListPageTemplateModel.swift index fa8b96a2..7533d722 100644 --- a/MVMCoreUI/Models/Template/ListPageTemplateModel.swift +++ b/MVMCoreUI/Models/Template/ListPageTemplateModel.swift @@ -40,10 +40,11 @@ import Foundation let typeContainer = try decoder.container(keyedBy: CodingKeys.self) self.pageType = try typeContainer.decode(String.self, forKey: .pageType) self.screenHeading = try typeContainer.decode(String.self, forKey: .screenHeading) - guard let list = try typeContainer.decodeArray(codingKey: .molecules) as? [ListItemModelProtocol] else { + + guard let molecules = try typeContainer.decodeMolecules(codingKey: .molecules) as? [ListItemModelProtocol] else { throw JSONError.pathNotFound } - self.molecules = list + self.molecules = molecules self.isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs) self.header = try typeContainer.decodeIfPresent(HeaderModel.self, forKey: .header) self.footer = try typeContainer.decodeIfPresent(MoleculeStackModel.self, forKey: .footer) @@ -54,7 +55,7 @@ import Foundation try container.encode(pageType, forKey: .pageType) try container.encode(screenHeading, forKey: .screenHeading) - try container.encodeArray(molecules, forKey: .molecules) + try container.encodeModelsIfPresent(molecules, forKey: .molecules) try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs) try container.encodeIfPresent(header, forKey: .header) try container.encodeIfPresent(footer, forKey: .footer) diff --git a/MVMCoreUI/Molecules/Items/ListItemModel.swift b/MVMCoreUI/Molecules/Items/ListItemModel.swift index c1fd5203..a24ff967 100644 --- a/MVMCoreUI/Molecules/Items/ListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/ListItemModel.swift @@ -33,8 +33,8 @@ import MVMCore required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - molecule = try typeContainer.decode(codingKey: .molecule) - action = try typeContainer.decodeIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.type) + molecule = try typeContainer.decodeMolecule(codingKey: .molecule) + action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.type) hideArrow = try typeContainer.decodeIfPresent(Bool.self, forKey: .hideArrow) separator = try typeContainer.decodeIfPresent(LineModel.self, forKey: .separator) style = try typeContainer.decodeIfPresent(String.self, forKey: .style) @@ -43,8 +43,8 @@ import MVMCore public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encode(molecule, forKey: .molecule) - try container.encodeIfPresent(action, forKey: .action) + try container.encodeModel(molecule, forKey: .molecule) + try container.encodeModelIfPresent(action, forKey: .action) try container.encodeIfPresent(hideArrow, forKey: .hideArrow) try container.encodeIfPresent(separator, forKey: .separator) try container.encodeIfPresent(style, forKey: .style) diff --git a/MVMCoreUI/Utility/UIStackViewAlignment+Extension.swift b/MVMCoreUI/Utility/UIStackViewAlignment+Extension.swift new file mode 100644 index 00000000..18afca83 --- /dev/null +++ b/MVMCoreUI/Utility/UIStackViewAlignment+Extension.swift @@ -0,0 +1,72 @@ +// +// UIStackViewAlignment+Extension.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 12/16/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import Foundation + +/** + When using this class in codable for a String value from server. + + Example use case.... + + var alignment: UIStackView.Alignment + + enum CodingKeys: String, CodingKey { + case alignment + } + + required public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let word = try container.decode(String.self, forKey: .alignment) + alignment = UIStackView.Alignment(rawValue: word)! + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(alignment.rawValueString, forKey: .alignment) + } + */ +extension UIStackView.Alignment: RawRepresentable { + + init?(rawValue: String) { + switch rawValue { + case "fill": + self = .fill + case "leading": + self = .leading + case "firstBaseline": + self = .firstBaseline + case "center": + self = .center + case "trailing": + self = .trailing + case "lastBaseline": + self = .lastBaseline + default: + return nil + } + } + + var rawValueString: String { + switch self { + case .fill: + return "fill" + case .leading: + return "leading" + case .firstBaseline: + return "firstBaseline" + case .center: + return "center" + case .trailing: + return "trailing" + case .lastBaseline: + return "lastBaseline" + @unknown default: + return "" + } + } +}