From f7ce81874e2a7d5ff98a9eb3be0161a873881ee1 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 22 Jan 2020 11:47:21 -0500 Subject: [PATCH 01/25] EntryField Models. Updated dropdown for new dropdown. --- MVMCoreUI.xcodeproj/project.pbxproj | 36 +++++++-- .../TextFields/BaseDropdownEntryField.swift | 6 ++ .../BaseDropdownEntryFieldModel.swift | 18 +++++ .../TextFields/DateDropdownEntryField.swift | 10 +++ .../DateDropdownEntryFieldModel.swift | 43 +++++++++++ .../Atoms/TextFields/DigitEntryField.swift | 16 ++++ .../TextFields/DigitEntryFieldModel.swift | 49 ++++++++++++ MVMCoreUI/Atoms/TextFields/EntryField.swift | 37 ++++++++++ .../Atoms/TextFields/EntryFieldModel.swift | 74 +++++++++++++++++++ .../TextFields/ItemDropdownEntryField.swift | 15 +++- .../ItemDropdownEntryFieldModel.swift | 43 +++++++++++ .../Atoms/TextFields/MdnEntryFieldModel.swift | 17 +++++ .../Atoms/TextFields/TextEntryField.swift | 56 ++++++++++++++ .../TextFields/TextEntryFieldModel.swift | 65 ++++++++++++++++ MVMCoreUI/Atoms/Views/DropDown.swift | 55 -------------- MVMCoreUI/Atoms/Views/DropDownModel.swift | 22 ------ .../views/EntryFieldContainer.swift | 10 ++- .../Items/DropDownFilterTableViewCell.swift | 36 +++++---- .../Items/DropDownListItemModel.swift | 6 +- .../MVMCoreUIMoleculeMappingObject.m | 2 +- 20 files changed, 505 insertions(+), 111 deletions(-) create mode 100644 MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift create mode 100644 MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift create mode 100644 MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift create mode 100644 MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift create mode 100644 MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift create mode 100644 MVMCoreUI/Atoms/TextFields/MdnEntryFieldModel.swift create mode 100644 MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift delete mode 100644 MVMCoreUI/Atoms/Views/DropDown.swift delete mode 100644 MVMCoreUI/Atoms/Views/DropDownModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 3371e6ca..6fa69289 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -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 */; }; 0ABD136B237B193A0081388D /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136A237B193A0081388D /* EntryFieldContainer.swift */; }; 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; }; @@ -148,7 +154,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 */; }; @@ -318,7 +323,6 @@ 0116A4E4228B19640094F3ED /* RadioButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonModel.swift; sourceTree = ""; }; 011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemModelProtocol.swift; sourceTree = ""; }; 011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDownListItemModel.swift; sourceTree = ""; }; - 011B58F323A2CCC80085F53C /* DropDownModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDownModel.swift; sourceTree = ""; }; 012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModelProtocol.swift; sourceTree = ""; }; 012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateProtocol.swift; sourceTree = ""; }; 012A88AE238C626E00FE3DA1 /* CarouselModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselModel.swift; sourceTree = ""; }; @@ -375,6 +379,13 @@ 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; 0A7BAFA2232BE63400FB8E22 /* CheckboxWithLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckboxWithLabelView.swift; sourceTree = ""; }; + 0A7EF85A23D8A52800B2AAD1 /* EntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryFieldModel.swift; sourceTree = ""; }; + 0A7EF85C23D8A95600B2AAD1 /* TextEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryFieldModel.swift; sourceTree = ""; }; + 0A7EF85E23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MdnEntryFieldModel.swift; sourceTree = ""; }; + 0A7EF86023D8AC2500B2AAD1 /* DigitEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitEntryFieldModel.swift; sourceTree = ""; }; + 0A7EF86223D8AFA000B2AAD1 /* BaseDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDropdownEntryFieldModel.swift; sourceTree = ""; }; + 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryFieldModel.swift; sourceTree = ""; }; + 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryFieldModel.swift; sourceTree = ""; }; 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = ""; }; 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = ""; }; 0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = ""; }; @@ -440,7 +451,6 @@ D260D7B022D65BDD007E7233 /* MVMCoreUIPageControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIPageControl.m; sourceTree = ""; }; D260D7B522D68509007E7233 /* MVMCoreUIPagingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIPagingProtocol.h; sourceTree = ""; }; D268C70D238C22D7007F2C1C /* DropDownFilterTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropDownFilterTableViewCell.swift; sourceTree = ""; }; - D268C711238D6699007F2C1C /* DropDown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDown.swift; sourceTree = ""; }; D274CA322236A78900B01B62 /* FooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterView.swift; sourceTree = ""; }; D2755D7A23689C7500485468 /* TableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCell.swift; sourceTree = ""; }; D27CD40D2322EEAF00C1DC07 /* TabsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabsTableViewCell.swift; sourceTree = ""; }; @@ -1138,8 +1148,6 @@ D282AAB3223FDDAE00C46919 /* MFLoadImageView.swift */, 017BEB7A236763000024EF95 /* LineModel.swift */, D213347623843825008E41B3 /* Line.swift */, - 011B58F323A2CCC80085F53C /* DropDownModel.swift */, - D268C711238D6699007F2C1C /* DropDown.swift */, DBC4391C2245232D001AB423 /* LabelWithInternalButton.swift */, 94C2D9822386F3E30006CF46 /* Label */, 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */, @@ -1161,13 +1169,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; @@ -1500,6 +1515,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 */, @@ -1554,24 +1570,29 @@ 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 */, 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 */, 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 */, @@ -1651,7 +1672,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 */, @@ -1662,12 +1682,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 */, diff --git a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryField.swift index 05e64f70..6cb0c96a 100644 --- a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryField.swift @@ -68,6 +68,12 @@ 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) + + dropDownCaretView.setWithModel(model, delegateObject, additionalData) + } } // MARK: - MVMCoreUIMoleculeViewProtocol diff --git a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift new file mode 100644 index 00000000..3dffa669 --- /dev/null +++ b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift @@ -0,0 +1,18 @@ +// +// 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 override class var identifier: String { + return "" + } +} diff --git a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift index feddfd6b..6fde6b45 100644 --- a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift @@ -112,6 +112,16 @@ import UIKit return formatter } + + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.setWithModel(model, delegateObject, additionalData) + + guard let model = model as? DateDropdownEntryFieldModel else { return } + + if let dateFormat = model.dateFormat { + self.dateFormat = dateFormat + } + } } // MARK: - MVMCoreUIMoleculeViewProtocol diff --git a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift new file mode 100644 index 00000000..d2c9d747 --- /dev/null +++ b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift @@ -0,0 +1,43 @@ +// +// 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? + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + 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) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(dateFormat, forKey: .dateFormat) + } +} diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift index 4cd9b67a..ce741346 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift @@ -327,6 +327,22 @@ import UIKit } } } + + public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.setWithModel(model, delegateObject, additionalData) + + guard let model = model as? DigitEntryFieldModel else { return } + + numberOfDigits = model.digits ?? 4 + + if let secureEntry = model.secureEntry, secureEntry { + setAsSecureTextEntry(true) + } + + for digitBox in digitBoxes { + MVMCoreUICommonViewsUtility.addDismissToolbar(digitBox.digitField, delegate: delegateObject as? UITextFieldDelegate) + } + } } // MARK: - TextField Delegate diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift new file mode 100644 index 00000000..bab3f81b --- /dev/null +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift @@ -0,0 +1,49 @@ +// +// 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 "DigitEntryField" + } + + public var digits: Int? + public var secureEntry: Bool? + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + 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) + secureEntry = try typeContainer.decodeIfPresent(Bool.self, forKey: .secureEntry) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(digits, forKey: .digits) + try container.encodeIfPresent(secureEntry, forKey: .secureEntry) + } +} diff --git a/MVMCoreUI/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atoms/TextFields/EntryField.swift index 7e40feba..25b8b670 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryField.swift @@ -238,6 +238,43 @@ 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) + + if let title = model.title { + self.title = title + } + + if let isDisabled = model.isDisabled { + self.isEnabled = isDisabled + } + + if let feedback = model.feedback { + self.feedback = feedback + } + + if let errorMessage = model.errorMessage { + self.errorMessage = errorMessage + } + + if let isLocked = model.isLocked { + self.isLocked = isLocked + } + + if let isSelected = model.isSelected { + self.isSelected = isSelected + } + + if let fieldKey = model.fieldKey { + self.fieldKey = fieldKey + } + } } // MARK: - MVMCoreUIMoleculeViewProtocol diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift new file mode 100644 index 00000000..ce6d2207 --- /dev/null +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -0,0 +1,74 @@ +// +// 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 title: String? + public var feedback: String? + public var errorMessage: String? + public var isDisabled: Bool? + public var isLocked: Bool? + public var isSelected: Bool? + + public var fieldKey: String? + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + case backgroundColor + case title + case isDisabled + case feedback + case errorMessage + case isLocked + case isSelected + case fieldKey + } + + //-------------------------------------------------- + // MARK: - Initializers + //-------------------------------------------------- + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + 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) + isDisabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isDisabled) + isLocked = try typeContainer.decodeIfPresent(Bool.self, forKey: .isLocked) + isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected) + fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(title, forKey: .title) + try container.encodeIfPresent(feedback, forKey: .feedback) + try container.encodeIfPresent(errorMessage, forKey: .errorMessage) + try container.encodeIfPresent(isDisabled, forKey: .isDisabled) + try container.encodeIfPresent(isLocked, forKey: .isLocked) + try container.encodeIfPresent(isSelected, forKey: .isSelected) + try container.encodeIfPresent(fieldKey, forKey: .fieldKey) + } +} diff --git a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift index 7eaf6c5c..440ad5fc 100644 --- a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift @@ -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,17 @@ 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 } + + if let options = model.options { + pickerData = options + setPickerDelegates(delegate: self) + } + } } // MARK:- Base Picker Delegate @@ -108,8 +119,8 @@ extension ItemDropdownEntryField: UIPickerViewDelegate, UIPickerViewDataSource { } @objc public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { + observeDropdownChange?(text ?? "", pickerData[row]) text = pickerData[row] - observeDropdownChange?(pickerData[row]) } } diff --git a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift new file mode 100644 index 00000000..1d110c57 --- /dev/null +++ b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift @@ -0,0 +1,43 @@ +// +// 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 "ItemDropdownEntryField" + } + + public var options: [String]? + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + 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.decodeIfPresent([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.encodeIfPresent(options, forKey: .options) + } +} diff --git a/MVMCoreUI/Atoms/TextFields/MdnEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/MdnEntryFieldModel.swift new file mode 100644 index 00000000..d07c7524 --- /dev/null +++ b/MVMCoreUI/Atoms/TextFields/MdnEntryFieldModel.swift @@ -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" + } +} diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index 5ff12679..a2a9631f 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -270,6 +270,62 @@ 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) + + if let enabledTextColor = model.enabledTextColor { + textColor.enabled = enabledTextColor.uiColor + } + + if let disabledTextColor = model.disabledTextColor { + textColor.disabled = disabledTextColor.uiColor + } + + if let text = model.text { + self.text = text + } + + if let placeholder = model.placeholder { + self.placeholder = placeholder + } + + switch model.type { + case "password": + textField.isSecureTextEntry = true + + case "number": + textField.keyboardType = .numberPad + + case "email": + textField.keyboardType = .emailAddress + + default: + break + } + + let regex = model.regex ?? "" + + if !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 diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift new file mode 100644 index 00000000..bd69c908 --- /dev/null +++ b/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift @@ -0,0 +1,65 @@ +// +// 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 "TextEntryField" + } + + 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 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.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) + } +} diff --git a/MVMCoreUI/Atoms/Views/DropDown.swift b/MVMCoreUI/Atoms/Views/DropDown.swift deleted file mode 100644 index 929bd67f..00000000 --- a/MVMCoreUI/Atoms/Views/DropDown.swift +++ /dev/null @@ -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 - } -} diff --git a/MVMCoreUI/Atoms/Views/DropDownModel.swift b/MVMCoreUI/Atoms/Views/DropDownModel.swift deleted file mode 100644 index 8e3e4e10..00000000 --- a/MVMCoreUI/Atoms/Views/DropDownModel.swift +++ /dev/null @@ -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 - } -} diff --git a/MVMCoreUI/Containers/views/EntryFieldContainer.swift b/MVMCoreUI/Containers/views/EntryFieldContainer.swift index 96a51a8f..98e3d661 100644 --- a/MVMCoreUI/Containers/views/EntryFieldContainer.swift +++ b/MVMCoreUI/Containers/views/EntryFieldContainer.swift @@ -271,9 +271,17 @@ import UIKit layoutIfNeeded() } } + + //-------------------------------------------------- + // MARK: - MVMCoreUIMoleculeViewProtocol + //-------------------------------------------------- + + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.setWithModel(model, delegateObject, additionalData) + self.delegateObject = delegateObject + } } -// MARK:- MVMCoreUIMoleculeViewProtocol extension EntryFieldContainer { override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index cd18eb04..abf6f711 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -9,37 +9,35 @@ import UIKit @objcMembers public class DropDownFilterTableViewCell: TableViewCell { + var dropDownListItemModel: DropDownListItemModel? - let dropDown = DropDown(forDropDownWithBothDelegates: nil) + let dropDown = ItemDropdownEntryField() var delegateObject: MVMCoreUIDelegateObject? var previousIndex = NSNotFound var dropDownSelectionObservation: NSKeyValueObservation? - + // MARK: - MFViewProtocol override public func setupView() { super.setupView() - guard let dropDown = dropDown, dropDown.superview == nil else { - return - } + guard 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), + dropDown.observeDropdownChange = { [weak self] oldValue, newValue in + + guard newValue != oldValue, + let self = self, + let options = self.dropDown.json?.optionalArrayForKey("options") as? [NSString], + let index = options.firstIndex(of: newValue as NSString), let molecules = self.dropDownListItemModel?.molecules else { return } if self.previousIndex != NSNotFound { self.delegateObject?.moleculeDelegate?.removeMolecules(molecules[self.previousIndex], sender: self, animation: .fade) } + self.delegateObject?.moleculeDelegate?.addMolecules(molecules[index], sender: self, animation: .fade) self.previousIndex = index } @@ -47,17 +45,17 @@ import UIKit public override func updateView(_ size: CGFloat) { super.updateView(size) - dropDown?.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.observingTextFieldDelegate = delegateObject?.uiTextFieldDelegate as? ObservingTextFieldDelegate + dropDown.uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate + dropDown.setWithModel(dropDownListItemModel, delegateObject, additionalData) } public override func reset() { diff --git a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift index c7b9ca75..47ea71c5 100644 --- a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift @@ -11,12 +11,12 @@ import Foundation @objcMembers public class DropDownListItemModel: MoleculeContainerModel, ListItemModelProtocol { 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 - public init(molecule: MoleculeModelProtocol, molecules: [[ListItemModelProtocol]], dropDown: DropDownModel) { + public init(molecule: MoleculeModelProtocol, molecules: [[ListItemModelProtocol]], dropDown: ItemDropdownEntryFieldModel) { self.molecules = molecules self.dropDown = dropDown super.init(with: molecule) @@ -32,7 +32,7 @@ import Foundation 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) + dropDown = try typeContainer.decode(ItemDropdownEntryFieldModel.self, forKey: .dropDown) if let lineModel = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) { line = lineModel } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index b5a39119..4f2d6e3c 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -36,10 +36,10 @@ @"caretView": CaretView.class, @"caretLink": CaretButton.class, @"textField": MFTextField.class, - @"dropDown": DropDown.class, @"digitTextField": MFDigitTextField.class, @"digitEntryField": DigitEntryField.class, @"textEntryField": TextEntryField.class, + @"mdnEntryField": MdnEntryField.class, @"itemDropdownEntryField": ItemDropdownEntryField.class, @"dateDropdownEntryField": DateDropdownEntryField.class, @"checkbox": Checkbox.class, From 1eec90e8e12e5f86e6f1e5e5fceefbc398e8792d Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 22 Jan 2020 11:57:16 -0500 Subject: [PATCH 02/25] align model. --- MVMCoreUI/Containers/Views/EntryFieldContainer.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift index 96a51a8f..98e3d661 100644 --- a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift +++ b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift @@ -271,9 +271,17 @@ import UIKit layoutIfNeeded() } } + + //-------------------------------------------------- + // MARK: - MVMCoreUIMoleculeViewProtocol + //-------------------------------------------------- + + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.setWithModel(model, delegateObject, additionalData) + self.delegateObject = delegateObject + } } -// MARK:- MVMCoreUIMoleculeViewProtocol extension EntryFieldContainer { override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { From 86ce3c9d4f9f216a1a12f66fa7e8b1fb426e412e Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 22 Jan 2020 14:51:27 -0500 Subject: [PATCH 03/25] modeling entryField --- .../TextFields/DateDropdownEntryFieldModel.swift | 2 +- MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift | 3 +-- MVMCoreUI/Atoms/TextFields/EntryField.swift | 1 + MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift | 11 ++++++++--- .../TextFields/ItemDropdownEntryFieldModel.swift | 2 +- MVMCoreUI/Atoms/TextFields/MdnEntryFieldModel.swift | 2 +- MVMCoreUI/Atoms/TextFields/TextEntryField.swift | 4 +--- MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift | 3 +-- .../BaseControllers/MFViewController+Model.swift | 4 ++++ .../OtherHandlers/MVMCoreUIMoleculeMappingObject.m | 8 +++----- MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift | 2 +- MVMCoreUI/Templates/MoleculeListTemplate.swift | 2 +- 12 files changed, 24 insertions(+), 20 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift index d2c9d747..ebccffcd 100644 --- a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift @@ -12,7 +12,7 @@ //-------------------------------------------------- public override class var identifier: String { - return "DateDropdownEntryField" + return "dateDropdownEntryField" } public var dateFormat: String? diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift index bab3f81b..a798eebb 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift @@ -8,13 +8,12 @@ @objcMembers public class DigitEntryFieldModel: TextEntryFieldModel { - //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- public override class var identifier: String { - return "DigitEntryField" + return "digitTextField" } public var digits: Int? diff --git a/MVMCoreUI/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atoms/TextFields/EntryField.swift index 25b8b670..57d1b0bf 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryField.swift @@ -119,6 +119,7 @@ import UIKit feedbackLabel.text = newFeedback feedbackLabel.accessibilityElementsHidden = feedbackLabel.text?.isEmpty ?? true entryFieldContainer.refreshUI() + delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) } } diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index ce6d2207..dbf240ee 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -10,7 +10,6 @@ import Foundation @objcMembers public class EntryFieldModel: MoleculeModelProtocol { - //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -28,7 +27,9 @@ import Foundation public var isSelected: Bool? public var fieldKey: String? - + public var isValid: Bool? + public var isRequired: Bool? + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- @@ -38,10 +39,12 @@ import Foundation case title case isDisabled case feedback - case errorMessage + case errorMessage = "errorMsg" case isLocked case isSelected case fieldKey + case isValid + case isRequired = "required" } //-------------------------------------------------- @@ -58,6 +61,7 @@ import Foundation 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 { @@ -70,5 +74,6 @@ import Foundation try container.encodeIfPresent(isLocked, forKey: .isLocked) try container.encodeIfPresent(isSelected, forKey: .isSelected) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) + try container.encodeIfPresent(isValid, forKey: .isValid) } } diff --git a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift index 1d110c57..e1313086 100644 --- a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift @@ -12,7 +12,7 @@ //-------------------------------------------------- public override class var identifier: String { - return "ItemDropdownEntryField" + return "dropDown" } public var options: [String]? diff --git a/MVMCoreUI/Atoms/TextFields/MdnEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/MdnEntryFieldModel.swift index d07c7524..ea367447 100644 --- a/MVMCoreUI/Atoms/TextFields/MdnEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/MdnEntryFieldModel.swift @@ -12,6 +12,6 @@ //-------------------------------------------------- public override class var identifier: String { - return "MdnEntryField" + return "mdnEntryField" } } diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index a2a9631f..f4381faf 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -308,9 +308,7 @@ import UIKit break } - let regex = model.regex ?? "" - - if !regex.isEmpty { + if let regex = model.regex, !regex.isEmpty { validationBlock = { enteredValue in guard let value = enteredValue else { return false } return MVMCoreUIUtility.validate(value, withRegularExpression: regex) diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift index bd69c908..d890d918 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift @@ -8,13 +8,12 @@ @objcMembers public class TextEntryFieldModel: EntryFieldModel { - //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- public override class var identifier: String { - return "TextEntryField" + return "textField" } public var text: String? diff --git a/MVMCoreUI/BaseControllers/MFViewController+Model.swift b/MVMCoreUI/BaseControllers/MFViewController+Model.swift index 7e250b2a..f503d0b5 100644 --- a/MVMCoreUI/BaseControllers/MFViewController+Model.swift +++ b/MVMCoreUI/BaseControllers/MFViewController+Model.swift @@ -29,6 +29,10 @@ extension MFViewController: MoleculeDelegateProtocol { } return nil } + + @objc public func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) { + + } } public extension MFViewController { diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index 4f2d6e3c..e0c83569 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -35,12 +35,10 @@ @"footer": FooterView.class, @"caretView": CaretView.class, @"caretLink": CaretButton.class, - @"textField": MFTextField.class, - @"digitTextField": MFDigitTextField.class, - @"digitEntryField": DigitEntryField.class, - @"textEntryField": TextEntryField.class, + @"digitTextField": DigitEntryField.class, + @"textField": TextEntryField.class, @"mdnEntryField": MdnEntryField.class, - @"itemDropdownEntryField": ItemDropdownEntryField.class, + @"dropDown": ItemDropdownEntryField.class, @"dateDropdownEntryField": DateDropdownEntryField.class, @"checkbox": Checkbox.class, @"checkboxLabel": CheckboxWithLabelView.class, diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 54ec832c..3972002d 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -33,7 +33,7 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CaretButton.self, viewModelClass: CaretLinkModel.self) // Entry Field - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: TextEntryField.self, viewModelClass: TextFieldModel.self) + 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) diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 61e1121c..920439a1 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -123,7 +123,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 { From ccb8a2cf524254f1eb5efd5956bda47a3038c8f7 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 22 Jan 2020 15:39:39 -0500 Subject: [PATCH 04/25] weak change --- .../Views/EntryFieldContainer.swift | 2 +- .../views/EntryFieldContainer.swift | 293 ------------------ 2 files changed, 1 insertion(+), 294 deletions(-) delete mode 100644 MVMCoreUI/Containers/views/EntryFieldContainer.swift diff --git a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift index 98e3d661..3f80006a 100644 --- a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift +++ b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift @@ -118,7 +118,7 @@ import UIKit //-------------------------------------------------- /// Holds reference to delegateObject to inform molecular tableView of an update. - weak var delegateObject: MVMCoreUIDelegateObject? + var delegateObject: MVMCoreUIDelegateObject? //-------------------------------------------------- // MARK: - Lifecycle diff --git a/MVMCoreUI/Containers/views/EntryFieldContainer.swift b/MVMCoreUI/Containers/views/EntryFieldContainer.swift deleted file mode 100644 index 98e3d661..00000000 --- a/MVMCoreUI/Containers/views/EntryFieldContainer.swift +++ /dev/null @@ -1,293 +0,0 @@ -// -// EntryFieldContainer.swift -// MVMCoreUI -// -// Created by Kevin Christiano on 11/12/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import UIKit - - -@objcMembers open class EntryFieldContainer: View { - //-------------------------------------------------- - // MARK: - Drawing Properties - //-------------------------------------------------- - - /// The bottom border line. Height is dynamic based on scenario. - public var bottomBar: CAShapeLayer? = { - let layer = CAShapeLayer() - layer.backgroundColor = UIColor.black.cgColor - layer.drawsAsynchronously = true - layer.anchorPoint = CGPoint(x: 0.5, y: 1.0); - return layer - }() - - /// Total control over the drawn top, bottom, left and right borders. - public var disableAllBorders = false { - didSet { - bottomBar?.isHidden = disableAllBorders - } - } - - private(set) var fieldState: FieldState = .original { - didSet (oldState) { - // Will not update if new state is the same as old. - if fieldState != oldState { - DispatchQueue.main.async { [weak self] in - guard let self = self else { return } - - self.fieldState.setStateUI(for: self) - } - } - } - } - - /// Determines if the top, left, and right borders should be drawn. - private var hideBorders = false - - public var borderStrokeColor: UIColor = .mfSilver() - private var borderPath: UIBezierPath = UIBezierPath() - - //-------------------------------------------------- - // MARK: - Property Observers - //-------------------------------------------------- - - private var _isEnabled: Bool = true - private var _showError: Bool = false - private var _isLocked: Bool = false - private var _isSelected: Bool = false - - public var isEnabled: Bool { - get { return _isEnabled } - set (enabled) { - - _isEnabled = enabled - _isLocked = false - _isSelected = false - _showError = false - - fieldState = enabled ? .original : .disabled - } - } - - public var showError: Bool { - get { return _showError } - set (error) { - - _showError = error - _isEnabled = true - _isLocked = false - _isSelected = false - - fieldState = error ? .error : .original - } - } - - public var isLocked: Bool { - get { return _isLocked } - set (locked) { - - _isLocked = locked - _isEnabled = true - _isSelected = false - _showError = false - - fieldState = locked ? .locked : .original - } - } - - public var isSelected: Bool { - get { return _isSelected } - set (selected) { - - _isSelected = selected - _isLocked = false - _isEnabled = true - - if _showError { - fieldState = selected ? .selectedError : .error - } else { - fieldState = selected ? .selected : .original - } - } - } - - //-------------------------------------------------- - // MARK: - Delegate - //-------------------------------------------------- - - /// Holds reference to delegateObject to inform molecular tableView of an update. - weak var delegateObject: MVMCoreUIDelegateObject? - - //-------------------------------------------------- - // MARK: - Lifecycle - //-------------------------------------------------- - - open override func layoutSubviews() { - super.layoutSubviews() - - refreshUI(bottomBarSize: showError ? 4 : 1) - } - - open override func updateView(_ size: CGFloat) { - super.updateView(size) - - refreshUI() - } - - /// This handles the top, left, and right border lines. - open override func draw(_ rect: CGRect) { - super.draw(rect) - - borderPath.removeAllPoints() - - if !disableAllBorders && !hideBorders { - // Brings the other half of the line inside the view to prevent cropping. - let origin = bounds.origin - let size = frame.size - let insetLean: CGFloat = 0.5 - borderPath.lineWidth = 1 - - borderPath.move(to: CGPoint(x: origin.x + insetLean, y: origin.y + size.height)) - borderPath.addLine(to: CGPoint(x: origin.x + insetLean, y: origin.y + insetLean)) - borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + insetLean)) - borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + size.height)) - - borderStrokeColor.setStroke() - borderPath.stroke() - } - } - - override open func setupView() { - super.setupView() - - isAccessibilityElement = false - isOpaque = false - - if let bottomBar = bottomBar { - layer.addSublayer(bottomBar) - } - } - - //-------------------------------------------------- - // MARK: - Draw States - //-------------------------------------------------- - - public enum FieldState { - case original - case error - case selectedError - case selected - case locked - case disabled - - public func setStateUI(for formField: EntryFieldContainer) { - - switch self { - case .original: - formField.originalUI() - - case .error: - formField.errorUI() - - case .selectedError: - formField.selectedErrorUI() - - case .selected: - formField.selectedUI() - - case .locked: - formField.lockedUI() - - case .disabled: - formField.disabledUI() - } - } - } - - open func originalUI() { - - isUserInteractionEnabled = true - hideBorders = false - borderStrokeColor = .mfSilver() - bottomBar?.backgroundColor = UIColor.black.cgColor - refreshUI(bottomBarSize: 1) - } - - open func errorUI() { - - isUserInteractionEnabled = true - hideBorders = false - borderStrokeColor = .mfPumpkin() - bottomBar?.backgroundColor = UIColor.mfPumpkin().cgColor - refreshUI(bottomBarSize: 4) - } - - open func selectedErrorUI() { - - isUserInteractionEnabled = true - hideBorders = false - borderStrokeColor = .black - bottomBar?.backgroundColor = UIColor.mfPumpkin().cgColor - refreshUI(bottomBarSize: 4) - } - - open func selectedUI() { - - isUserInteractionEnabled = true - hideBorders = false - borderStrokeColor = .black - bottomBar?.backgroundColor = UIColor.black.cgColor - refreshUI(bottomBarSize: 1) - } - - open func lockedUI() { - - isUserInteractionEnabled = false - hideBorders = true - borderStrokeColor = .clear - bottomBar?.backgroundColor = UIColor.clear.cgColor - refreshUI(bottomBarSize: 1) - } - - open func disabledUI() { - - isUserInteractionEnabled = false - hideBorders = false - borderStrokeColor = .mfSilver() - bottomBar?.backgroundColor = UIColor.mfSilver().cgColor - refreshUI(bottomBarSize: 1) - } - - open func refreshUI(bottomBarSize: CGFloat? = nil) { - - if !disableAllBorders { - let size: CGFloat = bottomBarSize ?? (showError ? 4 : 1) - bottomBar?.frame = CGRect(x: 0, y: bounds.height - size, width: bounds.width, height: size) - - delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) - setNeedsDisplay() - layoutIfNeeded() - } - } - - //-------------------------------------------------- - // MARK: - MVMCoreUIMoleculeViewProtocol - //-------------------------------------------------- - - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) - self.delegateObject = delegateObject - } -} - -extension EntryFieldContainer { - - override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - self.delegateObject = delegateObject - - guard let dictionary = json, !dictionary.isEmpty else { return } - } -} From 8a09424dbe9cef6761de8514ffe16ff554998746 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 23 Jan 2020 10:27:36 -0500 Subject: [PATCH 05/25] Removed and added file back. Something was corrupted with the path name. --- MVMCoreUI.xcodeproj/project.pbxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 83a1815f..9b80960e 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -90,9 +90,9 @@ 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 */; }; - 0ABD136B237B193A0081388D /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136A237B193A0081388D /* EntryFieldContainer.swift */; }; 0ABD136D237CAD1E0081388D /* DateDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */; }; 0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */; }; + 0ACDF26723D9F177002044B2 /* EntryFieldContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ACDF26623D9F177002044B2 /* EntryFieldContainer.swift */; }; 0AE14F64238315D2005417F8 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE14F63238315D2005417F8 /* TextField.swift */; }; 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F3236B77BB006A1E82 /* GraphView.swift */; }; 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 943784F4236B77BB006A1E82 /* GraphViewAnimationHandler.swift */; }; @@ -390,9 +390,9 @@ 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = ""; }; 0AA33B33239813C50067DD0F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = ""; }; 0AA33B392398524F0067DD0F /* Toggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toggle.swift; sourceTree = ""; }; - 0ABD136A237B193A0081388D /* EntryFieldContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.swift; sourceTree = ""; }; 0ABD136C237CAD1E0081388D /* DateDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryField.swift; sourceTree = ""; }; 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemDropdownEntryField.swift; sourceTree = ""; }; + 0ACDF26623D9F177002044B2 /* EntryFieldContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntryFieldContainer.swift; sourceTree = ""; }; 0AE14F63238315D2005417F8 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = ""; }; 9402C34F23A2CEA3004B974C /* LeftRightLabelModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeftRightLabelModel.swift; sourceTree = ""; }; 943784F3236B77BB006A1E82 /* GraphView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphView.swift; sourceTree = ""; }; @@ -696,8 +696,8 @@ 0ABD1369237B18EE0081388D /* Views */ = { isa = PBXGroup; children = ( + 0ACDF26623D9F177002044B2 /* EntryFieldContainer.swift */, D29E28DE23D740FC00ACEA85 /* Container */, - 0ABD136A237B193A0081388D /* EntryFieldContainer.swift */, 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */, D2FB151A23A2B65B00C20E10 /* MoleculeContainer.swift */, ); @@ -1493,6 +1493,7 @@ 943784F5236B77BB006A1E82 /* GraphView.swift in Sources */, 94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */, D29DF32121ED0CBA003B2FB9 /* LabelView.m in Sources */, + 0ACDF26723D9F177002044B2 /* EntryFieldContainer.swift in Sources */, D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */, DBC4391822442197001AB423 /* CaretView.swift in Sources */, C07065C42395677300FBF997 /* Link.swift in Sources */, @@ -1696,7 +1697,6 @@ D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */, D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */, 014AA72E23C5059B006F3E93 /* StackCenteredPageTemplateModel.swift in Sources */, - 0ABD136B237B193A0081388D /* EntryFieldContainer.swift in Sources */, D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */, D260105923D0A92900764D80 /* ContainerProtocol.swift in Sources */, C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */, From e143c75215d2bcf91863356422aeacb052f38b3e Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 23 Jan 2020 13:10:57 -0500 Subject: [PATCH 06/25] redirect type --- MVMCoreUI/Molecules/Items/DropDownListItemModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift index ca78c3fa..28bc373b 100644 --- a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift @@ -16,7 +16,7 @@ import Foundation public var line: LineModel? = LineModel(type: .none) public var hideArrow: Bool? = true - public init(molecules: [[ListItemModelProtocol]], dropDown: DropDownModel) { + public init(molecules: [[ListItemModelProtocol]], dropDown: ItemDropdownEntryFieldModel) { self.molecules = molecules self.dropDown = dropDown super.init() From 0c7a2940d985e170604b5763a789ee6f1a823beb Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 23 Jan 2020 14:26:04 -0500 Subject: [PATCH 07/25] Fixing issues for model reuse. --- .../TextFields/DateDropdownEntryField.swift | 36 +-- .../DateDropdownEntryFieldModel.swift | 4 +- .../Atoms/TextFields/DigitEntryField.swift | 6 +- .../TextFields/DigitEntryFieldModel.swift | 8 +- MVMCoreUI/Atoms/TextFields/EntryField.swift | 29 +- .../Atoms/TextFields/EntryFieldModel.swift | 21 +- .../TextFields/ItemDropdownEntryField.swift | 4 + .../ItemDropdownEntryFieldModel.swift | 24 -- .../Atoms/TextFields/TextEntryField.swift | 8 +- .../views/EntryFieldContainer.swift | 293 ++++++++++++++++++ .../Items/DropDownFilterTableViewCell.swift | 10 +- .../Items/DropDownListItemModel.swift | 3 + 12 files changed, 349 insertions(+), 97 deletions(-) create mode 100644 MVMCoreUI/Containers/views/EntryFieldContainer.swift diff --git a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift index 6fde6b45..7051239c 100644 --- a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift @@ -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,29 +111,12 @@ import UIKit setTextWith(date: datePicker?.date) } - public func dateFormatter() -> DateFormatter { - - let formatter = DateFormatter() - formatter.dateStyle = .medium - formatter.timeZone = NSTimeZone.system - formatter.locale = .current - formatter.formatterBehavior = .default - - if let dateFormat = dateFormat { - formatter.dateFormat = dateFormat - } - - return formatter - } - public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) guard let model = model as? DateDropdownEntryFieldModel else { return } - if let dateFormat = model.dateFormat { - self.dateFormat = dateFormat - } + self.dateFormat = model.dateFormat } } diff --git a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift index ebccffcd..c226660b 100644 --- a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift @@ -15,7 +15,7 @@ return "dateDropdownEntryField" } - public var dateFormat: String? + public var dateFormat: String = "MMM d, y" //-------------------------------------------------- // MARK: - Keys @@ -32,7 +32,7 @@ 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) + dateFormat = try typeContainer.decodeIfPresent(String.self, forKey: .dateFormat) ?? "MMM d, y" } public override func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift index ce741346..c7888041 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift @@ -333,11 +333,9 @@ import UIKit guard let model = model as? DigitEntryFieldModel else { return } - numberOfDigits = model.digits ?? 4 + numberOfDigits = model.digits - if let secureEntry = model.secureEntry, secureEntry { - setAsSecureTextEntry(true) - } + setAsSecureTextEntry(model.secureEntry) for digitBox in digitBoxes { MVMCoreUICommonViewsUtility.addDismissToolbar(digitBox.digitField, delegate: delegateObject as? UITextFieldDelegate) diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift index a798eebb..3b139e9b 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift @@ -16,8 +16,8 @@ return "digitTextField" } - public var digits: Int? - public var secureEntry: Bool? + public var digits: Int = 4 + public var secureEntry: Bool = false //-------------------------------------------------- // MARK: - Keys @@ -35,8 +35,8 @@ 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) - secureEntry = try typeContainer.decodeIfPresent(Bool.self, forKey: .secureEntry) + 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 { diff --git a/MVMCoreUI/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atoms/TextFields/EntryField.swift index 57d1b0bf..e70a2df0 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryField.swift @@ -248,29 +248,12 @@ import UIKit entryFieldContainer.setWithModel(model, delegateObject, additionalData) - if let title = model.title { - self.title = title - } - - if let isDisabled = model.isDisabled { - self.isEnabled = isDisabled - } - - if let feedback = model.feedback { - self.feedback = feedback - } - - if let errorMessage = model.errorMessage { - self.errorMessage = errorMessage - } - - if let isLocked = model.isLocked { - self.isLocked = isLocked - } - - if let isSelected = model.isSelected { - self.isSelected = isSelected - } + title = model.title + isEnabled = model.isEnabled + feedback = model.feedback + errorMessage = model.errorMessage + isLocked = model.isLocked + isSelected = model.isSelected if let fieldKey = model.fieldKey { self.fieldKey = fieldKey diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index dbf240ee..adb2b58c 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -21,11 +21,10 @@ import Foundation public var backgroundColor: Color? public var title: String? public var feedback: String? - public var errorMessage: String? - public var isDisabled: Bool? - public var isLocked: Bool? - public var isSelected: Bool? - + public var errorMessage: String = "" + public var isEnabled: Bool = true + public var isLocked: Bool = false + public var isSelected: Bool = false public var fieldKey: String? public var isValid: Bool? public var isRequired: Bool? @@ -37,7 +36,7 @@ import Foundation private enum CodingKeys: String, CodingKey { case backgroundColor case title - case isDisabled + case isEnabled case feedback case errorMessage = "errorMsg" case isLocked @@ -56,10 +55,10 @@ import Foundation 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) - isDisabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isDisabled) - isLocked = try typeContainer.decodeIfPresent(Bool.self, forKey: .isLocked) - isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected) + 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) ?? false + isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected) ?? false fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) isValid = try typeContainer.decodeIfPresent(Bool.self, forKey: .isValid) } @@ -70,7 +69,7 @@ import Foundation try container.encodeIfPresent(title, forKey: .title) try container.encodeIfPresent(feedback, forKey: .feedback) try container.encodeIfPresent(errorMessage, forKey: .errorMessage) - try container.encodeIfPresent(isDisabled, forKey: .isDisabled) + try container.encodeIfPresent(isEnabled, forKey: .isEnabled) try container.encodeIfPresent(isLocked, forKey: .isLocked) try container.encodeIfPresent(isSelected, forKey: .isSelected) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) diff --git a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift index 440ad5fc..962ff89b 100644 --- a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift @@ -115,10 +115,14 @@ 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] } diff --git a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift index e1313086..a12d6b80 100644 --- a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift @@ -16,28 +16,4 @@ } public var options: [String]? - - //-------------------------------------------------- - // MARK: - Keys - //-------------------------------------------------- - - private enum CodingKeys: String, CodingKey { - 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.decodeIfPresent([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.encodeIfPresent(options, forKey: .options) - } } diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index f4381faf..1230a485 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -286,13 +286,9 @@ import UIKit textColor.disabled = disabledTextColor.uiColor } - if let text = model.text { - self.text = text - } + text = model.text + placeholder = model.placeholder - if let placeholder = model.placeholder { - self.placeholder = placeholder - } switch model.type { case "password": diff --git a/MVMCoreUI/Containers/views/EntryFieldContainer.swift b/MVMCoreUI/Containers/views/EntryFieldContainer.swift new file mode 100644 index 00000000..3f80006a --- /dev/null +++ b/MVMCoreUI/Containers/views/EntryFieldContainer.swift @@ -0,0 +1,293 @@ +// +// EntryFieldContainer.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 11/12/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + + +@objcMembers open class EntryFieldContainer: View { + //-------------------------------------------------- + // MARK: - Drawing Properties + //-------------------------------------------------- + + /// The bottom border line. Height is dynamic based on scenario. + public var bottomBar: CAShapeLayer? = { + let layer = CAShapeLayer() + layer.backgroundColor = UIColor.black.cgColor + layer.drawsAsynchronously = true + layer.anchorPoint = CGPoint(x: 0.5, y: 1.0); + return layer + }() + + /// Total control over the drawn top, bottom, left and right borders. + public var disableAllBorders = false { + didSet { + bottomBar?.isHidden = disableAllBorders + } + } + + private(set) var fieldState: FieldState = .original { + didSet (oldState) { + // Will not update if new state is the same as old. + if fieldState != oldState { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + + self.fieldState.setStateUI(for: self) + } + } + } + } + + /// Determines if the top, left, and right borders should be drawn. + private var hideBorders = false + + public var borderStrokeColor: UIColor = .mfSilver() + private var borderPath: UIBezierPath = UIBezierPath() + + //-------------------------------------------------- + // MARK: - Property Observers + //-------------------------------------------------- + + private var _isEnabled: Bool = true + private var _showError: Bool = false + private var _isLocked: Bool = false + private var _isSelected: Bool = false + + public var isEnabled: Bool { + get { return _isEnabled } + set (enabled) { + + _isEnabled = enabled + _isLocked = false + _isSelected = false + _showError = false + + fieldState = enabled ? .original : .disabled + } + } + + public var showError: Bool { + get { return _showError } + set (error) { + + _showError = error + _isEnabled = true + _isLocked = false + _isSelected = false + + fieldState = error ? .error : .original + } + } + + public var isLocked: Bool { + get { return _isLocked } + set (locked) { + + _isLocked = locked + _isEnabled = true + _isSelected = false + _showError = false + + fieldState = locked ? .locked : .original + } + } + + public var isSelected: Bool { + get { return _isSelected } + set (selected) { + + _isSelected = selected + _isLocked = false + _isEnabled = true + + if _showError { + fieldState = selected ? .selectedError : .error + } else { + fieldState = selected ? .selected : .original + } + } + } + + //-------------------------------------------------- + // MARK: - Delegate + //-------------------------------------------------- + + /// Holds reference to delegateObject to inform molecular tableView of an update. + var delegateObject: MVMCoreUIDelegateObject? + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + + open override func layoutSubviews() { + super.layoutSubviews() + + refreshUI(bottomBarSize: showError ? 4 : 1) + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + + refreshUI() + } + + /// This handles the top, left, and right border lines. + open override func draw(_ rect: CGRect) { + super.draw(rect) + + borderPath.removeAllPoints() + + if !disableAllBorders && !hideBorders { + // Brings the other half of the line inside the view to prevent cropping. + let origin = bounds.origin + let size = frame.size + let insetLean: CGFloat = 0.5 + borderPath.lineWidth = 1 + + borderPath.move(to: CGPoint(x: origin.x + insetLean, y: origin.y + size.height)) + borderPath.addLine(to: CGPoint(x: origin.x + insetLean, y: origin.y + insetLean)) + borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + insetLean)) + borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + size.height)) + + borderStrokeColor.setStroke() + borderPath.stroke() + } + } + + override open func setupView() { + super.setupView() + + isAccessibilityElement = false + isOpaque = false + + if let bottomBar = bottomBar { + layer.addSublayer(bottomBar) + } + } + + //-------------------------------------------------- + // MARK: - Draw States + //-------------------------------------------------- + + public enum FieldState { + case original + case error + case selectedError + case selected + case locked + case disabled + + public func setStateUI(for formField: EntryFieldContainer) { + + switch self { + case .original: + formField.originalUI() + + case .error: + formField.errorUI() + + case .selectedError: + formField.selectedErrorUI() + + case .selected: + formField.selectedUI() + + case .locked: + formField.lockedUI() + + case .disabled: + formField.disabledUI() + } + } + } + + open func originalUI() { + + isUserInteractionEnabled = true + hideBorders = false + borderStrokeColor = .mfSilver() + bottomBar?.backgroundColor = UIColor.black.cgColor + refreshUI(bottomBarSize: 1) + } + + open func errorUI() { + + isUserInteractionEnabled = true + hideBorders = false + borderStrokeColor = .mfPumpkin() + bottomBar?.backgroundColor = UIColor.mfPumpkin().cgColor + refreshUI(bottomBarSize: 4) + } + + open func selectedErrorUI() { + + isUserInteractionEnabled = true + hideBorders = false + borderStrokeColor = .black + bottomBar?.backgroundColor = UIColor.mfPumpkin().cgColor + refreshUI(bottomBarSize: 4) + } + + open func selectedUI() { + + isUserInteractionEnabled = true + hideBorders = false + borderStrokeColor = .black + bottomBar?.backgroundColor = UIColor.black.cgColor + refreshUI(bottomBarSize: 1) + } + + open func lockedUI() { + + isUserInteractionEnabled = false + hideBorders = true + borderStrokeColor = .clear + bottomBar?.backgroundColor = UIColor.clear.cgColor + refreshUI(bottomBarSize: 1) + } + + open func disabledUI() { + + isUserInteractionEnabled = false + hideBorders = false + borderStrokeColor = .mfSilver() + bottomBar?.backgroundColor = UIColor.mfSilver().cgColor + refreshUI(bottomBarSize: 1) + } + + open func refreshUI(bottomBarSize: CGFloat? = nil) { + + if !disableAllBorders { + let size: CGFloat = bottomBarSize ?? (showError ? 4 : 1) + bottomBar?.frame = CGRect(x: 0, y: bounds.height - size, width: bounds.width, height: size) + + delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) + setNeedsDisplay() + layoutIfNeeded() + } + } + + //-------------------------------------------------- + // MARK: - MVMCoreUIMoleculeViewProtocol + //-------------------------------------------------- + + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.setWithModel(model, delegateObject, additionalData) + self.delegateObject = delegateObject + } +} + +extension EntryFieldContainer { + + override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + self.delegateObject = delegateObject + + guard let dictionary = json, !dictionary.isEmpty else { return } + } +} diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index abf6f711..bf67a5bc 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -9,21 +9,25 @@ import UIKit @objcMembers public class DropDownFilterTableViewCell: TableViewCell { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- var dropDownListItemModel: DropDownListItemModel? let dropDown = ItemDropdownEntryField() var delegateObject: MVMCoreUIDelegateObject? var previousIndex = NSNotFound - var dropDownSelectionObservation: NSKeyValueObservation? + //-------------------------------------------------- // MARK: - MFViewProtocol + //-------------------------------------------------- + override public func setupView() { super.setupView() + guard dropDown.superview == nil else { return } - dropDown.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(dropDown) - NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: dropDown, useMargins: true).values)) dropDown.observeDropdownChange = { [weak self] oldValue, newValue in diff --git a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift index 28bc373b..9b9a66f1 100644 --- a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift @@ -9,6 +9,7 @@ import Foundation @objcMembers public class DropDownListItemModel: ContainerModel, ListItemModelProtocol { + public static var identifier: String = "dropDownListItem" public var molecules: [[ListItemModelProtocol]] public var dropDown: ItemDropdownEntryFieldModel @@ -33,9 +34,11 @@ import Foundation let typeContainer = try decoder.container(keyedBy: CodingKeys.self) 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) } From 83d5721e683c8675c494b7e7d8c78d2584cd2bde Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 23 Jan 2020 19:59:05 -0500 Subject: [PATCH 08/25] temp fix for arch issue --- .../BaseDropdownEntryFieldModel.swift | 8 +++ .../DateDropdownEntryFieldModel.swift | 2 +- .../TextFields/DigitEntryFieldModel.swift | 4 +- .../Atoms/TextFields/EntryFieldModel.swift | 8 +-- .../TextFields/ItemDropdownEntryField.swift | 8 ++- .../ItemDropdownEntryFieldModel.swift | 26 +++++++- .../MFViewController+Model.swift | 8 +++ .../Items/DropDownFilterTableViewCell.swift | 36 +++++------ .../Items/DropDownListItemModel.swift | 35 ++++++++++- .../ModelMoleculeDelegateProtocol.swift | 8 ++- .../Templates/MoleculeListTemplate.swift | 59 +++++++++++++++++++ 11 files changed, 171 insertions(+), 31 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift index 3dffa669..1fefd42f 100644 --- a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift @@ -15,4 +15,12 @@ public override class var identifier: String { return "" } + + required public init(from decoder: Decoder) throws { + try super.init(from: decoder) + } + + public override func encode(to encoder: Encoder) throws { + try super.encode(to: encoder) + } } diff --git a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift index c226660b..4e916268 100644 --- a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift @@ -38,6 +38,6 @@ public override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(dateFormat, forKey: .dateFormat) + try container.encode(dateFormat, forKey: .dateFormat) } } diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift index 3b139e9b..46171e41 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift @@ -42,7 +42,7 @@ public override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeIfPresent(digits, forKey: .digits) - try container.encodeIfPresent(secureEntry, forKey: .secureEntry) + try container.encode(digits, forKey: .digits) + try container.encode(secureEntry, forKey: .secureEntry) } } diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index adb2b58c..14a57f4c 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -68,10 +68,10 @@ import Foundation try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(title, forKey: .title) try container.encodeIfPresent(feedback, forKey: .feedback) - try container.encodeIfPresent(errorMessage, forKey: .errorMessage) - try container.encodeIfPresent(isEnabled, forKey: .isEnabled) - try container.encodeIfPresent(isLocked, forKey: .isLocked) - try container.encodeIfPresent(isSelected, forKey: .isSelected) + 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) } diff --git a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift index 962ff89b..d1728b46 100644 --- a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryField.swift @@ -96,9 +96,11 @@ open class ItemDropdownEntryField: BaseDropdownEntryField { guard let model = model as? ItemDropdownEntryFieldModel else { return } - if let options = model.options { - pickerData = options - setPickerDelegates(delegate: self) + pickerData = model.options + setPickerDelegates(delegate: self) + + if let pickerView = pickerView { + self.pickerView(pickerView, didSelectRow: 0, inComponent: 0) } } } diff --git a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift index a12d6b80..b913f976 100644 --- a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift @@ -15,5 +15,29 @@ return "dropDown" } - public var options: [String]? + public var options: [String] = [] + + //-------------------------------------------------- + // MARK: - Keys + //-------------------------------------------------- + + private enum CodingKeys: String, CodingKey { + 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.decodeIfPresent([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(options, forKey: .options) + } } diff --git a/MVMCoreUI/BaseControllers/MFViewController+Model.swift b/MVMCoreUI/BaseControllers/MFViewController+Model.swift index f503d0b5..6cedf93c 100644 --- a/MVMCoreUI/BaseControllers/MFViewController+Model.swift +++ b/MVMCoreUI/BaseControllers/MFViewController+Model.swift @@ -33,6 +33,14 @@ extension MFViewController: MoleculeDelegateProtocol { @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 { diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index bf67a5bc..bc8edf18 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -19,47 +19,49 @@ import UIKit var previousIndex = NSNotFound //-------------------------------------------------- - // MARK: - MFViewProtocol + // MARK: - Lifecycle //-------------------------------------------------- override public func setupView() { super.setupView() guard dropDown.superview == nil else { return } - - contentView.addSubview(dropDown) - NSLayoutConstraint.activate(Array(NSLayoutConstraint.pinView(toSuperview: dropDown, useMargins: true).values)) - + addMolecule(dropDown) dropDown.observeDropdownChange = { [weak self] oldValue, newValue in guard newValue != oldValue, let self = self, - let options = self.dropDown.json?.optionalArrayForKey("options") as? [NSString], - let index = options.firstIndex(of: newValue as NSString), - let molecules = self.dropDownListItemModel?.molecules else { return } + let index = self.dropDown.pickerData.firstIndex(of: newValue), + let molecules = self.dropDownListItemModel?.molecules + else { return } - if self.previousIndex != NSNotFound { - self.delegateObject?.moleculeDelegate?.removeMolecules(molecules[self.previousIndex], sender: self, animation: .fade) + var json2d = [[[AnyHashable: Any]]]() + + for moleculeList in molecules { + var json1d = [[AnyHashable: Any]]() + for molecule in moleculeList { + json1d.append((molecule as? ListItemModel)!.toJSON()!) + } + json2d.append(json1d) } - self.delegateObject?.moleculeDelegate?.addMolecules(molecules[index], sender: self, animation: .fade) + if self.previousIndex != NSNotFound { + self.delegateObject?.moleculeDelegate?.removeMolecules(json2d[self.previousIndex], 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.setWithModel(dropDownListItemModel?.dropDown, delegateObject, additionalData) dropDown.observingTextFieldDelegate = delegateObject?.uiTextFieldDelegate as? ObservingTextFieldDelegate dropDown.uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate - dropDown.setWithModel(dropDownListItemModel, delegateObject, additionalData) } public override func reset() { diff --git a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift index 9b9a66f1..13af4278 100644 --- a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift @@ -9,6 +9,9 @@ import Foundation @objcMembers public class DropDownListItemModel: ContainerModel, ListItemModelProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- public static var identifier: String = "dropDownListItem" public var molecules: [[ListItemModelProtocol]] @@ -16,12 +19,37 @@ import Foundation 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 + } + } + //-------------------------------------------------- + // 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 molecules @@ -29,10 +57,14 @@ import Foundation 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]] + 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) { @@ -41,6 +73,7 @@ import Foundation backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) try super.init(from: decoder) + setDefaults() } public override func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift b/MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift index 11e8a154..8fe1caa5 100644 --- a/MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift +++ b/MVMCoreUI/OtherHandlers/ModelMoleculeDelegateProtocol.swift @@ -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 } diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index c21a770b..a7b8d6ba 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -146,6 +146,64 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } } + public override func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { + + var tmpMolecules = [ListItemModelProtocol]() + + molecules.forEach { molecule in + + let data = try? JSONSerialization.data(withJSONObject: molecule) + let decoder = JSONDecoder() + let listItemModel = try? decoder.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 molecules { + if let info = self.getMoleculeInfo(with: tmpMolecules as! ListItemModelProtocol) { + 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 + + let data = try? JSONSerialization.data(withJSONObject: molecule) + let decoder = JSONDecoder() + let listItemModel = try? decoder.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 { @@ -164,6 +222,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol self.view.layoutIfNeeded() } } + public func removeMolecules(_ molecules: [ListItemModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) { var indexPaths: [IndexPath] = [] //TODO: cehck for molecule protocola eqality From c5e80d602efbf52ddbae597391a650c490dc9799 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 23 Jan 2020 21:04:48 -0500 Subject: [PATCH 09/25] temp fix for arch issue --- MVMCoreUI/Molecules/Items/ListItemModel.swift | 2 ++ MVMCoreUI/Templates/MoleculeListTemplate.swift | 7 +++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Molecules/Items/ListItemModel.swift b/MVMCoreUI/Molecules/Items/ListItemModel.swift index 5356ce25..ff9f056d 100644 --- a/MVMCoreUI/Molecules/Items/ListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/ListItemModel.swift @@ -18,6 +18,7 @@ import MVMCore public var style: String? = "standard" private enum CodingKeys: String, CodingKey { + case moleculeName case backgroundColor case action case hideArrow @@ -62,6 +63,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) diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index a7b8d6ba..c4542898 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -153,8 +153,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol molecules.forEach { molecule in let data = try? JSONSerialization.data(withJSONObject: molecule) - let decoder = JSONDecoder() - let listItemModel = try? decoder.decode(ListItemModel.self, from: data!) + let listItemModel = try? JSONDecoder().decode(ListItemModel.self, from: data!) tmpMolecules.append(listItemModel!) } @@ -162,8 +161,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol 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: tmpMolecules as! ListItemModelProtocol) { + 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) From 6139f31e54f791b5e5782d6cfb4d54dbc28873ce Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 23 Jan 2020 22:42:19 -0500 Subject: [PATCH 10/25] wring label --- MVMCoreUI/Atoms/Views/Label/LabelModel.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift index b7feefae..b0ad442f 100644 --- a/MVMCoreUI/Atoms/Views/Label/LabelModel.swift +++ b/MVMCoreUI/Atoms/Views/Label/LabelModel.swift @@ -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) From 304b4cbc4c38d7163ba7ab108c58c0c9d216df13 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 09:41:34 -0500 Subject: [PATCH 11/25] models encode properly --- MVMCoreUI/Atoms/Buttons/ButtonModel.swift | 5 +++++ .../Atoms/TextFields/DateDropdownEntryFieldModel.swift | 2 ++ MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift | 2 ++ .../Atoms/TextFields/ItemDropdownEntryFieldModel.swift | 2 ++ MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift | 2 ++ MVMCoreUI/Molecules/FooterModel.swift | 2 ++ MVMCoreUI/Molecules/Items/AccordionListItemModel.swift | 4 ++++ MVMCoreUI/Molecules/Items/CarouselItemModel.swift | 2 ++ MVMCoreUI/Molecules/Items/DropDownListItemModel.swift | 3 ++- MVMCoreUI/Molecules/Items/ListItemModel.swift | 4 ++++ MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift | 2 ++ MVMCoreUI/Molecules/Items/TabsListItemModel.swift | 2 ++ .../VerticalCombinationViews/HeadlineBodyModel.swift | 1 + .../Lists/NumberedListModel.swift | 1 + .../Lists/UnOrderedListModel.swift | 1 + MVMCoreUI/Templates/MoleculeListTemplate.swift | 9 +++------ 16 files changed, 37 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index c9a7f2f8..61e3ca3e 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -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) diff --git a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift index 4e916268..cdafc9e9 100644 --- a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryFieldModel.swift @@ -22,6 +22,7 @@ //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case moleculeName case dateFormat } @@ -38,6 +39,7 @@ 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) } } diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift index 46171e41..0291066c 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryFieldModel.swift @@ -24,6 +24,7 @@ //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case moleculeName case digits case secureEntry } @@ -42,6 +43,7 @@ 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) } diff --git a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift index b913f976..c247a644 100644 --- a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift @@ -22,6 +22,7 @@ //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case moleculeName case options } @@ -38,6 +39,7 @@ 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) } } diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift index d890d918..27b0e933 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift @@ -28,6 +28,7 @@ //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case moleculeName case text case placeholder case enabledTextColor @@ -54,6 +55,7 @@ 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) diff --git a/MVMCoreUI/Molecules/FooterModel.swift b/MVMCoreUI/Molecules/FooterModel.swift index 9f7b002f..d61d1194 100644 --- a/MVMCoreUI/Molecules/FooterModel.swift +++ b/MVMCoreUI/Molecules/FooterModel.swift @@ -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) } } diff --git a/MVMCoreUI/Molecules/Items/AccordionListItemModel.swift b/MVMCoreUI/Molecules/Items/AccordionListItemModel.swift index 5d88b913..c8124b3c 100644 --- a/MVMCoreUI/Molecules/Items/AccordionListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/AccordionListItemModel.swift @@ -17,7 +17,9 @@ class AccordionListItemModel: MoleculeContainerModel, ListItemModelProtocol { public var line: LineModel? private enum CodingKeys: String, CodingKey { + case moleculeName case molecules + case molecule case backgroundColor case hideLineWhenExpanded case hideArrow @@ -38,9 +40,11 @@ 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) try container.encodeIfPresent(line, forKey: .line) + try container.encodeModel(molecule, forKey: .molecule) } } diff --git a/MVMCoreUI/Molecules/Items/CarouselItemModel.swift b/MVMCoreUI/Molecules/Items/CarouselItemModel.swift index 8f7eea64..726d4846 100644 --- a/MVMCoreUI/Molecules/Items/CarouselItemModel.swift +++ b/MVMCoreUI/Molecules/Items/CarouselItemModel.swift @@ -19,6 +19,7 @@ import Foundation case backgroundColor case peakingUI case peakingArrowColor + case molecule } required public init(from decoder: Decoder) throws { @@ -35,5 +36,6 @@ import Foundation try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(peakingUI, forKey: .peakingUI) try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor) + try container.encodeModel(molecule, forKey: .molecule) } } diff --git a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift index 13af4278..5120eb0f 100644 --- a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift @@ -53,6 +53,7 @@ import Foundation private enum CodingKeys: String, CodingKey { case molecules + case molecule case dropDown case line case backgroundColor @@ -79,7 +80,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.encodeModels2D(molecules, forKey: .molecules) + try container.encodeModels2D(molecules, forKey: .molecules) try container.encode(dropDown, forKey: .dropDown) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(line, forKey: .line) diff --git a/MVMCoreUI/Molecules/Items/ListItemModel.swift b/MVMCoreUI/Molecules/Items/ListItemModel.swift index ff9f056d..a5490651 100644 --- a/MVMCoreUI/Molecules/Items/ListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/ListItemModel.swift @@ -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? @@ -20,6 +21,7 @@ import MVMCore private enum CodingKeys: String, CodingKey { case moleculeName case backgroundColor + case molecule case action case hideArrow case line @@ -63,6 +65,8 @@ import MVMCore public override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) + try container.encodeModel(molecule, forKey: .molecule) + try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModelIfPresent(action, forKey: .action) diff --git a/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift b/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift index 970f66f6..4731ef34 100644 --- a/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift +++ b/MVMCoreUI/Molecules/Items/MoleculeStackItemModel.swift @@ -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) diff --git a/MVMCoreUI/Molecules/Items/TabsListItemModel.swift b/MVMCoreUI/Molecules/Items/TabsListItemModel.swift index 13dd09e7..0158774a 100644 --- a/MVMCoreUI/Molecules/Items/TabsListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/TabsListItemModel.swift @@ -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) diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift index fc22f864..62199654 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/HeadlineBodyModel.swift @@ -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? diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift index 53bec673..795eec7d 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/NumberedListModel.swift @@ -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 { diff --git a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift index 56281c43..87d57927 100644 --- a/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift +++ b/MVMCoreUI/Molecules/VerticalCombinationViews/Lists/UnOrderedListModel.swift @@ -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 { diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index c4542898..d3a9f779 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -151,10 +151,10 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol var tmpMolecules = [ListItemModelProtocol]() molecules.forEach { molecule in - let data = try? JSONSerialization.data(withJSONObject: molecule) let listItemModel = try? JSONDecoder().decode(ListItemModel.self, from: data!) - +  let jsonData = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) + let json = String(data: data!, encoding: String.Encoding.utf8) tmpMolecules.append(listItemModel!) } @@ -180,11 +180,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol var tmpMolecules = [ListItemModelProtocol]() molecules.forEach { molecule in - let data = try? JSONSerialization.data(withJSONObject: molecule) - let decoder = JSONDecoder() - let listItemModel = try? decoder.decode(ListItemModel.self, from: data!) - + let listItemModel = try? JSONDecoder().decode(ListItemModel.self, from: data!) tmpMolecules.append(listItemModel!) } From 86f60bccf8a400b312c57d5ea3a66951bf2d359a Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 10:11:42 -0500 Subject: [PATCH 12/25] adding height override --- MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index bc8edf18..0826b4b5 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -68,4 +68,8 @@ import UIKit super.reset() bottomSeparatorView?.setStyle(.none) } + + public override static func estimatedHeight(forRow molecule: MoleculeModelProtocol?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { + return 80 + } } From f43e018e2117abf5ccb3c4a4c8f6bebc22cc64fe Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 10:38:38 -0500 Subject: [PATCH 13/25] model reuse --- MVMCoreUI/Containers/views/EntryFieldContainer.swift | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Containers/views/EntryFieldContainer.swift b/MVMCoreUI/Containers/views/EntryFieldContainer.swift index 3f80006a..96a51a8f 100644 --- a/MVMCoreUI/Containers/views/EntryFieldContainer.swift +++ b/MVMCoreUI/Containers/views/EntryFieldContainer.swift @@ -118,7 +118,7 @@ import UIKit //-------------------------------------------------- /// Holds reference to delegateObject to inform molecular tableView of an update. - var delegateObject: MVMCoreUIDelegateObject? + weak var delegateObject: MVMCoreUIDelegateObject? //-------------------------------------------------- // MARK: - Lifecycle @@ -271,17 +271,9 @@ import UIKit layoutIfNeeded() } } - - //-------------------------------------------------- - // MARK: - MVMCoreUIMoleculeViewProtocol - //-------------------------------------------------- - - open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) - self.delegateObject = delegateObject - } } +// MARK:- MVMCoreUIMoleculeViewProtocol extension EntryFieldContainer { override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { From af7e813e1842eda760e283aee65bee91f226a096 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 10:41:38 -0500 Subject: [PATCH 14/25] model reuse again --- MVMCoreUI/Atoms/TextFields/TextEntryField.swift | 13 +++---------- .../Containers/views/EntryFieldContainer.swift | 12 ++++++++++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index 1230a485..66f3ecd4 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -277,19 +277,12 @@ import UIKit guard let model = model as? TextEntryFieldModel else { return } FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) - - if let enabledTextColor = model.enabledTextColor { - textColor.enabled = enabledTextColor.uiColor - } - - if let disabledTextColor = model.disabledTextColor { - textColor.disabled = disabledTextColor.uiColor - } - + + textColor.enabled = model.enabledTextColor?.uiColor + textColor.disabled = model.disabledTextColor?.uiColor text = model.text placeholder = model.placeholder - switch model.type { case "password": textField.isSecureTextEntry = true diff --git a/MVMCoreUI/Containers/views/EntryFieldContainer.swift b/MVMCoreUI/Containers/views/EntryFieldContainer.swift index 96a51a8f..3f80006a 100644 --- a/MVMCoreUI/Containers/views/EntryFieldContainer.swift +++ b/MVMCoreUI/Containers/views/EntryFieldContainer.swift @@ -118,7 +118,7 @@ import UIKit //-------------------------------------------------- /// Holds reference to delegateObject to inform molecular tableView of an update. - weak var delegateObject: MVMCoreUIDelegateObject? + var delegateObject: MVMCoreUIDelegateObject? //-------------------------------------------------- // MARK: - Lifecycle @@ -271,9 +271,17 @@ import UIKit layoutIfNeeded() } } + + //-------------------------------------------------- + // MARK: - MVMCoreUIMoleculeViewProtocol + //-------------------------------------------------- + + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.setWithModel(model, delegateObject, additionalData) + self.delegateObject = delegateObject + } } -// MARK:- MVMCoreUIMoleculeViewProtocol extension EntryFieldContainer { override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { From 851d5b57ff3c70940175703b8f06c03023c2a9f0 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 10:58:03 -0500 Subject: [PATCH 15/25] remvoe explicit unwrapping --- .../Items/DropDownFilterTableViewCell.swift | 4 +- .../Templates/MoleculeListTemplate.swift | 60 +++++++++---------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index 0826b4b5..ed2294a5 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -40,7 +40,9 @@ import UIKit for moleculeList in molecules { var json1d = [[AnyHashable: Any]]() for molecule in moleculeList { - json1d.append((molecule as? ListItemModel)!.toJSON()!) + if let moleculeDictionary = (molecule as? ListItemModel)?.toJSON() { + json1d.append(moleculeDictionary) + } } json2d.append(json1d) } diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 159589eb..75ef7d2f 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -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 @@ -145,17 +145,15 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol } } } - + public override func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { var tmpMolecules = [ListItemModelProtocol]() molecules.forEach { molecule in - let data = try? JSONSerialization.data(withJSONObject: molecule) - let listItemModel = try? JSONDecoder().decode(ListItemModel.self, from: data!) -  let jsonData = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) - let json = String(data: data!, encoding: String.Encoding.utf8) - tmpMolecules.append(listItemModel!) + if let data = try? JSONSerialization.data(withJSONObject: molecule), let listItemModel = try? JSONDecoder().decode(ListItemModel.self, from: data) { + tmpMolecules.append(listItemModel) + } } DispatchQueue.main.async { @@ -180,9 +178,9 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol var tmpMolecules = [ListItemModelProtocol]() molecules.forEach { molecule in - let data = try? JSONSerialization.data(withJSONObject: molecule) - let listItemModel = try? JSONDecoder().decode(ListItemModel.self, from: data!) - tmpMolecules.append(listItemModel!) + if let data = try? JSONSerialization.data(withJSONObject: molecule), let listItemModel = try? JSONDecoder().decode(ListItemModel.self, from: data) { + tmpMolecules.append(listItemModel) + } } var indexPaths: [IndexPath] = [] @@ -202,21 +200,21 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol 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) { @@ -241,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) } From f41ad328d2f783f8cc739342d319450eed13aafa Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Fri, 24 Jan 2020 11:44:48 -0500 Subject: [PATCH 16/25] remove conflict files --- .../Items/DropDownListItemModel.swift.orig | 55 ------------------- 1 file changed, 55 deletions(-) delete mode 100644 MVMCoreUI/Molecules/Items/DropDownListItemModel.swift.orig diff --git a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift.orig b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift.orig deleted file mode 100644 index e702000b..00000000 --- a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift.orig +++ /dev/null @@ -1,55 +0,0 @@ -// -// DropDownListItemModel.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 12/12/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - -@objcMembers public class DropDownListItemModel: ContainerModel, ListItemModelProtocol { - public static var identifier: String = "dropDownListItem" - public var molecules: [[ListItemModelProtocol]] - public var dropDown: ItemDropdownEntryFieldModel - public var backgroundColor: Color? - public var line: LineModel? = LineModel(type: .none) - public var hideArrow: Bool? = true - -<<<<<<< HEAD - public init(molecule: MoleculeModelProtocol, molecules: [[ListItemModelProtocol]], dropDown: ItemDropdownEntryFieldModel) { -======= - public init(molecules: [[ListItemModelProtocol]], dropDown: DropDownModel) { ->>>>>>> remotes/origin/feature/coding - self.molecules = molecules - self.dropDown = dropDown - super.init() - } - - private enum CodingKeys: String, CodingKey { - case molecules - case dropDown - case line - case backgroundColor - } - - 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(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) - } - - 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(dropDown, forKey: .dropDown) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - try container.encodeIfPresent(line, forKey: .line) - } -} From 451e28cdfd4cf315aeb5b362016a200f30200093 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 11:47:25 -0500 Subject: [PATCH 17/25] removed conflict file --- .../Items/DropDownListItemModel.swift.orig | 55 ------------------- 1 file changed, 55 deletions(-) delete mode 100644 MVMCoreUI/Molecules/Items/DropDownListItemModel.swift.orig diff --git a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift.orig b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift.orig deleted file mode 100644 index e702000b..00000000 --- a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift.orig +++ /dev/null @@ -1,55 +0,0 @@ -// -// DropDownListItemModel.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 12/12/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - -@objcMembers public class DropDownListItemModel: ContainerModel, ListItemModelProtocol { - public static var identifier: String = "dropDownListItem" - public var molecules: [[ListItemModelProtocol]] - public var dropDown: ItemDropdownEntryFieldModel - public var backgroundColor: Color? - public var line: LineModel? = LineModel(type: .none) - public var hideArrow: Bool? = true - -<<<<<<< HEAD - public init(molecule: MoleculeModelProtocol, molecules: [[ListItemModelProtocol]], dropDown: ItemDropdownEntryFieldModel) { -======= - public init(molecules: [[ListItemModelProtocol]], dropDown: DropDownModel) { ->>>>>>> remotes/origin/feature/coding - self.molecules = molecules - self.dropDown = dropDown - super.init() - } - - private enum CodingKeys: String, CodingKey { - case molecules - case dropDown - case line - case backgroundColor - } - - 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(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) - } - - 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(dropDown, forKey: .dropDown) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - try container.encodeIfPresent(line, forKey: .line) - } -} From 7019bdaa7802f3170999440e2ec1a8b1bb009db8 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 11:54:23 -0500 Subject: [PATCH 18/25] no longer needed. --- .../MVMCoreUIMoleculeMappingObject.m | 50 +------------------ 1 file changed, 1 insertion(+), 49 deletions(-) diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m index e0c83569..ccaa9115 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIMoleculeMappingObject.m @@ -25,55 +25,7 @@ static dispatch_once_t onceToken; static NSMutableDictionary *mapping; dispatch_once(&onceToken, ^{ - mapping = [@{ - @"label": Label.class, - @"line": Line.class, - @"button": PrimaryButton.class, - @"link": MFTextButton.class, - @"header": HeaderView.class, - @"twoButtonView": TwoButtonView.class, - @"footer": FooterView.class, - @"caretView": CaretView.class, - @"caretLink": CaretButton.class, - @"digitTextField": DigitEntryField.class, - @"textField": TextEntryField.class, - @"mdnEntryField": MdnEntryField.class, - @"dropDown": ItemDropdownEntryField.class, - @"dateDropdownEntryField": DateDropdownEntryField.class, - @"checkbox": Checkbox.class, - @"checkboxLabel": CheckboxWithLabelView.class, - @"cornerLabels" : CornerLabels.class, - @"progressBar": ProgressBar.class, - @"circleProgress": GraphView.class, - @"multiProgressBar": MultiProgress.class, - @"radioButton": RadioButton.class, - @"radioButtonLabel": RadioButtonLabel.class, - @"listItem": MoleculeTableViewCell.class, - @"accordionListItem": AccordionMoleculeTableViewCell.class, - @"toggle": Toggle.class, - @"leftRightLabelView": LeftRightLabelView.class, - @"actionDetailWithImage": ActionDetailWithImage.class, - @"image": MFLoadImageView.class, - @"moduleMolecule": ModuleMolecule.class, - @"headlineBody": HeadlineBody.class, - @"carousel": Carousel.class, - @"carouselItem": MoleculeCollectionViewCell.class, - @"barsPager": MVMCoreUIPageControl.class, - @"scroller": Scroller.class, - @"imageHeadlineBody": ImageHeadlineBody.class, - @"labelToggle": LabelSwitch.class, - @"headlineBodyToggle": HeadlineBodySwitch.class, - @"headlineBodyLink": HeadlineBodyTextButton.class, - @"headlineBodyLinkToggle": HeadlineBodyTextButtonSwitch.class, - @"tabsListItem": TabsTableViewCell.class, - @"dropDownListItem": DropDownFilterTableViewCell.class, - @"headlineBodyButton": HeadlineBodyButton.class, - @"stackItem": MoleculeStackItem.class, - @"eyebrowHeadlineBodyLink": EyebrowHeadlineBodyLink.class, - @"headlineBodyCaretLinkImage" : HeadLineBodyCaretLinkImage.class, - @"doughnutChart": DoughnutChartView.class, - @"headLineBodyCaretLinkImage" : HeadLineBodyCaretLinkImage.class - } mutableCopy]; + mapping = [@{} mutableCopy]; }); return mapping; } From e5948e05e5d80c26d653b556aebcdc92d5d0fbf8 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 12:33:22 -0500 Subject: [PATCH 19/25] pr fixes --- .../TextFields/BaseDropdownEntryField.swift | 4 +++- .../BaseDropdownEntryFieldModel.swift | 21 ++++++++++++++++++- .../TextFields/DateDropdownEntryField.swift | 2 +- .../Atoms/TextFields/EntryFieldModel.swift | 4 ++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryField.swift index 6cb0c96a..3290c744 100644 --- a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryField.swift @@ -72,7 +72,9 @@ import UIKit public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.setWithModel(model, delegateObject, additionalData) - dropDownCaretView.setWithModel(model, delegateObject, additionalData) + guard let model = model as? BaseDropdownEntryFieldModel else { return } + + dropDownCaretView.setWithModel(model.caretView, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift index 1fefd42f..e6e7cb24 100644 --- a/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/BaseDropdownEntryFieldModel.swift @@ -7,20 +7,39 @@ // @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) } } diff --git a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift index 7051239c..acfe0a42 100644 --- a/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DateDropdownEntryField.swift @@ -116,7 +116,7 @@ import UIKit guard let model = model as? DateDropdownEntryFieldModel else { return } - self.dateFormat = model.dateFormat + dateFormat = model.dateFormat } } diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index 14a57f4c..70c1c0e3 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -19,6 +19,7 @@ import Foundation } public var backgroundColor: Color? + public var moleculeName: String? public var title: String? public var feedback: String? public var errorMessage: String = "" @@ -34,6 +35,7 @@ import Foundation //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case moleculeName case backgroundColor case title case isEnabled @@ -52,6 +54,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) title = try typeContainer.decodeIfPresent(String.self, forKey: .title) feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) @@ -65,6 +68,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.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(title, forKey: .title) try container.encodeIfPresent(feedback, forKey: .feedback) From 7b8b2a059f1c6dc8e270d9d91eefa502bf41e696 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 12:43:38 -0500 Subject: [PATCH 20/25] no need for val --- MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift | 2 +- MVMCoreUI/Molecules/Items/AccordionListItemModel.swift | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift index c247a644..03c1cf40 100644 --- a/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/ItemDropdownEntryFieldModel.swift @@ -33,7 +33,7 @@ required public init(from decoder: Decoder) throws { try super.init(from: decoder) let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - options = try typeContainer.decodeIfPresent([String].self, forKey: .options) ?? [] + options = try typeContainer.decode([String].self, forKey: .options) } public override func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Molecules/Items/AccordionListItemModel.swift b/MVMCoreUI/Molecules/Items/AccordionListItemModel.swift index c8124b3c..0e2fa531 100644 --- a/MVMCoreUI/Molecules/Items/AccordionListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/AccordionListItemModel.swift @@ -19,7 +19,6 @@ class AccordionListItemModel: MoleculeContainerModel, ListItemModelProtocol { private enum CodingKeys: String, CodingKey { case moleculeName case molecules - case molecule case backgroundColor case hideLineWhenExpanded case hideArrow @@ -45,6 +44,5 @@ class AccordionListItemModel: MoleculeContainerModel, ListItemModelProtocol { try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(hideLineWhenExpanded, forKey: .hideLineWhenExpanded) try container.encodeIfPresent(line, forKey: .line) - try container.encodeModel(molecule, forKey: .molecule) } } From c250769620e7c0c1c48cbf2627c78c2e18c53319 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 13:20:02 -0500 Subject: [PATCH 21/25] using existing model encoding func --- .../Molecules/Items/CarouselItemModel.swift | 4 ++++ .../Items/DropDownFilterTableViewCell.swift | 17 +++-------------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/MVMCoreUI/Molecules/Items/CarouselItemModel.swift b/MVMCoreUI/Molecules/Items/CarouselItemModel.swift index 726d4846..4f4c3b58 100644 --- a/MVMCoreUI/Molecules/Items/CarouselItemModel.swift +++ b/MVMCoreUI/Molecules/Items/CarouselItemModel.swift @@ -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 @@ -24,6 +26,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) @@ -33,6 +36,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) diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index ed2294a5..46139a37 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -32,21 +32,10 @@ import UIKit guard newValue != oldValue, let self = self, let index = self.dropDown.pickerData.firstIndex(of: newValue), - let molecules = self.dropDownListItemModel?.molecules + let dropListItemJSON = self.dropDownListItemModel.toJSON(), + let json2d = dropListItemJSON.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]] else { return } - - var json2d = [[[AnyHashable: Any]]]() - - for moleculeList in molecules { - var json1d = [[AnyHashable: Any]]() - for molecule in moleculeList { - if let moleculeDictionary = (molecule as? ListItemModel)?.toJSON() { - json1d.append(moleculeDictionary) - } - } - json2d.append(json1d) - } - + if self.previousIndex != NSNotFound { self.delegateObject?.moleculeDelegate?.removeMolecules(json2d[self.previousIndex], sender: self, animation: .fade) } From 11aaedfa6b6b54d54e2a979ee65ee7cf81daf14c Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 13:25:59 -0500 Subject: [PATCH 22/25] pr fixes --- MVMCoreUI/Molecules/Items/CarouselItemModel.swift | 2 -- MVMCoreUI/Molecules/Items/DropDownListItemModel.swift | 3 ++- MVMCoreUI/Molecules/Items/ListItemModel.swift | 3 --- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Molecules/Items/CarouselItemModel.swift b/MVMCoreUI/Molecules/Items/CarouselItemModel.swift index 4f4c3b58..f2c88e9b 100644 --- a/MVMCoreUI/Molecules/Items/CarouselItemModel.swift +++ b/MVMCoreUI/Molecules/Items/CarouselItemModel.swift @@ -21,7 +21,6 @@ import Foundation case backgroundColor case peakingUI case peakingArrowColor - case molecule } required public init(from decoder: Decoder) throws { @@ -40,6 +39,5 @@ import Foundation try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(peakingUI, forKey: .peakingUI) try container.encodeIfPresent(peakingArrowColor, forKey: .peakingArrowColor) - try container.encodeModel(molecule, forKey: .molecule) } } diff --git a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift index 5120eb0f..35f69b51 100644 --- a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift @@ -52,8 +52,8 @@ import Foundation //-------------------------------------------------- private enum CodingKeys: String, CodingKey { + case moleculeName case molecules - case molecule case dropDown case line case backgroundColor @@ -80,6 +80,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.encodeModels2D(molecules, forKey: .molecules) try container.encode(dropDown, forKey: .dropDown) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) diff --git a/MVMCoreUI/Molecules/Items/ListItemModel.swift b/MVMCoreUI/Molecules/Items/ListItemModel.swift index a5490651..ffb0eb35 100644 --- a/MVMCoreUI/Molecules/Items/ListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/ListItemModel.swift @@ -21,7 +21,6 @@ import MVMCore private enum CodingKeys: String, CodingKey { case moleculeName case backgroundColor - case molecule case action case hideArrow case line @@ -65,8 +64,6 @@ import MVMCore public override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) - try container.encodeModel(molecule, forKey: .molecule) - try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeModelIfPresent(action, forKey: .action) From 3eb97d65c92a33264c0e0149228e7c461f0de144 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 15:06:45 -0500 Subject: [PATCH 23/25] fixing reuse error in setWithModel --- MVMCoreUI/Atoms/TextFields/EntryField.swift | 11 ++++++++--- MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift | 8 ++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atoms/TextFields/EntryField.swift index e70a2df0..82cc69f6 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryField.swift @@ -249,11 +249,16 @@ import UIKit entryFieldContainer.setWithModel(model, delegateObject, additionalData) title = model.title - isEnabled = model.isEnabled feedback = model.feedback errorMessage = model.errorMessage - isLocked = model.isLocked - isSelected = model.isSelected + 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 diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index 70c1c0e3..5f60081e 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -24,8 +24,8 @@ import Foundation public var feedback: String? public var errorMessage: String = "" public var isEnabled: Bool = true - public var isLocked: Bool = false - public var isSelected: Bool = false + public var isLocked: Bool? + public var isSelected: Bool? public var fieldKey: String? public var isValid: Bool? public var isRequired: Bool? @@ -60,8 +60,8 @@ import Foundation 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) ?? false - isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected) ?? false + 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) } From a3a3d4b66a914f1b0bcf1c12ac15c64af44b1e91 Mon Sep 17 00:00:00 2001 From: "Xinlei(Ryan) Pan" Date: Fri, 24 Jan 2020 15:14:02 -0500 Subject: [PATCH 24/25] add file back --- .../Views/EntryFieldContainer.swift | 293 ++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 MVMCoreUI/Containers/Views/EntryFieldContainer.swift diff --git a/MVMCoreUI/Containers/Views/EntryFieldContainer.swift b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift new file mode 100644 index 00000000..3f80006a --- /dev/null +++ b/MVMCoreUI/Containers/Views/EntryFieldContainer.swift @@ -0,0 +1,293 @@ +// +// EntryFieldContainer.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 11/12/19. +// Copyright © 2019 Verizon Wireless. All rights reserved. +// + +import UIKit + + +@objcMembers open class EntryFieldContainer: View { + //-------------------------------------------------- + // MARK: - Drawing Properties + //-------------------------------------------------- + + /// The bottom border line. Height is dynamic based on scenario. + public var bottomBar: CAShapeLayer? = { + let layer = CAShapeLayer() + layer.backgroundColor = UIColor.black.cgColor + layer.drawsAsynchronously = true + layer.anchorPoint = CGPoint(x: 0.5, y: 1.0); + return layer + }() + + /// Total control over the drawn top, bottom, left and right borders. + public var disableAllBorders = false { + didSet { + bottomBar?.isHidden = disableAllBorders + } + } + + private(set) var fieldState: FieldState = .original { + didSet (oldState) { + // Will not update if new state is the same as old. + if fieldState != oldState { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + + self.fieldState.setStateUI(for: self) + } + } + } + } + + /// Determines if the top, left, and right borders should be drawn. + private var hideBorders = false + + public var borderStrokeColor: UIColor = .mfSilver() + private var borderPath: UIBezierPath = UIBezierPath() + + //-------------------------------------------------- + // MARK: - Property Observers + //-------------------------------------------------- + + private var _isEnabled: Bool = true + private var _showError: Bool = false + private var _isLocked: Bool = false + private var _isSelected: Bool = false + + public var isEnabled: Bool { + get { return _isEnabled } + set (enabled) { + + _isEnabled = enabled + _isLocked = false + _isSelected = false + _showError = false + + fieldState = enabled ? .original : .disabled + } + } + + public var showError: Bool { + get { return _showError } + set (error) { + + _showError = error + _isEnabled = true + _isLocked = false + _isSelected = false + + fieldState = error ? .error : .original + } + } + + public var isLocked: Bool { + get { return _isLocked } + set (locked) { + + _isLocked = locked + _isEnabled = true + _isSelected = false + _showError = false + + fieldState = locked ? .locked : .original + } + } + + public var isSelected: Bool { + get { return _isSelected } + set (selected) { + + _isSelected = selected + _isLocked = false + _isEnabled = true + + if _showError { + fieldState = selected ? .selectedError : .error + } else { + fieldState = selected ? .selected : .original + } + } + } + + //-------------------------------------------------- + // MARK: - Delegate + //-------------------------------------------------- + + /// Holds reference to delegateObject to inform molecular tableView of an update. + var delegateObject: MVMCoreUIDelegateObject? + + //-------------------------------------------------- + // MARK: - Lifecycle + //-------------------------------------------------- + + open override func layoutSubviews() { + super.layoutSubviews() + + refreshUI(bottomBarSize: showError ? 4 : 1) + } + + open override func updateView(_ size: CGFloat) { + super.updateView(size) + + refreshUI() + } + + /// This handles the top, left, and right border lines. + open override func draw(_ rect: CGRect) { + super.draw(rect) + + borderPath.removeAllPoints() + + if !disableAllBorders && !hideBorders { + // Brings the other half of the line inside the view to prevent cropping. + let origin = bounds.origin + let size = frame.size + let insetLean: CGFloat = 0.5 + borderPath.lineWidth = 1 + + borderPath.move(to: CGPoint(x: origin.x + insetLean, y: origin.y + size.height)) + borderPath.addLine(to: CGPoint(x: origin.x + insetLean, y: origin.y + insetLean)) + borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + insetLean)) + borderPath.addLine(to: CGPoint(x: origin.x + size.width - insetLean, y: origin.y + size.height)) + + borderStrokeColor.setStroke() + borderPath.stroke() + } + } + + override open func setupView() { + super.setupView() + + isAccessibilityElement = false + isOpaque = false + + if let bottomBar = bottomBar { + layer.addSublayer(bottomBar) + } + } + + //-------------------------------------------------- + // MARK: - Draw States + //-------------------------------------------------- + + public enum FieldState { + case original + case error + case selectedError + case selected + case locked + case disabled + + public func setStateUI(for formField: EntryFieldContainer) { + + switch self { + case .original: + formField.originalUI() + + case .error: + formField.errorUI() + + case .selectedError: + formField.selectedErrorUI() + + case .selected: + formField.selectedUI() + + case .locked: + formField.lockedUI() + + case .disabled: + formField.disabledUI() + } + } + } + + open func originalUI() { + + isUserInteractionEnabled = true + hideBorders = false + borderStrokeColor = .mfSilver() + bottomBar?.backgroundColor = UIColor.black.cgColor + refreshUI(bottomBarSize: 1) + } + + open func errorUI() { + + isUserInteractionEnabled = true + hideBorders = false + borderStrokeColor = .mfPumpkin() + bottomBar?.backgroundColor = UIColor.mfPumpkin().cgColor + refreshUI(bottomBarSize: 4) + } + + open func selectedErrorUI() { + + isUserInteractionEnabled = true + hideBorders = false + borderStrokeColor = .black + bottomBar?.backgroundColor = UIColor.mfPumpkin().cgColor + refreshUI(bottomBarSize: 4) + } + + open func selectedUI() { + + isUserInteractionEnabled = true + hideBorders = false + borderStrokeColor = .black + bottomBar?.backgroundColor = UIColor.black.cgColor + refreshUI(bottomBarSize: 1) + } + + open func lockedUI() { + + isUserInteractionEnabled = false + hideBorders = true + borderStrokeColor = .clear + bottomBar?.backgroundColor = UIColor.clear.cgColor + refreshUI(bottomBarSize: 1) + } + + open func disabledUI() { + + isUserInteractionEnabled = false + hideBorders = false + borderStrokeColor = .mfSilver() + bottomBar?.backgroundColor = UIColor.mfSilver().cgColor + refreshUI(bottomBarSize: 1) + } + + open func refreshUI(bottomBarSize: CGFloat? = nil) { + + if !disableAllBorders { + let size: CGFloat = bottomBarSize ?? (showError ? 4 : 1) + bottomBar?.frame = CGRect(x: 0, y: bounds.height - size, width: bounds.width, height: size) + + delegateObject?.moleculeDelegate?.moleculeLayoutUpdated(self) + setNeedsDisplay() + layoutIfNeeded() + } + } + + //-------------------------------------------------- + // MARK: - MVMCoreUIMoleculeViewProtocol + //-------------------------------------------------- + + open override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + super.setWithModel(model, delegateObject, additionalData) + self.delegateObject = delegateObject + } +} + +extension EntryFieldContainer { + + override open func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + self.delegateObject = delegateObject + + guard let dictionary = json, !dictionary.isEmpty else { return } + } +} From a932e554d517432d8bec5ec69a7793c8ecee029e Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 24 Jan 2020 15:32:40 -0500 Subject: [PATCH 25/25] timing fix --- MVMCoreUI/Atoms/TextFields/DigitEntryField.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift index c7888041..9febf0c1 100644 --- a/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/DigitEntryField.swift @@ -329,7 +329,7 @@ import UIKit } public override func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - super.setWithModel(model, delegateObject, additionalData) + guard let model = model as? DigitEntryFieldModel else { return } @@ -340,6 +340,8 @@ import UIKit for digitBox in digitBoxes { MVMCoreUICommonViewsUtility.addDismissToolbar(digitBox.digitField, delegate: delegateObject as? UITextFieldDelegate) } + + super.setWithModel(model, delegateObject, additionalData) } }