Merge branch 'feature/entry_fields_models' into 'feature/coding'

Entry field models

See merge request BPHV_MIPS/mvm_core_ui!232
This commit is contained in:
Pfeil, Scott Robert 2020-01-24 15:40:21 -05:00
commit 3951669ec6
33 changed files with 711 additions and 168 deletions

View File

@ -15,7 +15,6 @@
0116A4E5228B19640094F3ED /* RadioButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */; };
011B58F023A2AA980085F53C /* ListItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */; };
011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */; };
011B58F423A2CCC80085F53C /* DropDownModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58F323A2CCC80085F53C /* DropDownModel.swift */; };
012A889C23889E8400FE3DA1 /* TemplateModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */; };
012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */; };
012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88B0238C880100FE3DA1 /* CarouselPagingModelProtocol.swift */; };
@ -83,6 +82,13 @@
0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */; };
0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */; };
0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */; };
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */; };
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */; };
0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */; };
0A7EF86123D8AC2500B2AAD1 /* DigitEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86023D8AC2500B2AAD1 /* DigitEntryFieldModel.swift */; };
0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86223D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift */; };
0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */; };
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */; };
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AA33B392398524F0067DD0F /* Toggle.swift */; };
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; };
0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; };
@ -153,7 +159,6 @@
D260D7B622D68514007E7233 /* MVMCoreUIPagingProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01EB368A23609801006832FA /* MoleculeStackItemModel.swift */; };
D268C70E238C22D7007F2C1C /* DropDownFilterTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */; };
D268C712238D6699007F2C1C /* DropDown.swift in Sources */ = {isa = PBXBuildFile; fileRef = D268C711238D6699007F2C1C /* DropDown.swift */; };
D274CA332236A78900B01B62 /* FooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D274CA322236A78900B01B62 /* FooterView.swift */; };
D2755D7B23689C7500485468 /* TableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2755D7A23689C7500485468 /* TableViewCell.swift */; };
D27CD40E2322EEAF00C1DC07 /* TabsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */; };
@ -327,7 +332,6 @@
0116A4E4228B19640094F3ED /* RadioButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonModel.swift; sourceTree = "<group>"; };
011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemModelProtocol.swift; sourceTree = "<group>"; };
011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDownListItemModel.swift; sourceTree = "<group>"; };
011B58F323A2CCC80085F53C /* DropDownModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDownModel.swift; sourceTree = "<group>"; };
012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModelProtocol.swift; sourceTree = "<group>"; };
012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateProtocol.swift; sourceTree = "<group>"; };
012A88AE238C626E00FE3DA1 /* CarouselModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselModel.swift; sourceTree = "<group>"; };
@ -384,6 +388,13 @@
0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = "<group>"; };
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = "<group>"; };
0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = "<group>"; };
0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryFieldModel.swift; sourceTree = "<group>"; };
0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryFieldModel.swift; sourceTree = "<group>"; };
0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnEntryFieldModel.swift; sourceTree = "<group>"; };
0A7EF86023D8AC2500B2AAD1 /* DigitEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitEntryFieldModel.swift; sourceTree = "<group>"; };
0A7EF86223D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDropdownEntryFieldModel.swift; sourceTree = "<group>"; };
0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryFieldModel.swift; sourceTree = "<group>"; };
0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryFieldModel.swift; sourceTree = "<group>"; };
0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = "<group>"; };
0AA33B33239813C50067DD0F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = "<group>"; };
0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = "<group>"; };
@ -454,7 +465,6 @@
D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIPageControl.m; sourceTree = "<group>"; };
D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPagingProtocol.h; sourceTree = "<group>"; };
D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownFilterTableViewCell.swift; sourceTree = "<group>"; };
D268C711238D6699007F2C1C /* DropDown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDown.swift; sourceTree = "<group>"; };
D274CA322236A78900B01B62 /* FooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterView.swift; sourceTree = "<group>"; };
D2755D7A23689C7500485468 /* TableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCell.swift; sourceTree = "<group>"; };
D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsTableViewCell.swift; sourceTree = "<group>"; };
@ -1161,8 +1171,6 @@
D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */,
017BEB7A236763000024EF95 /* LineModel.swift */,
D213347623843825008E41B3 /* Line.swift */,
011B58F323A2CCC80085F53C /* DropDownModel.swift */,
D268C711238D6699007F2C1C /* DropDown.swift */,
DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */,
94C2D9822386F3E30006CF46 /* Label */,
31BE15CA23D8924C00452370 /* CheckboxModel.swift */,
@ -1186,13 +1194,20 @@
children = (
017BEB3F23620A230024EF95 /* TextFieldModel.swift */,
0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */,
0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */,
0A8321AE2355FE9500CB7F00 /* DigitBox.swift */,
0A21DB7E235DECC500C160A2 /* EntryField.swift */,
0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */,
0A21DB82235DFBC500C160A2 /* MdnEntryField.swift */,
0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */,
0A21DB93235E24ED00C160A2 /* DigitEntryField.swift */,
0A7EF86023D8AC2500B2AAD1 /* DigitEntryFieldModel.swift */,
0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */,
0A7EF86223D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift */,
0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */,
0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */,
0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */,
0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */,
012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */,
);
path = TextFields;
@ -1528,6 +1543,7 @@
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */,
D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */,
012A88C8238DB02000FE3DA1 /* ModelMoleculeDelegateProtocol.swift in Sources */,
0A7EF86123D8AC2500B2AAD1 /* DigitEntryFieldModel.swift in Sources */,
DBC4392122491730001AB423 /* LabelWithInternalButton.swift in Sources */,
D224798C231450C8003FCCF9 /* HeadlineBodySwitch.swift in Sources */,
017BEB442362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift in Sources */,
@ -1585,26 +1601,31 @@
D268C70C2386DFFD007F2C1C /* MoleculeStackItemModel.swift in Sources */,
DBEFFA04225A829700230692 /* Label.swift in Sources */,
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */,
0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */,
01509D952327ED1900EF99AA /* HeadlineBodyTextButtonSwitch.swift in Sources */,
31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */,
D260105523CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift in Sources */,
D29DF13021E6851E003B2FB9 /* MVMCoreUITopAlertShortView.m in Sources */,
0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */,
0A7EF85B23D8A52800B2AAD1 /* EntryFieldModel.swift in Sources */,
0A1B4A96233BB18F005B3FB4 /* CheckboxWithLabelView.swift in Sources */,
0A21DB8B235E06EF00C160A2 /* MFDigitTextBox.m in Sources */,
D260D7B222D65BDD007E7233 /* MVMCoreUIPageControl.m in Sources */,
D2B18B812360945C00A9AEDC /* View.swift in Sources */,
C6FA7D5423C77A4A00A3614A /* NumberedList.swift in Sources */,
D29DF26D21E6AA0B003B2FB9 /* FLAnimatedImageView.m in Sources */,
0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */,
94FB966323D797DA003D482B /* MFTextButton.m in Sources */,
D260105323CEA61600764D80 /* ToggleModel.swift in Sources */,
014AA72523C501E2006F3E93 /* ContainerModel.swift in Sources */,
0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */,
D29DF2EF21ECEAE1003B2FB9 /* MFFonts.m in Sources */,
D22479942316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift in Sources */,
D2B18B94236214AD00A9AEDC /* NavigationController.swift in Sources */,
D29E28DA23D21AFA00ACEA85 /* StringAndMoleculeModel.swift in Sources */,
D282AACB2243C61700C46919 /* ButtonView.swift in Sources */,
D260105D23D0BCD400764D80 /* Stack.swift in Sources */,
0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */,
D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */,
01EB368F23609801006832FA /* LabelModel.swift in Sources */,
0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */,
@ -1686,7 +1707,6 @@
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */,
94C2D9A323872C110006CF46 /* LabelAttributeStrikeThroughModel.swift in Sources */,
011B58F423A2CCC80085F53C /* DropDownModel.swift in Sources */,
D28A838523CCCA8900DFE4FC /* ScrollerModel.swift in Sources */,
D29DF26C21E6AA0B003B2FB9 /* FLAnimatedImage.m in Sources */,
D28A839123CD4FD400DFE4FC /* CornerLabelsModel.swift in Sources */,
@ -1697,12 +1717,12 @@
DBC4391B224421A0001AB423 /* CaretButton.swift in Sources */,
0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */,
0A6BF4722360C56C0028F841 /* BaseDropdownEntryField.swift in Sources */,
D268C712238D6699007F2C1C /* DropDown.swift in Sources */,
0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */,
C7192E7D23C301750050C2A0 /* HeadLineBodyCaretLinkImage.swift in Sources */,
D29DF13221E6851E003B2FB9 /* MVMCoreUITopAlertBaseView.m in Sources */,
D29DF29C21E7ADB9003B2FB9 /* MFProgrammaticTableViewController.m in Sources */,
0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */,
0A7EF86323D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift in Sources */,
0A1214A022C11A18007C7030 /* ActionDetailWithImage.swift in Sources */,
D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */,
D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */,

View File

@ -20,6 +20,7 @@ public enum ButtonSize: String, Codable {
public class ButtonModel: MoleculeModelProtocol {
public static var identifier: String = "button"
public var moleculeName: String?
public var backgroundColor: Color?
public var title: String
public var action: ActionModelProtocol
@ -34,6 +35,7 @@ public class ButtonModel: MoleculeModelProtocol {
}
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case title
case action
@ -45,6 +47,8 @@ public class ButtonModel: MoleculeModelProtocol {
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
title = try typeContainer.decode(String.self, forKey: .title)
action = try typeContainer.decodeModel(codingKey: .action, typeCodingKey: ActionCodingKey.actionType)
@ -60,6 +64,7 @@ public class ButtonModel: MoleculeModelProtocol {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(title, forKey: .title)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeModel(action, forKey: .action)

View File

@ -68,6 +68,14 @@ import UIKit
container.trailingAnchor.constraint(equalTo: dropDownCaretView.trailingAnchor, constant: 16).isActive = true
dropDownCaretView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
}
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? BaseDropdownEntryFieldModel else { return }
dropDownCaretView.setWithModel(model.caretView, delegateObject, additionalData)
}
}
// MARK: - MVMCoreUIMoleculeViewProtocol

View File

@ -0,0 +1,45 @@
//
// BaseDropdownEntryFieldModel.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 1/22/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
@objcMembers public class BaseDropdownEntryFieldModel: TextEntryFieldModel {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var caretView: CaretViewModel?
public override class var identifier: String {
return ""
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case caretView
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
caretView = try typeContainer.decodeIfPresent(CaretViewModel.self, forKey: .caretView)
}
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)
try container.encode(caretView, forKey: .caretView)
}
}

View File

@ -22,7 +22,20 @@ import UIKit
return calendar
}()
public var dateFormat: String?
public var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeZone = NSTimeZone.system
formatter.locale = .current
formatter.formatterBehavior = .default
return formatter
}()
public var dateFormat: String = "MMM d, y" {
didSet {
dateFormatter.dateFormat = dateFormat
}
}
//--------------------------------------------------
// MARK: - Initializers
@ -83,7 +96,7 @@ import UIKit
if calendar.isDate(date, inSameDayAs: Date()) {
text = MVMCoreUIUtility.hardcodedString(withKey: "textfield_today_string")
} else {
text = dateFormatter().string(from: date)
text = dateFormatter.string(from: date)
}
}
@ -98,19 +111,12 @@ import UIKit
setTextWith(date: datePicker?.date)
}
public func dateFormatter() -> DateFormatter {
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.setWithModel(model, delegateObject, additionalData)
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeZone = NSTimeZone.system
formatter.locale = .current
formatter.formatterBehavior = .default
guard let model = model as? DateDropdownEntryFieldModel else { return }
if let dateFormat = dateFormat {
formatter.dateFormat = dateFormat
}
return formatter
dateFormat = model.dateFormat
}
}

View File

@ -0,0 +1,45 @@
//
// DateDropdownEntryFieldModel.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 1/22/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
@objcMembers public class DateDropdownEntryFieldModel: BaseDropdownEntryFieldModel {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public override class var identifier: String {
return "dateDropdownEntryField"
}
public var dateFormat: String = "MMM d, y"
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case dateFormat
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
dateFormat = try typeContainer.decodeIfPresent(String.self, forKey: .dateFormat) ?? "MMM d, y"
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(dateFormat, forKey: .dateFormat)
}
}

View File

@ -327,6 +327,22 @@ import UIKit
}
}
}
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
guard let model = model as? DigitEntryFieldModel else { return }
numberOfDigits = model.digits
setAsSecureTextEntry(model.secureEntry)
for digitBox in digitBoxes {
MVMCoreUICommonViewsUtility.addDismissToolbar(digitBox.digitField, delegate: delegateObject as? UITextFieldDelegate)
}
super.setWithModel(model, delegateObject, additionalData)
}
}
// MARK: - TextField Delegate

View File

@ -0,0 +1,50 @@
//
// DigitEntryFieldModel.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 1/22/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
@objcMembers public class DigitEntryFieldModel: TextEntryFieldModel {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public override class var identifier: String {
return "digitTextField"
}
public var digits: Int = 4
public var secureEntry: Bool = false
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case digits
case secureEntry
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
digits = try typeContainer.decodeIfPresent(Int.self, forKey: .digits) ?? 4
secureEntry = try typeContainer.decodeIfPresent(Bool.self, forKey: .secureEntry) ?? false
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(digits, forKey: .digits)
try container.encode(secureEntry, forKey: .secureEntry)
}
}

View File

@ -119,6 +119,7 @@ import UIKit
feedbackLabel.text = newFeedback
feedbackLabel.accessibilityElementsHidden = feedbackLabel.text?.isEmpty ?? true
entryFieldContainer.refreshUI()
delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self)
}
}
@ -238,6 +239,31 @@ import UIKit
feedbackLabel.textColor = .black
entryFieldContainer.reset()
}
open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.setWithModel(model, delegateObject, additionalData)
self.delegateObject = delegateObject
guard let model = model as? EntryFieldModel else { return }
entryFieldContainer.setWithModel(model, delegateObject, additionalData)
title = model.title
feedback = model.feedback
errorMessage = model.errorMessage
isEnabled = model.isEnabled
if let isLocked = model.isLocked {
self.isLocked = isLocked
} else if let isSelected = model.isSelected{
self.isSelected = isSelected
}
if let fieldKey = model.fieldKey {
self.fieldKey = fieldKey
}
}
}
// MARK: - MVMCoreUIMoleculeViewProtocol

View File

@ -0,0 +1,82 @@
//
// EntryFieldModel.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 1/22/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class EntryFieldModel: MoleculeModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public class var identifier: String {
return ""
}
public var backgroundColor: Color?
public var moleculeName: String?
public var title: String?
public var feedback: String?
public var errorMessage: String = ""
public var isEnabled: Bool = true
public var isLocked: Bool?
public var isSelected: Bool?
public var fieldKey: String?
public var isValid: Bool?
public var isRequired: Bool?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case title
case isEnabled
case feedback
case errorMessage = "errorMsg"
case isLocked
case isSelected
case fieldKey
case isValid
case isRequired = "required"
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
title = try typeContainer.decodeIfPresent(String.self, forKey: .title)
feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback)
errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) ?? ""
isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true
isLocked = try typeContainer.decodeIfPresent(Bool.self, forKey: .isLocked)
isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected)
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
isValid = try typeContainer.decodeIfPresent(Bool.self, forKey: .isValid)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(title, forKey: .title)
try container.encodeIfPresent(feedback, forKey: .feedback)
try container.encode(errorMessage, forKey: .errorMessage)
try container.encode(isEnabled, forKey: .isEnabled)
try container.encode(isLocked, forKey: .isLocked)
try container.encode(isSelected, forKey: .isSelected)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(isValid, forKey: .isValid)
}
}

View File

@ -21,7 +21,7 @@ open class ItemDropdownEntryField: BaseDropdownEntryField {
public var setInitialValueInTextField = true
/// Closure passed here will run as picker changes items.
public var observeDropdownChange: ((String)->())?
public var observeDropdownChange: ((String, String)->())?
/// Closure passed here will run upon dismissing the selection picker.
public var observeDropdownSelection: ((String)->())?
@ -90,6 +90,19 @@ open class ItemDropdownEntryField: BaseDropdownEntryField {
observeDropdownSelection?(pickerData[pickerIndex])
}
}
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? ItemDropdownEntryFieldModel else { return }
pickerData = model.options
setPickerDelegates(delegate: self)
if let pickerView = pickerView {
self.pickerView(pickerView, didSelectRow: 0, inComponent: 0)
}
}
}
// MARK:- Base Picker Delegate
@ -104,12 +117,16 @@ extension ItemDropdownEntryField: UIPickerViewDelegate, UIPickerViewDataSource {
}
@objc public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
guard !pickerData.isEmpty else { return nil }
return pickerData[row]
}
@objc public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
guard !pickerData.isEmpty else { return }
observeDropdownChange?(text ?? "", pickerData[row])
text = pickerData[row]
observeDropdownChange?(pickerData[row])
}
}

View File

@ -0,0 +1,45 @@
//
// ItemDropdownEntryFieldModel.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 1/22/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
@objcMembers public class ItemDropdownEntryFieldModel: BaseDropdownEntryFieldModel {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public override class var identifier: String {
return "dropDown"
}
public var options: [String] = []
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case options
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
options = try typeContainer.decode([String].self, forKey: .options)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(options, forKey: .options)
}
}

View File

@ -0,0 +1,17 @@
//
// MdnEntryFieldModel.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 1/22/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
@objcMembers public class MdnEntryFieldModel: TextEntryFieldModel {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public override class var identifier: String {
return "mdnEntryField"
}
}

View File

@ -270,6 +270,49 @@ import UIKit
resignFirstResponder()
}
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
super.setWithModel(model, delegateObject, additionalData)
guard let model = model as? TextEntryFieldModel else { return }
FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol)
textColor.enabled = model.enabledTextColor?.uiColor
textColor.disabled = model.disabledTextColor?.uiColor
text = model.text
placeholder = model.placeholder
switch model.type {
case "password":
textField.isSecureTextEntry = true
case "number":
textField.keyboardType = .numberPad
case "email":
textField.keyboardType = .emailAddress
default:
break
}
if let regex = model.regex, !regex.isEmpty {
validationBlock = { enteredValue in
guard let value = enteredValue else { return false }
return MVMCoreUIUtility.validate(value, withRegularExpression: regex)
}
} else {
defaultValidationBlock()
}
if let formValidationProtocol = delegateObject?.formValidationProtocol {
observingTextFieldDelegate = FormValidator.getFormValidatorFor(delegate: formValidationProtocol)
}
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate)
}
}
// MARK: - MVMCoreUIMoleculeViewProtocol

View File

@ -0,0 +1,66 @@
//
// TextEntryFieldModel.swift
// MVMCoreUI
//
// Created by Kevin Christiano on 1/22/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
@objcMembers public class TextEntryFieldModel: EntryFieldModel {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public override class var identifier: String {
return "textField"
}
public var text: String?
public var placeholder: String?
public var enabledTextColor: Color?
public var disabledTextColor: Color?
public var type: String?
public var regex: String?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case text
case placeholder
case enabledTextColor
case disabledTextColor
case type
case regex
}
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
try super.init(from: decoder)
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
text = try typeContainer.decodeIfPresent(String.self, forKey: .text)
placeholder = try typeContainer.decodeIfPresent(String.self, forKey: .placeholder)
enabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .enabledTextColor)
disabledTextColor = try typeContainer.decodeIfPresent(Color.self, forKey: .disabledTextColor)
type = try typeContainer.decodeIfPresent(String.self, forKey: .type)
regex = try typeContainer.decodeIfPresent(String.self, forKey: .regex)
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(text, forKey: .text)
try container.encodeIfPresent(placeholder, forKey: .placeholder)
try container.encodeIfPresent(enabledTextColor, forKey: .enabledTextColor)
try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor)
try container.encodeIfPresent(type, forKey: .type)
try container.encodeIfPresent(regex, forKey: .regex)
}
}

View File

@ -1,55 +0,0 @@
//
// DropDown.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 11/26/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import UIKit
@objcMembers public class DropDown: MFTextField {
let picker = MVMCoreUICommonViewsUtility.commonPickerView()!
public override func getNib() -> UINib? {
return UINib(nibName: String(describing: MFTextField.self), bundle: MVMCoreUIUtility.bundleForMVMCoreUI())
}
public override func setupView() {
super.setupView()
dropDownCarrotWidth?.isActive = false
errorHeightConstraint?.constant = 0
}
override public func setWithJSON(_ json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable : Any]?) {
super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData)
guard let textField = textField, textField.inputView == nil else { return }
picker.delegate = self
picker.dataSource = self
picker.tag = textField.tag
textField.inputView = picker
picker.reloadAllComponents()
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: delegateObject?.uiTextFieldDelegate)
textField.text = json?.stringWithChainOfKeysOrIndexes(["options",picker.selectedRow(inComponent: 0)])
}
}
extension DropDown: UIPickerViewDelegate {
public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return json?.stringWithChainOfKeysOrIndexes(["options",row])
}
public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
textField?.text = json?.stringWithChainOfKeysOrIndexes(["options",row])
}
}
extension DropDown: UIPickerViewDataSource {
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return json?.optionalArrayForKey("options")?.count ?? 0
}
}

View File

@ -1,22 +0,0 @@
//
// DropDownModel.swift
// MVMCoreUI
//
// Created by Suresh, Kamlesh on 12/12/19.
// Copyright © 2019 Verizon Wireless. All rights reserved.
//
import Foundation
@objcMembers public class DropDownModel: MoleculeModelProtocol {
public static var identifier: String = "dropDownModel"
public var backgroundColor: Color?
public var label: String
public var options: [String]
public init(label: String, options: [String]) {
self.label = label
self.options = options
}
}

View File

@ -66,7 +66,7 @@ import Foundation
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
try container.encode(text, forKey: .moleculeName)
try container.encode(text, forKey: .text)
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
try container.encodeIfPresent(textColor, forKey: .textColor)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
@ -75,9 +75,9 @@ import Foundation
try container.encodeIfPresent(fontSize, forKey: .fontSize)
try container.encodeIfPresent(textAlignment, forKey: .textAlignment)
var attributeContainer = container.nestedUnkeyedContainer(forKey: .attributes)
try attributes?.forEach({ (attributeModel) in
try attributes?.forEach { attributeModel in
try attributeContainer.encode(attributeModel)
})
}
try container.encodeIfPresent(html, forKey: .html)
try container.encodeIfPresent(hero, forKey: .hero)
try container.encodeIfPresent(makeWholeViewClickable, forKey: .makeWholeViewClickable)

View File

@ -29,6 +29,18 @@ extension MFViewController: MoleculeDelegateProtocol {
}
return nil
}
@objc public func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {
}
@objc public func addMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
// Do nothing
}
@objc public func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
// Do nothing
}
}
public extension MFViewController {

View File

@ -14,6 +14,7 @@ import Foundation
public var backgroundColor: Color?
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
}
@ -48,6 +49,7 @@ import Foundation
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
}
}

View File

@ -17,6 +17,7 @@ class AccordionListItemModel: MoleculeContainerModel, ListItemModelProtocol {
public var line: LineModel?
private enum CodingKeys: String, CodingKey {
case moleculeName
case molecules
case backgroundColor
case hideLineWhenExpanded
@ -38,6 +39,7 @@ class AccordionListItemModel: MoleculeContainerModel, ListItemModelProtocol {
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeModels(molecules, forKey: .molecules)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(hideLineWhenExpanded, forKey: .hideLineWhenExpanded)

View File

@ -14,8 +14,10 @@ import Foundation
public var backgroundColor: Color?
public var peakingUI: Bool?
public var peakingArrowColor: Color?
public var moleculeName: String?
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case peakingUI
case peakingArrowColor
@ -23,6 +25,7 @@ import Foundation
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
moleculeName = try typeContainer.decodeIfPresent(String.self, forKey: .moleculeName)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
peakingUI = try typeContainer.decodeIfPresent(Bool.self, forKey: .peakingUI)
peakingArrowColor = try typeContainer.decodeIfPresent(Color.self, forKey: .peakingArrowColor)
@ -32,6 +35,7 @@ import Foundation
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(peakingUI, forKey: .peakingUI)
try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor)

View File

@ -9,59 +9,58 @@
import UIKit
@objcMembers public class DropDownFilterTableViewCell: TableViewCell {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
var dropDownListItemModel: DropDownListItemModel?
let dropDown = DropDown(forDropDownWithBothDelegates: nil)
let dropDown = ItemDropdownEntryField()
var delegateObject: MVMCoreUIDelegateObject?
var previousIndex = NSNotFound
var dropDownSelectionObservation: NSKeyValueObservation?
// MARK: - MFViewProtocol
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
override public func setupView() {
super.setupView()
guard let dropDown = dropDown, dropDown.superview == nil else {
return
}
dropDown.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(dropDown)
NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: dropDown, useMargins: true).values))
#warning("Once we have the state manager, we will need to change this logic to only add or remove on user selection...Want to avoid re-use crashes from array size differences")
dropDownSelectionObservation = observe(
\.dropDown?.textField?.text,
options: [.old, .new]
) { [weak self] object, change in
guard change.newValue != change.oldValue, let self = self,
let options = self.dropDown?.json?.optionalArrayForKey("options") as? [NSString],
let index = options.firstIndex(of: change.newValue!! as NSString),
let molecules = self.dropDownListItemModel?.molecules else { return }
guard dropDown.superview == nil else { return }
addMolecule(dropDown)
dropDown.observeDropdownChange = { [weak self] oldValue, newValue in
guard newValue != oldValue,
let self = self,
let index = self.dropDown.pickerData.firstIndex(of: newValue),
let dropListItemJSON = self.dropDownListItemModel.toJSON(),
let json2d = dropListItemJSON.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]]
else { return }
if self.previousIndex != NSNotFound {
self.delegateObject?.moleculeDelegate?.removeMolecules(molecules[self.previousIndex], sender: self, animation: .fade)
self.delegateObject?.moleculeDelegate?.removeMolecules(json2d[self.previousIndex], sender: self, animation: .fade)
}
self.delegateObject?.moleculeDelegate?.addMolecules(molecules[index], sender: self, animation: .fade)
self.delegateObject?.moleculeDelegate?.addMolecules(json2d[index], sender: self, animation: .fade)
self.previousIndex = index
}
}
public override func updateView(_ size: CGFloat) {
super.updateView(size)
dropDown?.updateView(size)
}
public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
dropDownListItemModel = model as? DropDownListItemModel
self.delegateObject = delegateObject
super.setWithModel(model, delegateObject, additionalData)
dropDown?.mfTextFieldDelegate = delegateObject?.uiTextFieldDelegate as? MFTextFieldDelegate
dropDown?.uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
dropDown?.setWithModel(dropDownListItemModel, delegateObject, additionalData)
dropDown.setWithModel(dropDownListItemModel?.dropDown, delegateObject, additionalData)
dropDown.observingTextFieldDelegate = delegateObject?.uiTextFieldDelegate as? ObservingTextFieldDelegate
dropDown.uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
}
public override func reset() {
super.reset()
bottomSeparatorView?.setStyle(.none)
}
public override static func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 80
}
}

View File

@ -9,41 +9,79 @@
import Foundation
@objcMembers public class DropDownListItemModel: ContainerModel, ListItemModelProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "dropDownListItem"
public var molecules: [[ListItemModelProtocol]]
public var dropDown: DropDownModel
public var dropDown: ItemDropdownEntryFieldModel
public var backgroundColor: Color?
public var line: LineModel? = LineModel(type: .none)
public var hideArrow: Bool? = true
/// Defaults to set
func setDefaults() {
if useHorizontalMargins == nil {
useHorizontalMargins = true
}
if useVerticalMargins == nil {
useVerticalMargins = true
}
if topMarginPadding == nil {
topMarginPadding = 24
}
if bottomMarginPadding == nil {
bottomMarginPadding = 0
}
}
public init(molecules: [[ListItemModelProtocol]], dropDown: DropDownModel) {
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(molecules: [[ListItemModelProtocol]], dropDown: ItemDropdownEntryFieldModel) {
self.molecules = molecules
self.dropDown = dropDown
super.init()
setDefaults()
}
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case molecules
case dropDown
case line
case backgroundColor
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
required public init(from decoder: Decoder) throws {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
molecules = try typeContainer.decodeMolecules2D(codingKey: .molecules) as! [[ListItemModelProtocol]]
dropDown = try typeContainer.decode(DropDownModel.self, forKey: .dropDown)
molecules = try typeContainer.decodeMolecules2D(codingKey: .molecules) as? [[ListItemModelProtocol]] ?? [[]]
dropDown = try typeContainer.decode(ItemDropdownEntryFieldModel.self, forKey: .dropDown)
if let lineModel = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) {
line = lineModel
}
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
try super.init(from: decoder)
setDefaults()
}
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeModels2D(molecules, forKey: .molecules)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeModels2D(molecules, forKey: .molecules)
try container.encode(dropDown, forKey: .dropDown)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeIfPresent(line, forKey: .line)

View File

@ -10,6 +10,7 @@ import Foundation
import MVMCore
@objcMembers public class ListItemModel: MoleculeContainerModel, ListItemModelProtocol {
public static var identifier: String = "listItem"
public var backgroundColor: Color?
public var action: ActionModelProtocol?
@ -18,6 +19,7 @@ import MVMCore
public var style: String? = "standard"
private enum CodingKeys: String, CodingKey {
case moleculeName
case backgroundColor
case action
case hideArrow
@ -62,6 +64,7 @@ import MVMCore
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeModelIfPresent(action, forKey: .action)
try container.encodeIfPresent(hideArrow, forKey: .hideArrow)

View File

@ -16,6 +16,7 @@ import Foundation
public var gone: Bool = false
private enum CodingKeys: String, CodingKey {
case moleculeName
case spacing
case percent
case gone
@ -38,6 +39,7 @@ import Foundation
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encodeIfPresent(spacing, forKey: .spacing)
try container.encodeIfPresent(percent, forKey: .percent)
try container.encode(gone, forKey: .gone)

View File

@ -18,6 +18,7 @@ public class TabsListItemModel: ContainerModel, ListItemModelProtocol {
public var line: LineModel? = LineModel(type: .standard)
private enum CodingKeys: String, CodingKey {
case moleculeName
case tabs
case molecules
case backgroundColor
@ -46,6 +47,7 @@ public class TabsListItemModel: ContainerModel, ListItemModelProtocol {
public override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(tabs, forKey: .tabs)
try container.encodeModels2D(molecules, forKey: .molecules)
try container.encode(backgroundColor, forKey: .backgroundColor)

View File

@ -10,6 +10,7 @@ import Foundation
@objcMembers public class HeadlineBodyModel: MoleculeModelProtocol {
public static var identifier: String = "headlineBody"
public var moleculeName: String?
public var headline: LabelModel?
public var body: LabelModel?
public var style: String?

View File

@ -35,6 +35,7 @@ import Foundation
public override func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encode(moleculeName, forKey: .moleculeName)
var models: [MoleculeModelProtocol] = []
for molecule in molecules {

View File

@ -41,6 +41,7 @@ import Foundation
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(bulletChar, forKey: .bulletChar)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encode(moleculeName, forKey: .moleculeName)
var models: [MoleculeModelProtocol] = []
for molecule in molecules {

View File

@ -31,15 +31,19 @@ extension MoleculeDelegateProtocol {
public func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {
// Do Nothing
}
public func addMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
// Do nothpublic ing
// Do nothing
}
public func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
// Do nothing
}
public func addMolecules(_ molecules: [ListItemModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
// Do nothpublic ing
// Do nothing
}
public func removeMolecules(_ molecules: [ListItemModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
// Do nothing
}

View File

@ -32,10 +32,15 @@ import Foundation
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Link.self, viewModelClass: LinkModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CaretButton.self, viewModelClass: CaretLinkModel.self)
// Entry Field
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TextEntryField.self, viewModelClass: TextEntryFieldModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MdnEntryField.self, viewModelClass: MdnEntryFieldModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: DigitEntryField.self, viewModelClass: DigitEntryFieldModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ItemDropdownEntryField.self, viewModelClass: ItemDropdownEntryFieldModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: DateDropdownEntryField.self, viewModelClass: DateDropdownEntryFieldModel.self)
// Other Atoms
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Label.self, viewModelClass: LabelModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TextEntryField.self, viewModelClass: TextFieldModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: DropDown.self, viewModelClass: DropDownModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ProgressBar.self, viewModelClass: ProgressBarModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: MultiProgress.self, viewModelClass: MultiProgressBarModel.self)
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CaretView.self, viewModelClass: CaretViewModel.self)

View File

@ -9,10 +9,10 @@
import UIKit
open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol {
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: ListItemModelProtocol)]?
var observer: NSKeyValueObservation?
public var templateModel: ListPageTemplateModel?
@objc public override func parsePageJSON() throws {
try parseTemplateJSON()
@ -31,11 +31,11 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
}
}
}
open override func viewForTop() -> UIView {
guard let headerModel = templateModel?.header,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(headerModel, delegateObject() as? MVMCoreUIDelegateObject, false) else {
return super.viewForTop()
return super.viewForTop()
}
// Temporary, Default the horizontal padding
@ -48,7 +48,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
override open func viewForBottom() -> UIView {
guard let footerModel = templateModel?.footer,
let molecule = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(footerModel, delegateObject() as? MVMCoreUIDelegateObject, false) else {
return super.viewForBottom()
return super.viewForBottom()
}
return molecule
}
@ -97,7 +97,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let moleculeInfo = moleculesInfo?[indexPath.row],
let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier) else {
return UITableViewCell()
return UITableViewCell()
}
let delegate = delegateObject() as? MVMCoreUIDelegateObject
let moleculeCell = cell as? MVMCoreUIMoleculeViewProtocol
@ -136,7 +136,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
}
// MARK: - MoleculeDelegateProtocol
open func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {
open override func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {
if let tableView = tableView {
let point = molecule.convert(molecule.bounds.origin, to: tableView)
if let indexPath = tableView.indexPathForRow(at: point), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false {
@ -145,25 +145,78 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
}
}
}
public override func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
var tmpMolecules = [ListItemModelProtocol]()
molecules.forEach { molecule in
if let data = try? JSONSerialization.data(withJSONObject: molecule), let listItemModel = try? JSONDecoder().decode(ListItemModel.self, from: data) {
tmpMolecules.append(listItemModel)
}
}
DispatchQueue.main.async {
guard let indexPath = self.tableView?.indexPath(for: sender) else { return }
var indexPaths: [IndexPath] = []
for molecule in tmpMolecules {
if let info = self.getMoleculeInfo(with: molecule) {
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
let index = indexPath.row + 1 + indexPaths.count
self.moleculesInfo?.insert(info, at: index)
indexPaths.append(IndexPath(row: index, section: 0))
}
}
self.tableView?.insertRows(at: indexPaths, with: animation)
self.updateViewConstraints()
self.view.layoutIfNeeded()
}
}
public override func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
var tmpMolecules = [ListItemModelProtocol]()
molecules.forEach { molecule in
if let data = try? JSONSerialization.data(withJSONObject: molecule), let listItemModel = try? JSONDecoder().decode(ListItemModel.self, from: data) {
tmpMolecules.append(listItemModel)
}
}
var indexPaths: [IndexPath] = []
//TODO: cehck for molecule protocola eqality
for molecule in tmpMolecules {
if let removeIndex = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in
return molecule.toJSONString() == moleculeInfo.molecule.toJSONString()
}) {
moleculesInfo?.remove(at: removeIndex)
indexPaths.append(IndexPath(row: removeIndex + indexPaths.count, section: 0))
}
}
self.tableView?.deleteRows(at: indexPaths, with: animation)
self.updateViewConstraints()
self.view.layoutIfNeeded()
}
public func addMolecules(_ molecules: [ListItemModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
// This dispatch is needed to fix a race condition that can occur if this function is called during the table setup.
DispatchQueue.main.async {
guard let indexPath = self.tableView?.indexPath(for: sender) else { return }
var indexPaths: [IndexPath] = []
for molecule in molecules {
if let info = self.getMoleculeInfo(with: molecule) {
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
let index = indexPath.row + 1 + indexPaths.count
self.moleculesInfo?.insert(info, at: index)
indexPaths.append(IndexPath(row: index, section: 0))
}
}
self.tableView?.insertRows(at: indexPaths, with: animation)
self.updateViewConstraints()
self.view.layoutIfNeeded()
}
DispatchQueue.main.async {
guard let indexPath = self.tableView?.indexPath(for: sender) else { return }
var indexPaths: [IndexPath] = []
for molecule in molecules {
if let info = self.getMoleculeInfo(with: molecule) {
self.tableView?.register(info.class, forCellReuseIdentifier: info.identifier)
let index = indexPath.row + 1 + indexPaths.count
self.moleculesInfo?.insert(info, at: index)
indexPaths.append(IndexPath(row: index, section: 0))
}
}
self.tableView?.insertRows(at: indexPaths, with: animation)
self.updateViewConstraints()
self.view.layoutIfNeeded()
}
}
public func removeMolecules(_ molecules: [ListItemModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
var indexPaths: [IndexPath] = []
//TODO: cehck for molecule protocola eqality
@ -186,7 +239,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
guard let listItem = listItem,
let moleculeClass = MVMCoreUIMoleculeMappingObject.shared()?.getMoleculeClass(listItem),
let moleculeName = (moleculeClass as? ModelMoleculeViewProtocol.Type)?.nameForReuse(listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName else {
return nil
return nil
}
return (moleculeName, moleculeClass, listItem)
}