From 3ec024ff270efbcd63aea24bf939590362ae3552 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 3 Mar 2020 20:32:57 -0500 Subject: [PATCH 01/27] changes --- MVMCoreUI.xcodeproj/project.pbxproj | 76 ++++++++++++ MVMCoreUI/Atoms/Buttons/ButtonModel.swift | 24 ++-- MVMCoreUI/Atoms/Buttons/PillButton.swift | 22 ++-- ...maryButton+MoleculeProtocolExtension.swift | 11 +- .../Atoms/TextFields/EntryFieldModel.swift | 22 +++- .../MFTextField+ModelExtension.swift | 116 ++++++++--------- .../Atoms/TextFields/MdnEntryField.swift | 42 +++---- .../Atoms/TextFields/TextEntryField.swift | 53 ++++---- .../TextFields/TextEntryFieldModel.swift | 1 - MVMCoreUI/Atoms/Views/Checkbox.swift | 91 +------------- MVMCoreUI/Atoms/Views/CheckboxModel.swift | 24 ++-- .../Atoms/Views/MFView+ModelExtension.swift | 2 +- .../Atoms/Views/MVMCoreUISwitch+Model.swift | 5 +- MVMCoreUI/Atoms/Views/RadioButton.swift | 62 +++------- MVMCoreUI/Atoms/Views/RadioButtonModel.swift | 15 ++- MVMCoreUI/Atoms/Views/Toggle.swift | 4 +- MVMCoreUI/Atoms/Views/ToggleModel.swift | 7 +- .../MFViewController+Form.swift | 22 ++++ MVMCoreUI/BaseControllers/MFViewController.m | 15 +-- .../FormValidator+FormParams.swift | 18 --- .../FormValidator+TextFields.swift | 117 +++++++++--------- MVMCoreUI/FormUIHelpers/FormValidator.swift | 106 ++++++++-------- .../New/FormActionFieldProtocol.swift | 15 +++ .../FormUIHelpers/New/FormFieldProtocol.swift | 15 +++ .../New/FormHolderProtocol.swift | 17 +++ .../FormUIHelpers/New/FormItemProtocol.swift | 13 ++ .../FormUIHelpers/New/FormProtocol.swift | 15 +++ .../New/Rules/FormGroupRule.swift | 49 ++++++++ .../New/Rules/RuleAnyModel.swift | 20 +++ .../New/Rules/RuleEqualsModel.swift | 20 +++ .../New/Rules/RuleRegexModel.swift | 19 +++ .../New/Rules/RuleRequiredModel.swift | 30 +++++ .../New/Rules/RuleValueChangeModel.swift | 20 +++ .../New/Rules/RulesProtocol.swift | 61 +++++++++ .../FormUIHelpers/New/ValidProtocol.swift | 15 +++ MVMCoreUI/Legacy/Views/MFTextField.m | 6 +- MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m | 4 +- MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m | 13 +- MVMCoreUI/Legacy/Views/PrimaryButton.m | 2 +- .../TemplateModelProtocol.swift | 2 +- MVMCoreUI/Molecules/RadioButtonLabel.swift | 32 ++--- .../Molecules/RadioButtonLabelModel.swift | 17 +++ .../RadioButtonSelectionHelper.swift | 37 +++--- .../MVMCoreUIDelegateObject.swift | 6 +- .../OtherHandlers/MoleculeObjectMapping.swift | 11 +- .../Templates/ListPageTemplateModel.swift | 7 ++ .../Templates/MoleculeListTemplate.swift | 7 +- .../Templates/MoleculeStackTemplate.swift | 5 + .../StackCenteredPageTemplateModel.swift | 27 ++++ .../Templates/StackPageTemplateModel.swift | 6 + MVMCoreUI/Templates/TemplateProtocol.swift | 8 +- .../ThreeLayerPageTemplateModel.swift | 4 + MVMCoreUI/Templates/ThreeLayerTemplate.swift | 5 + 53 files changed, 863 insertions(+), 500 deletions(-) create mode 100644 MVMCoreUI/BaseControllers/MFViewController+Form.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/FormActionFieldProtocol.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/FormItemProtocol.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/FormProtocol.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyModel.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/Rules/RuleValueChangeModel.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/ValidProtocol.swift create mode 100644 MVMCoreUI/Molecules/RadioButtonLabelModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 339735f3..d15c400c 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -15,7 +15,22 @@ 0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */; }; 011B58F023A2AA980085F53C /* ListItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */; }; 011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */; }; + 011D958524042432000E3791 /* RulesProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D958424042432000E3791 /* RulesProtocol.swift */; }; + 011D958724042492000E3791 /* FormFieldProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D958624042492000E3791 /* FormFieldProtocol.swift */; }; + 011D95892404249B000E3791 /* FormProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95882404249B000E3791 /* FormProtocol.swift */; }; + 011D959B240451E3000E3791 /* RuleRequiredModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959A240451E3000E3791 /* RuleRequiredModel.swift */; }; + 011D959D2404536F000E3791 /* RuleAnyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959C2404536F000E3791 /* RuleAnyModel.swift */; }; + 011D959F240453A1000E3791 /* RuleValueChangeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959E240453A1000E3791 /* RuleValueChangeModel.swift */; }; + 011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95A0240453D0000E3791 /* RuleEqualsModel.swift */; }; + 011D95A3240453F8000E3791 /* RuleRegexModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95A2240453F8000E3791 /* RuleRegexModel.swift */; }; + 011D95A5240455DC000E3791 /* FormGroupRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95A4240455DC000E3791 /* FormGroupRule.swift */; }; + 011D95A924057AC7000E3791 /* FormActionFieldProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95A824057AC7000E3791 /* FormActionFieldProtocol.swift */; }; + 011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95AA2405C553000E3791 /* FormItemProtocol.swift */; }; + 011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */; }; 011D95AF2407266E000E3791 /* RadioButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95AE2407266E000E3791 /* RadioButtonModel.swift */; }; + 011D9602240DA20A000E3791 /* ValidProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D9601240DA20A000E3791 /* ValidProtocol.swift */; }; + 011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */; }; + 011D9628240EFA1E000E3791 /* MFViewController+Form.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D9627240EFA1E000E3791 /* MFViewController+Form.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 */; }; @@ -370,7 +385,22 @@ 0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonSelectionHelper.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 = ""; }; + 011D958424042432000E3791 /* RulesProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RulesProtocol.swift; sourceTree = ""; }; + 011D958624042492000E3791 /* FormFieldProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormFieldProtocol.swift; sourceTree = ""; }; + 011D95882404249B000E3791 /* FormProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormProtocol.swift; sourceTree = ""; }; + 011D959A240451E3000E3791 /* RuleRequiredModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleRequiredModel.swift; sourceTree = ""; }; + 011D959C2404536F000E3791 /* RuleAnyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModel.swift; sourceTree = ""; }; + 011D959E240453A1000E3791 /* RuleValueChangeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleValueChangeModel.swift; sourceTree = ""; }; + 011D95A0240453D0000E3791 /* RuleEqualsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleEqualsModel.swift; sourceTree = ""; }; + 011D95A2240453F8000E3791 /* RuleRegexModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleRegexModel.swift; sourceTree = ""; }; + 011D95A4240455DC000E3791 /* FormGroupRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormGroupRule.swift; sourceTree = ""; }; + 011D95A824057AC7000E3791 /* FormActionFieldProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormActionFieldProtocol.swift; sourceTree = ""; }; + 011D95AA2405C553000E3791 /* FormItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormItemProtocol.swift; sourceTree = ""; }; + 011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormHolderProtocol.swift; sourceTree = ""; }; 011D95AE2407266E000E3791 /* RadioButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonModel.swift; sourceTree = ""; }; + 011D9601240DA20A000E3791 /* ValidProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidProtocol.swift; sourceTree = ""; }; + 011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonLabelModel.swift; sourceTree = ""; }; + 011D9627240EFA1E000E3791 /* MFViewController+Form.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFViewController+Form.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 = ""; }; @@ -748,6 +778,34 @@ path = ModelProtocols; sourceTree = ""; }; + 011D9583240422BF000E3791 /* New */ = { + isa = PBXGroup; + children = ( + 011D958A24042794000E3791 /* Rules */, + 011D95882404249B000E3791 /* FormProtocol.swift */, + 011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */, + 011D95AA2405C553000E3791 /* FormItemProtocol.swift */, + 011D958624042492000E3791 /* FormFieldProtocol.swift */, + 011D95A824057AC7000E3791 /* FormActionFieldProtocol.swift */, + 011D9601240DA20A000E3791 /* ValidProtocol.swift */, + ); + path = New; + sourceTree = ""; + }; + 011D958A24042794000E3791 /* Rules */ = { + isa = PBXGroup; + children = ( + 011D958424042432000E3791 /* RulesProtocol.swift */, + 011D959A240451E3000E3791 /* RuleRequiredModel.swift */, + 011D959C2404536F000E3791 /* RuleAnyModel.swift */, + 011D959E240453A1000E3791 /* RuleValueChangeModel.swift */, + 011D95A0240453D0000E3791 /* RuleEqualsModel.swift */, + 011D95A2240453F8000E3791 /* RuleRegexModel.swift */, + 011D95A4240455DC000E3791 /* FormGroupRule.swift */, + ); + path = Rules; + sourceTree = ""; + }; 012A88EF23985E0100FE3DA1 /* CustomPrimitives */ = { isa = PBXGroup; children = ( @@ -768,6 +826,7 @@ 01C74D87224298E2009C25A3 /* FormUIHelpers */ = { isa = PBXGroup; children = ( + 011D9583240422BF000E3791 /* New */, 0198F79E225679870066C936 /* FormValidationProtocol.swift */, 0105618A224BBE7700E1557D /* FormValidator.swift */, 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */, @@ -1203,6 +1262,7 @@ D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */, D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */, D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */, + 011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */, 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */, 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */, 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */, @@ -1217,6 +1277,7 @@ D29DF16021E69996003B2FB9 /* MFViewController.h */, D29DF15F21E69996003B2FB9 /* MFViewController.m */, 017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */, + 011D9627240EFA1E000E3791 /* MFViewController+Form.swift */, D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */, D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */, D29DF29121E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h */, @@ -1731,6 +1792,7 @@ D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */, D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */, D2B18B7F2360913400A9AEDC /* Control.swift in Sources */, + 011D95A924057AC7000E3791 /* FormActionFieldProtocol.swift in Sources */, 0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */, D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */, 012A88C8238DB02000FE3DA1 /* ModelMoleculeDelegateProtocol.swift in Sources */, @@ -1744,9 +1806,11 @@ 9445891F2385D2E900DE9FD4 /* CaretViewModel.swift in Sources */, 01C851D323CF9E740021F976 /* LabelToggleModel.swift in Sources */, D29DF2C521E7BF57003B2FB9 /* MFTabBarSwipeAnimator.m in Sources */, + 011D95A3240453F8000E3791 /* RuleRegexModel.swift in Sources */, D2E2A98323D8B32D000B42E6 /* EyebrowHeadlineBodyLinkModel.swift in Sources */, 012A88AD238C418100FE3DA1 /* TemplateProtocol.swift in Sources */, D29DF2B421E7B76D003B2FB9 /* MFLoadingSpinner.m in Sources */, + 011D9602240DA20A000E3791 /* ValidProtocol.swift in Sources */, D260106323D0C05000764D80 /* StackItemModel.swift in Sources */, D2E2A99823D8D63C000B42E6 /* ActionDetailWithImageModel.swift in Sources */, D2E2A99D23DA3217000B42E6 /* UIStackViewAlignment+Extension.swift in Sources */, @@ -1786,6 +1850,7 @@ AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */, 01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */, 012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */, + 011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */, D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */, 944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */, D213347723843825008E41B3 /* Line.swift in Sources */, @@ -1801,6 +1866,7 @@ DBEFFA04225A829700230692 /* Label.swift in Sources */, D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */, 0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */, + 011D959B240451E3000E3791 /* RuleRequiredModel.swift in Sources */, 01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */, 31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */, D260105523CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift in Sources */, @@ -1844,6 +1910,7 @@ D29DF17A21E69E1F003B2FB9 /* MFCustomButton.m in Sources */, 017BEB7B236763000024EF95 /* LineModel.swift in Sources */, 94C2D9A523872C350006CF46 /* LabelAttributeFontModel.swift in Sources */, + 011D958724042492000E3791 /* FormFieldProtocol.swift in Sources */, 011D95AF2407266E000E3791 /* RadioButtonModel.swift in Sources */, 017BEB7F23676E870024EF95 /* MoleculeObjectMapping.swift in Sources */, D274CA332236A78900B01B62 /* FooterView.swift in Sources */, @@ -1856,6 +1923,7 @@ 944589212385D6E900DE9FD4 /* DashLineModel.swift in Sources */, D2E2A99623D8CF85000B42E6 /* HeadlineBodyLinkToggleModel.swift in Sources */, C6FA7D5323C77A4A00A3614A /* StringAndMoleculeStack.swift in Sources */, + 011D958524042432000E3791 /* RulesProtocol.swift in Sources */, 94AF4A3F23E9D13900676048 /* MFCaretButton.m in Sources */, D29DF27A21E7A533003B2FB9 /* MVMCoreUISession.m in Sources */, D2A5146B2214905000345BFB /* ThreeLayerViewController.swift in Sources */, @@ -1865,6 +1933,7 @@ 012A88B1238C880100FE3DA1 /* CarouselPagingModelProtocol.swift in Sources */, D29DF2C921E7BFC6003B2FB9 /* MFSizeObject.m in Sources */, 9445890E2385C3F800DE9FD4 /* MultiProgressModel.swift in Sources */, + 011D95A5240455DC000E3791 /* FormGroupRule.swift in Sources */, D2A6390522CBCE160052ED1F /* MoleculeCollectionViewCell.swift in Sources */, D2A6390122CBB1820052ED1F /* Carousel.swift in Sources */, D29DF2C721E7BF57003B2FB9 /* MFTabBarInteractor.m in Sources */, @@ -1915,13 +1984,16 @@ 94C2D9A123872BCC0006CF46 /* LabelAttributeUnderlineModel.swift in Sources */, D20A9A5E2243D3E300ADE781 /* TwoButtonView.swift in Sources */, D2B1E3E522F37D6A0065F95C /* ImageHeadlineBody.swift in Sources */, + 011D9628240EFA1E000E3791 /* MFViewController+Form.swift in Sources */, 0A21DB94235E24ED00C160A2 /* DigitEntryField.swift in Sources */, 52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */, D26C5A6B23F4A40D007AEECE /* ListItemModel.swift in Sources */, 0A21DB8D235E06EF00C160A2 /* MFDigitTextField.m in Sources */, 94AF4A4323E9D19E00676048 /* MFCaretView.m in Sources */, 943784F6236B77BB006A1E82 /* GraphViewAnimationHandler.swift in Sources */, + 011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */, D29DF2AA21E7B2F9003B2FB9 /* MVMCoreUIConstants.m in Sources */, + 011D95892404249B000E3791 /* FormProtocol.swift in Sources */, 948DB67E2326DCD90011F916 /* MultiProgress.swift in Sources */, 013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */, D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */, @@ -1950,6 +2022,7 @@ D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */, 014AA72E23C5059B006F3E93 /* StackCenteredPageTemplateModel.swift in Sources */, D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */, + 011D959D2404536F000E3791 /* RuleAnyModel.swift in Sources */, D260105923D0A92900764D80 /* ContainerProtocol.swift in Sources */, C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */, D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */, @@ -1958,6 +2031,7 @@ D29DF29E21E7AE3B003B2FB9 /* MFStyler.m in Sources */, D2A514592211C53C00345BFB /* MVMCoreUIMoleculeMappingObject.m in Sources */, 94C661D923CCF4B400D9FE5B /* LeftRightLabelModel.swift in Sources */, + 011D95AB2405C553000E3791 /* FormItemProtocol.swift in Sources */, D21EE53C23AD3AD4003D1A30 /* NSLayoutConstraintAxis+Extension.swift in Sources */, C6FA7D5223C77A4A00A3614A /* UnOrderedList.swift in Sources */, 01509D8F2327EC6F00EF99AA /* MoleculeTableViewCell.swift in Sources */, @@ -1966,6 +2040,8 @@ D22D1F1B220341F60077CEC0 /* MVMCoreUICheckBox.m in Sources */, C695A69823C990C200BFB94E /* DoughnutChartView.swift in Sources */, D29DF2CB21E7BFCC003B2FB9 /* MFSizeThreshold.m in Sources */, + 011D959F240453A1000E3791 /* RuleValueChangeModel.swift in Sources */, + 011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */, 946EE1BA237B66D80036751F /* MoleculeModelHelper.swift in Sources */, 01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */, D260106523D0CEA700764D80 /* StackModel.swift in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index f02eaf5c..77b7addc 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -18,7 +18,8 @@ public enum ButtonSize: String, Codable { case tiny } -public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { +public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormActionFieldProtocol { + public static var identifier: String = "button" public var backgroundColor: Color? public var title: String @@ -32,9 +33,15 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { public var disabledFillColor: Color? public var disabledTextColor: Color? public var disabledBorderColor: Color? - public var required: Bool? - public var requiredGroups: [String]? - + public var groupName: String? + + public func updateEnable(_ enabled: Bool) { + self.enabled = enabled + updateUI?() + } + + public var updateUI: (() -> Void)? + init(with title: String, action: ActionModelProtocol) { self.title = title self.action = action @@ -66,8 +73,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { case disabledFillColor case disabledTextColor case disabledBorderColor - case required - case requiredGroups + case groupName } required public init(from decoder: Decoder) throws { @@ -76,8 +82,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { 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) - required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required) - requiredGroups = try typeContainer.decodeIfPresent([String].self, forKey: .requiredGroups) + groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) if let style = try typeContainer.decodeIfPresent(ButtonStyle.self, forKey: .style) { self.style = style } @@ -110,7 +115,6 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol { try container.encodeIfPresent(disabledFillColor, forKey: .disabledFillColor) try container.encodeIfPresent(disabledTextColor, forKey: .disabledTextColor) try container.encodeIfPresent(disabledBorderColor, forKey: .disabledBorderColor) - try container.encodeIfPresent(required, forKey: .required) - try container.encodeIfPresent(requiredGroups, forKey: .requiredGroups) + try container.encodeIfPresent(groupName, forKey: .groupName) } } diff --git a/MVMCoreUI/Atoms/Buttons/PillButton.swift b/MVMCoreUI/Atoms/Buttons/PillButton.swift index d7fa8db5..da8cf0c7 100644 --- a/MVMCoreUI/Atoms/Buttons/PillButton.swift +++ b/MVMCoreUI/Atoms/Buttons/PillButton.swift @@ -8,7 +8,7 @@ import UIKit -open class PillButton: Button, MVMCoreUIViewConstrainingProtocol, FormValidationEnableDisableProtocol { +open class PillButton: Button, MVMCoreUIViewConstrainingProtocol { // Used to size the button. var size = MVMCoreUIUtility.getWidth() @@ -125,11 +125,12 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol, FormValidation guard let model = model as? ButtonModel else { return } setTitle(model.title, for: .normal) - - if let required = model.required, - required { - FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) + + model.updateUI = { [weak self] in + self?.enableField(model.enabled) } + + FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate) } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { @@ -163,17 +164,8 @@ open class PillButton: Button, MVMCoreUIViewConstrainingProtocol, FormValidation open func horizontalAlignment() -> UIStackView.Alignment { return .center } - - // MARK: - FormValidationEnableDisableProtocol - public func isValidationRequired() -> Bool { - return buttonModel?.required ?? false - } - - public func requiredGroups() -> [String]? { - return buttonModel?.requiredGroups - } public func enableField(_ enable: Bool) { - isEnabled = isValidationRequired() ? enable : true + isEnabled = enable } } diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift b/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift index 0e2368b8..f354ac85 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift @@ -16,13 +16,10 @@ extension PrimaryButton: ModelMoleculeViewProtocol { setTitle(model.title, for: .normal) backgroundColor = model.backgroundColor?.uiColor - self.validationRequired = model.required ?? false - self.requiredGroupsList = model.requiredGroups - - if self.validationRequired, - let selfForm = self as? FormValidationEnableDisableProtocol { - FormValidator.setupValidation(molecule: selfForm, delegate: delegateObject?.formValidationProtocol) - } +// if self.validationRequired, +// let selfForm = self as? FormValidationEnableDisableProtocol { +// FormValidator.setupValidation(molecule: selfForm, delegate: delegateObject?.formValidationProtocol) +// } if let style = model.style { switch style { diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index e4a794bc..e9ca5e65 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -9,7 +9,8 @@ import Foundation -@objcMembers public class EntryFieldModel: MoleculeModelProtocol { +@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, ValidProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -26,8 +27,18 @@ import Foundation public var isLocked: Bool? public var isSelected: Bool? public var fieldKey: String? - public var isValid: Bool? public var isRequired: Bool? + public var text: String? + + public var isValid: Bool? { + didSet { + updateUI?() + } + } + public var updateUI: (() -> Void)? + public func setValidity(_ isValid: Bool) { + self.isValid = isValid + } //-------------------------------------------------- // MARK: - Keys @@ -45,6 +56,11 @@ import Foundation case fieldKey case isValid case isRequired = "required" + case text + } + + public func formFieldValue() -> Any? { + return text } //-------------------------------------------------- @@ -62,6 +78,7 @@ import Foundation isSelected = try typeContainer.decodeIfPresent(Bool.self, forKey: .isSelected) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) isValid = try typeContainer.decodeIfPresent(Bool.self, forKey: .isValid) + text = try typeContainer.decodeIfPresent(String.self, forKey: .text) } public func encode(to encoder: Encoder) throws { @@ -76,5 +93,6 @@ import Foundation try container.encode(isSelected, forKey: .isSelected) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(isValid, forKey: .isValid) + try container.encodeIfPresent(text, forKey: .text) } } diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField+ModelExtension.swift b/MVMCoreUI/Atoms/TextFields/MFTextField+ModelExtension.swift index e57cec9c..63e01b3a 100644 --- a/MVMCoreUI/Atoms/TextFields/MFTextField+ModelExtension.swift +++ b/MVMCoreUI/Atoms/TextFields/MFTextField+ModelExtension.swift @@ -16,64 +16,64 @@ enum TextType: String { } extension MFTextField: ModelMoleculeViewProtocol { // - public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - //TODO: Need to create setWithModel in ViewConstraining View - #warning("This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.") - //TODO: This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView. - setUpDefaultWithModel(model, delegateObject, additionalData) - - guard let textFieldModel = model as? TextFieldModel, - let delegateObject = delegateObject else { - return - } - - if let delegate = delegateObject.formValidationProtocol { - let formValidator = FormValidator.getFormValidatorFor(delegate: delegate) - mfTextFieldDelegate = formValidator - uiTextFieldDelegate = delegateObject.uiTextFieldDelegate - if let textField = textField { - MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate) - } - } - - formText = textFieldModel.label as NSString? - text = textFieldModel.value as NSString? - if let disabled = textFieldModel.disabled { - enable(disabled) - } - errMessage = textFieldModel.errorMsg - fieldKey = textFieldModel.fieldKey - groupName = textFieldModel.groupName - - - switch textFieldModel.type { - case TextType.dropDown.rawValue: - dropDownCarrotLabel?.isHidden = true - hasDropDown = true - break - case TextType.password.rawValue: - textField?.isSecureTextEntry = true - break - case TextType.number.rawValue: - textField?.keyboardType = .numberPad - break - case TextType.email.rawValue: - textField?.keyboardType = .emailAddress - break - default: - print("default") - } - - if let regex = textFieldModel.regex { - validationBlock = {(enteredValue: String?) -> Bool in - if let enteredValue = enteredValue { - return MVMCoreUIUtility.validate(enteredValue, withRegularExpression: regex) - } - return true - } - } else { - setDefaultValidationBlock() - } + public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { +// //TODO: Need to create setWithModel in ViewConstraining View +// #warning("This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.") +// //TODO: This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView. +// setUpDefaultWithModel(model, delegateObject, additionalData) +// +// guard let textFieldModel = model as? TextFieldModel, +// let delegateObject = delegateObject else { +// return +// } +// +// if let delegate = delegateObject.formValidationProtocol { +// let formValidator = FormValidator.getFormValidatorFor(delegate: delegate) +// mfTextFieldDelegate = formValidator +// uiTextFieldDelegate = delegateObject.uiTextFieldDelegate +// if let textField = textField { +// MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate) +// } +// } +// +// formText = textFieldModel.label as NSString? +// text = textFieldModel.value as NSString? +// if let disabled = textFieldModel.disabled { +// enable(disabled) +// } +// errMessage = textFieldModel.errorMsg +// fieldKey = textFieldModel.fieldKey +// groupName = textFieldModel.groupName +// +// +// switch textFieldModel.type { +// case TextType.dropDown.rawValue: +// dropDownCarrotLabel?.isHidden = true +// hasDropDown = true +// break +// case TextType.password.rawValue: +// textField?.isSecureTextEntry = true +// break +// case TextType.number.rawValue: +// textField?.keyboardType = .numberPad +// break +// case TextType.email.rawValue: +// textField?.keyboardType = .emailAddress +// break +// default: +// print("default") +// } +// +// if let regex = textFieldModel.regex { +// validationBlock = {(enteredValue: String?) -> Bool in +// if let enteredValue = enteredValue { +// return MVMCoreUIUtility.validate(enteredValue, withRegularExpression: regex) +// } +// return true +// } +// } else { +// setDefaultValidationBlock() +// } } } diff --git a/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift index a0a893a6..b42349c6 100644 --- a/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift @@ -97,25 +97,25 @@ import MVMCore return MVMCoreUIUtility.validateInternationalMDNString(MDN) } - @objc public override func validateTextField() -> Bool { + @objc public override func validateTextField() { - guard !shouldValidateMDN, let MDN = mdn, !MDN.isEmpty else { - isValid = true - return true - } - - let isValid = hasValidMDN() - - if isValid { - showError = false - - } else { - errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message") - showError = true - UIAccessibility.post(notification: .layoutChanged, argument: textField) - } - - return isValid +// guard !shouldValidateMDN, let MDN = mdn, !MDN.isEmpty else { +// isValid = true +// return true +// } +// +// let isValid = hasValidMDN() +// +// if isValid { +// showError = false +// +// } else { +// errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message") +// showError = true +// UIAccessibility.post(notification: .layoutChanged, argument: textField) +// } +// +// return isValid } @objc public func getContacts(_ sender: Any?) { @@ -186,9 +186,9 @@ import MVMCore proprietorTextDelegate?.textFieldDidEndEditing?(textField) - if validateTextField() && isNationalMDN { - textField.text = MVMCoreUIUtility.formatMdn(textField.text) - } +// if validateTextField() && isNationalMDN { +// textField.text = MVMCoreUIUtility.formatMdn(textField.text) +// } } @objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index 61f6c82c..870d669a 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -49,7 +49,7 @@ import UIKit /// Validate when user resigns editing. Default: true public var validateWhenDoneEditing: Bool = true - + //-------------------------------------------------- // MARK: - Computed Properties //-------------------------------------------------- @@ -218,34 +218,33 @@ import UIKit @discardableResult @objc override open func resignFirstResponder() -> Bool { - if validateWhenDoneEditing { validateTextField() } - textField.resignFirstResponder() isSelected = false return true } /// Validates the text of the entry field. - @discardableResult - @objc public func validateTextField() -> Bool { - - isValid = validationBlock?(text) ?? true - + @objc public func validateTextField() { + text = textField.text + FormValidator.validate(delegate: delegateObject?.formHolderDelegate) + } + + @objc public func updateValidation(_ isValid: Bool) { + self.isValid = isValid if isValid { showError = false observingTextFieldDelegate?.isValid?(textfield: self) - + } else { showError = true observingTextFieldDelegate?.isInvalid?(textfield: self) } - - return isValid } - + + /// Executes on UITextField.textDidBeginEditingNotification @objc func startEditing() { @@ -263,17 +262,14 @@ import UIKit /// Executes on UITextField.textDidEndEditingNotification @objc func endInputing() { - + resignFirstResponder() if isValid { showError = false entryFieldContainer.bottomBar?.backgroundColor = UIColor.black.cgColor } - - resignFirstResponder() } @objc func dismissFieldInput(_ sender: Any?) { - resignFirstResponder() } @@ -281,9 +277,14 @@ import UIKit super.set(with: model, delegateObject, additionalData) guard let model = model as? TextEntryFieldModel else { return } - - FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) - + + model.updateUI = { [weak self] in + if self?.isSelected ?? false { + self?.updateValidation(model.isValid ?? true) + } + } + self.delegateObject = delegateObject + FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate) textColor.enabled = model.enabledTextColor?.uiColor textColor.disabled = model.disabledTextColor?.uiColor text = model.text @@ -312,11 +313,9 @@ import UIKit defaultValidationBlock() } - if let formValidationProtocol = delegateObject?.formValidationProtocol { - observingTextFieldDelegate = FormValidator.getFormValidatorFor(delegate: formValidationProtocol) - } - +// observingTextFieldDelegate = FormValidator.getFormValidatorFor(delegate: delegateObject?.formHolderDelegate) uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate + observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate) } } @@ -330,9 +329,7 @@ extension TextEntryField { guard let delegateObject = delegateObject, let dictionary = json else { return } - - FormValidator.setupValidation(molecule: self, delegate: delegateObject.formValidationProtocol) - + if let enabledTextColorHex = dictionary["enabledTextColor"] as? String { textColor.enabled = UIColor.mfGet(forHex: enabledTextColorHex) } @@ -374,11 +371,9 @@ extension TextEntryField { defaultValidationBlock() } - if let formValidationProtocol = delegateObject.formValidationProtocol { - observingTextFieldDelegate = FormValidator.getFormValidatorFor(delegate: formValidationProtocol) - } uiTextFieldDelegate = delegateObject.uiTextFieldDelegate + observingTextFieldDelegate = delegateObject.observingTextFieldDelegate MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate) } } diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift index 27b0e933..8b8e582e 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryFieldModel.swift @@ -16,7 +16,6 @@ return "textField" } - public var text: String? public var placeholder: String? public var enabledTextColor: Color? public var disabledTextColor: Color? diff --git a/MVMCoreUI/Atoms/Views/Checkbox.swift b/MVMCoreUI/Atoms/Views/Checkbox.swift index fd186d7e..a87c3e3e 100644 --- a/MVMCoreUI/Atoms/Views/Checkbox.swift +++ b/MVMCoreUI/Atoms/Views/Checkbox.swift @@ -127,9 +127,10 @@ import MVMCore didSet { if !updateSelectionOnly { layoutIfNeeded() + (model as? CheckboxModel)?.isChecked = isSelected shapeLayer?.removeAllAnimations() updateCheckboxUI(isSelected: isSelected, isAnimated: isAnimated) - FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) + FormValidator.validate(delegate: delegateObject?.formHolderDelegate) updateAccessibilityLabel() } } @@ -397,76 +398,12 @@ import MVMCore //layoutIfNeeded() } - - public override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - self.delegateObject = delegateObject - FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) - - guard let dictionary = json else { return } - - groupName = dictionary.optionalStringForKey("groupName") - fieldValue = dictionary.optionalStringForKey("value") - if let fieldKey = dictionary[KeyFieldKey] as? String { - self.fieldKey = fieldKey - } - - if let isRequired = dictionary[KeyRequired] as? Bool { - self.isRequired = isRequired - } - - if let borderColorHex = dictionary["borderColor"] as? String { - layer.borderColor = UIColor.mfGet(forHex: borderColorHex).cgColor - } - - if let borderWidth = dictionary["borderWidth"] as? CGFloat { - layer.borderWidth = borderWidth - } - - if let checkColorHex = dictionary["checkColor"] as? String { - checkColor = UIColor.mfGet(forHex: checkColorHex) - } - - if let isChecked = dictionary["isChecked"] as? Bool, isChecked { - checkAndBypassAnimations(selected: isChecked) - } - - if let unCheckedBackgroundColorHex = dictionary["unCheckedBackgroundColor"] as? String { - unCheckedBackgroundColor = UIColor.mfGet(forHex: unCheckedBackgroundColorHex) - } - - if let checkedBackgroundColorHex = dictionary["checkedBackgroundColor"] as? String { - checkedBackgroundColor = UIColor.mfGet(forHex: checkedBackgroundColorHex) - } - - if let isAnimated = dictionary["isAnimated"] as? Bool { - self.isAnimated = isAnimated - } - - if let isRound = dictionary["isRound"] as? Bool { - self.isRound = isRound - } - - if let enabled = dictionary["isEnabled"] as? Bool { - isEnabled = enabled - } - - if let actionMap = dictionary.optionalDictionaryForKey("action") { - actionBlock = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } - } - } - + public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { super.set(with: model, delegateObject, additionalData) - guard let model = model as? CheckboxModel else { return } - self.delegateObject = delegateObject - FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) - - groupName = model.groupName - fieldValue = model.value - isRequired = model.required + FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate) if let fieldKey = model.fieldKey { self.fieldKey = fieldKey @@ -500,23 +437,3 @@ import MVMCore } } } - -// MARK:- FormValidationProtocol -extension Checkbox: FormValidationFormFieldProtocol { - - public func formFieldGroupName() -> String? { - return groupName - } - - public func isValidField() -> Bool { - return isRequired ? isSelected : true - } - - public func formFieldName() -> String? { - return fieldKey - } - - public func formFieldValue() -> Any? { - return isSelected ? fieldValue : nil - } -} diff --git a/MVMCoreUI/Atoms/Views/CheckboxModel.swift b/MVMCoreUI/Atoms/Views/CheckboxModel.swift index 706597ff..60aade23 100644 --- a/MVMCoreUI/Atoms/Views/CheckboxModel.swift +++ b/MVMCoreUI/Atoms/Views/CheckboxModel.swift @@ -8,7 +8,8 @@ import Foundation -@objcMembers public class CheckboxModel: MoleculeModelProtocol { +@objcMembers public class CheckboxModel: MoleculeModelProtocol, FormFieldProtocol { + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -16,10 +17,6 @@ import Foundation public static var identifier: String = "checkbox" public var backgroundColor: Color? - public var groupName: String? - public var value: String? - public var fieldKey: String? - public var required: Bool = false public var borderColor: Color = Color(uiColor: .black) public var borderWidth: CGFloat = 1 public var isChecked: Bool = false @@ -33,17 +30,16 @@ import Foundation public var disabledBackgroundColor: Color = Color(uiColor: .clear) public var disabledBorderColor: Color = Color(uiColor: .mvmCoolGray3) public var disabledCheckColor: Color = Color(uiColor: .mvmCoolGray3) - + + public var fieldKey: String? + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- private enum CodingKeys: String, CodingKey { case moleculeName - case groupName - case value case fieldKey - case required case borderColor case borderWidth case isChecked @@ -61,16 +57,17 @@ import Foundation init(isChecked: Bool = false) {} + public func formFieldValue() -> Any? { + return isChecked + } + //-------------------------------------------------- // MARK: - Codec //-------------------------------------------------- required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) - value = try typeContainer.decodeIfPresent(String.self, forKey: .value) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) - required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required) ?? false borderWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .borderWidth) ?? 1 borderColor = try typeContainer.decodeIfPresent(Color.self, forKey: .borderColor) ?? Color(uiColor: .black) checkColor = try typeContainer.decodeIfPresent(Color.self, forKey: .checkColor) ?? Color(uiColor: .black) @@ -89,10 +86,7 @@ import Foundation public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) - try container.encodeIfPresent(groupName, forKey: .groupName) - try container.encodeIfPresent(value, forKey: .value) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) - try container.encodeIfPresent(required, forKey: .required) try container.encodeIfPresent(borderColor, forKey: .borderColor) try container.encode(borderWidth, forKey: .borderWidth) try container.encode(isChecked, forKey: .isChecked) diff --git a/MVMCoreUI/Atoms/Views/MFView+ModelExtension.swift b/MVMCoreUI/Atoms/Views/MFView+ModelExtension.swift index af14bc44..840a5d18 100644 --- a/MVMCoreUI/Atoms/Views/MFView+ModelExtension.swift +++ b/MVMCoreUI/Atoms/Views/MFView+ModelExtension.swift @@ -18,7 +18,7 @@ extension MFView { } extension ModelMoleculeViewProtocol where Self: MFView { - func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { setUpDefaultWithModel(model, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch+Model.swift b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch+Model.swift index aeccf2ff..1b7ad307 100644 --- a/MVMCoreUI/Atoms/Views/MVMCoreUISwitch+Model.swift +++ b/MVMCoreUI/Atoms/Views/MVMCoreUISwitch+Model.swift @@ -13,10 +13,7 @@ extension MVMCoreUISwitch: ModelMoleculeViewProtocol { public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) { guard let model = model as? ToggleModel else { return } - if let castSelf = self as? FormValidationProtocol { - FormValidator.setupValidation(molecule: castSelf, delegate: delegateObject?.formValidationProtocol) - } - + FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate) setState(model.state, animated: false) guard let action = model.action else { return } diff --git a/MVMCoreUI/Atoms/Views/RadioButton.swift b/MVMCoreUI/Atoms/Views/RadioButton.swift index 47eeb0ca..f6484326 100644 --- a/MVMCoreUI/Atoms/Views/RadioButton.swift +++ b/MVMCoreUI/Atoms/Views/RadioButton.swift @@ -8,13 +8,14 @@ import UIKit -@objcMembers public class RadioButton: Control, FormValidationFormFieldProtocol { +@objcMembers public class RadioButton: Control { var diameter: CGFloat = 30 { didSet { widthConstraint?.constant = diameter } } + var enabledColor = UIColor.black var disabledColor = UIColor.mfSilver() @@ -27,15 +28,18 @@ import UIKit var widthConstraint: NSLayoutConstraint? var heightConstraint: NSLayoutConstraint? + var radioModel: RadioButtonModel? { + return model as? RadioButtonModel + } + lazy var radioGroupName: String? = { - [unowned self] in - return json?.optionalStringForKey("radioGroupName") ?? json?.optionalStringForKey("fieldKey") + [unowned self] in return radioModel?.radioGroupName ?? radioModel?.fieldKey }() - lazy var radioButtonModel: RadioButtonSelectionHelper? = { + lazy var radioButtonSelectionHelper: RadioButtonSelectionHelper? = { [unowned self] in if let radioGroupName = radioGroupName, - let radioButtonModel = delegateObject?.formValidationProtocol?.formValidatorModel?()?.radioButtonsModelByGroup[radioGroupName] { + let radioButtonModel = delegateObject?.formHolderDelegate?.formValidator?.radioButtonsModelByGroup[radioGroupName] { return radioButtonModel } else { return nil @@ -58,12 +62,12 @@ import UIKit /// The action performed when tapped. func tapAction() { - if let radioButtonModel = radioButtonModel { + if let radioButtonModel = radioButtonSelectionHelper { radioButtonModel.selected(self) } else { isSelected = !isSelected } - FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) + FormValidator.validate(delegate: delegateObject?.formHolderDelegate) setNeedsDisplay() } @@ -72,15 +76,15 @@ import UIKit } public func formFieldName() -> String? { - return json?.optionalStringForKey("fieldKey") + return radioModel?.fieldKey } public func formFieldGroupName() -> String? { - return json?.optionalStringForKey("groupName") + return radioModel?.radioGroupName } - public func formFieldValue() -> Any? { - return isSelected + public func formFieldValue() -> String? { + return radioModel?.fieldValue } // MARK: - MVMViewProtocol @@ -104,40 +108,14 @@ import UIKit guard let model = model as? RadioButtonModel else { return } - setWithJSON(model.toJSON(), delegateObject: delegateObject, additionalData: additionalData) - } -} - -// MARK: - MVMCoreUIViewConstrainingProtocol -extension RadioButton: MVMCoreUIViewConstrainingProtocol { - public func needsToBeConstrained() -> Bool { - return true - } -} - -// MARK: - MVMCoreUIMoleculeViewProtocol -extension RadioButton { - - @objc open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - - // Configure class properties with JSON values - guard let jsonDictionary = json else { - return - } - - fieldKey = jsonDictionary.optionalStringForKey("fieldKey") - isRequired = jsonDictionary.boolForKey("required") self.delegateObject = delegateObject - - let radioButtonModel = RadioButtonSelectionHelper.setupForRadioButtonGroup(radioButton: self, - formValidator: delegateObject?.formValidationProtocol?.formValidatorModel?()) - FormValidator.setupValidation(molecule: radioButtonModel, delegate: delegateObject?.formValidationProtocol) + let radioButtonModel = RadioButtonSelectionHelper.setupForRadioButtonGroup(model, + formValidator: delegateObject?.formHolderDelegate?.formValidator) + FormValidator.setupValidation(molecule: radioButtonModel, delegate: delegateObject?.formHolderDelegate) } public override func reset() { - super.reset() - backgroundColor = .white + super.reset() + backgroundColor = .white } } diff --git a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift index c8443691..a058ada6 100644 --- a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift +++ b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift @@ -9,9 +9,20 @@ import Foundation -public class RadioButtonModel: MoleculeModelProtocol { +public class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { + public static var identifier: String = "radioButton" public var backgroundColor: Color? - public var state: Bool = false + public var state: Bool? = false + public var radioGroupName: String? public var fieldKey: String? + public var fieldValue: String + public func formFieldValue() -> Any? { + return fieldValue + } + + init(_ fieldKey: String, _ fieldValue: String) { + self.fieldKey = fieldKey + self.fieldValue = fieldValue + } } diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index ee888b3f..c53b4be6 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -101,7 +101,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) self.constrainKnob() } - FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol) + FormValidator.validate(delegate: delegateObject?.formHolderDelegate) accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") setNeedsLayout() layoutIfNeeded() @@ -379,7 +379,7 @@ extension Toggle { super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) self.delegateObject = delegateObject - FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) +// FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) guard let dictionary = json else { return } diff --git a/MVMCoreUI/Atoms/Views/ToggleModel.swift b/MVMCoreUI/Atoms/Views/ToggleModel.swift index aafacec8..54c86514 100644 --- a/MVMCoreUI/Atoms/Views/ToggleModel.swift +++ b/MVMCoreUI/Atoms/Views/ToggleModel.swift @@ -8,7 +8,8 @@ import UIKit -public class ToggleModel: MoleculeModelProtocol { +public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { + public static var identifier: String = "toggle" public var backgroundColor: Color? public var state: Bool = true @@ -27,6 +28,10 @@ public class ToggleModel: MoleculeModelProtocol { case alternateAction } + public func formFieldValue() -> Any? { + return state + } + public init(_ state: Bool) { self.state = state } diff --git a/MVMCoreUI/BaseControllers/MFViewController+Form.swift b/MVMCoreUI/BaseControllers/MFViewController+Form.swift new file mode 100644 index 00000000..2c3b14bf --- /dev/null +++ b/MVMCoreUI/BaseControllers/MFViewController+Form.swift @@ -0,0 +1,22 @@ +// +// MFViewController+Form.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 3/3/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +extension MFViewController: ObservingTextFieldDelegate { +} + +public extension MFViewController { + @objc func startValidation() { + (self as? FormHolderProtocol)?.formValidator?.validate() + } + + @objc func addFormParams(requestParameters: MVMCoreRequestParameters) { + (self as? FormHolderProtocol)?.formValidator?.addFormParams(requestParameters: requestParameters) + } +} diff --git a/MVMCoreUI/BaseControllers/MFViewController.m b/MVMCoreUI/BaseControllers/MFViewController.m index f663193f..1af64e34 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.m +++ b/MVMCoreUI/BaseControllers/MFViewController.m @@ -52,19 +52,10 @@ // title view for navigation bar, used for custom navigation titles @property (weak, nonatomic) UILabel *titleLabel; -@property (strong, nonatomic) FormValidator *formValidator; - @end @implementation MFViewController -- (FormValidator *)formValidatorModel { - if (self.formValidator == nil) { - self.formValidator = [FormValidator new]; - } - return self.formValidator; -} - - (void)dismiss { [MVMCoreDispatchUtility performBlockOnMainThread:^{ if (self.presentingViewController) { @@ -487,12 +478,13 @@ if (!self.disableAnimations) { [self setupIntroAnimations]; } + + [self startValidation]; } - (void)newDataBuildAndUpdate { [MVMCoreDispatchUtility performBlockOnMainThread:^{ [self newDataBuildScreen]; - [self.formValidator enableByValidation]; self.needToUpdateUI = YES; [self.view setNeedsLayout]; }]; @@ -690,9 +682,8 @@ [[MVMCoreUISession sharedGlobal].splitViewController.rightPanel willOpenWithActionInformation:actionInformation]; } - [self.formValidator addFormParamsWithRequestParameters:requestParameters]; + [self addFormParamsWithRequestParameters:requestParameters]; requestParameters.parentPageType = [self.loadObject.pageJSON stringForKey:@"parentPageType"]; - [[MVMCoreLoadHandler sharedGlobal] loadRequest:requestParameters dataForPage:additionalData delegateObject:[self delegateObject]]; } diff --git a/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift b/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift index 4c4945a4..97668df4 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift @@ -8,21 +8,3 @@ import Foundation -@objc public extension FormValidator { - @objc func addFormParams(requestParameters: MVMCoreRequestParameters) { - requestParameters.add(self.getFormParams()) - } - - @objc func getFormParams() -> [String: Any] { - var extraParam: [String: Any] = [:] - MVMCoreDispatchUtility.performSyncBlock(onMainThread: { - for molecule in self.fieldMolecules { - if let formFieldName = molecule.formFieldName(), - let formFieldValue = molecule.formFieldValue() { - extraParam[formFieldName] = formFieldValue - } - } - }) - return extraParam - } -} diff --git a/MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift b/MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift index 21599abf..0455b689 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift @@ -8,63 +8,62 @@ import Foundation -@objc extension FormValidator: MFTextFieldDelegate { - - public func dismissFieldInput(_ sender: Any?) { - - if let delegate = delegate as? MFTextFieldDelegate { - delegate.dismissFieldInput?(sender) - } - } - - public func entryIsValid(_ textfield: MFTextField?) { - - MVMCoreDispatchUtility.performBlock(onMainThread: { - self.enableByValidation() - if let delegate = self.delegate as? MFTextFieldDelegate { - delegate.entryIsValid?(textfield) - } - }) - } - - public func entryIsInvalid(_ textfield: MFTextField?) { - - MVMCoreDispatchUtility.performBlock(onMainThread: { - self.enableByValidation() - if let delegate = self.delegate as? MFTextFieldDelegate { - delegate.entryIsInvalid?(textfield) - } - }) - } -} - +//@objc extension FormValidator: MFTextFieldDelegate { +// +// public func dismissFieldInput(_ sender: Any?) { +// +// if let delegate = delegate as? MFTextFieldDelegate { +// delegate.dismissFieldInput?(sender) +// } +// } +// +// public func entryIsValid(_ textfield: MFTextField?) { +// +// MVMCoreDispatchUtility.performBlock(onMainThread: { +// self.enableByValidation() +// if let delegate = self.delegate as? MFTextFieldDelegate { +// delegate.entryIsValid?(textfield) +// } +// }) +// } +// +// public func entryIsInvalid(_ textfield: MFTextField?) { +// +// MVMCoreDispatchUtility.performBlock(onMainThread: { +// self.enableByValidation() +// if let delegate = self.delegate as? MFTextFieldDelegate { +// delegate.entryIsInvalid?(textfield) +// } +// }) +// } +//} +// // Temporary: Looking to either combine or separate entirely with MFTextFieldDelegate. -extension FormValidator: ObservingTextFieldDelegate { - - public func dismissField(_ sender: Any?) { - - if let delegate = delegate as? MFTextFieldDelegate { - delegate.dismissFieldInput?(sender) - } - } - - @nonobjc public func isValid(_ textfield: MFTextField?) { - - MVMCoreDispatchUtility.performBlock(onMainThread: { - self.enableByValidation() - if let delegate = self.delegate as? MFTextFieldDelegate { - delegate.entryIsValid?(textfield) - } - }) - } - - public func isInvalid(_ textfield: MFTextField?) { - - MVMCoreDispatchUtility.performBlock(onMainThread: { - self.enableByValidation() - if let delegate = self.delegate as? MFTextFieldDelegate { - delegate.entryIsInvalid?(textfield) - } - }) - } -} +//extension FormValidator: ObservingTextFieldDelegate { +// +// public func dismissField(_ sender: Any?) { +// if let delegate = delegate as? MFTextFieldDelegate { +// delegate.dismissFieldInput?(sender) +// } +// } +// +// @nonobjc public func isValid(_ textfield: MFTextField?) { +// +// MVMCoreDispatchUtility.performBlock(onMainThread: { +// self.enableByValidation() +// if let delegate = self.delegate as? MFTextFieldDelegate { +// delegate.entryIsValid?(textfield) +// } +// }) +// } +// +// public func isInvalid(_ textfield: MFTextField?) { +// +// MVMCoreDispatchUtility.performBlock(onMainThread: { +// self.enableByValidation() +// if let delegate = self.delegate as? MFTextFieldDelegate { +// delegate.entryIsInvalid?(textfield) +// } +// }) +// } +//} diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index cff26347..fd4dd6e8 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -13,73 +13,81 @@ import MVMCore var extraValidationBlock: (() -> Bool)? var dummyGroupName = "dummyGroupName" - weak var delegate: FormValidationProtocol? - var fieldMolecules: [FormValidationFormFieldProtocol] = [] - var enableDisableMolecules: [FormValidationEnableDisableProtocol] = [] + + var formRules: [FormGroupRule] + var delegate: FormHolderProtocol? + var fieldMolecules: [FormFieldProtocol] = [] + var formActionMolecules: [FormActionFieldProtocol] = [] var radioButtonsModelByGroup: [String: RadioButtonSelectionHelper] = [:] - - public func insertMolecule(_ molecule: FormValidationProtocol) { - if let molecule = molecule as? FormValidationFormFieldProtocol { - fieldMolecules.append(molecule) - } - if let moleculeT = molecule as? FormValidationEnableDisableProtocol, - moleculeT.isValidationRequired() { - enableDisableMolecules.append(moleculeT) - } + + public init(_ formRules: [FormGroupRule]) { + self.formRules = formRules } - public static func enableByValidationWith(delegate: FormValidationProtocol?) { - if let delegate = delegate { - let formValidator = FormValidator.getFormValidatorFor(delegate: delegate) - formValidator?.enableByValidation() + public func insertMolecule(_ molecule: FormItemProtocol) { + if let molecule = molecule as? FormFieldProtocol { + fieldMolecules.append(molecule) + } + if let molecule = molecule as? FormActionFieldProtocol { + formActionMolecules.append(molecule) } } - public static func getFormValidatorFor(delegate: FormValidationProtocol) -> FormValidator? { - return delegate.formValidatorModel?() - } - - public static func setupValidation(molecule: FormValidationProtocol, delegate: FormValidationProtocol?) { - if let validator = delegate?.formValidatorModel?() { + public static func setupValidation(molecule: FormItemProtocol, delegate: FormHolderProtocol?) { + if let validator = delegate?.formValidator { validator.delegate = delegate validator.insertMolecule(molecule) } } - public func enableByValidation() { - for molecule in enableDisableMolecules { - var requiredGroups = molecule.requiredGroups?() ?? [dummyGroupName] - if requiredGroups.count == 0 { - requiredGroups = [dummyGroupName] - } - enableWithGroups(requiredGroups, molecule) - } + public static func getFormValidatorFor(delegate: FormHolderProtocol?) -> FormValidator? { + return delegate?.formValidator } - - public func enableWithGroups(_ requiredGroupList: [String], _ enableDisableMolecule: FormValidationEnableDisableProtocol) { - let requiredGroupSet = Set(requiredGroupList) - var valid = true - for molecule in fieldMolecules { - let groupName = molecule.formFieldGroupName() ?? dummyGroupName - if requiredGroupSet.contains(groupName) { - valid = valid && molecule.isValidField() - if valid == false { - break - } + + public static func validate(delegate: FormHolderProtocol?) { + delegate?.formValidator?.validate() + } + + public func validate() { + formActionMolecules.forEach { (actionModel) in + if let groupName = actionModel.groupName, let formRule = formRules.first(where: { $0.groupName == groupName }) { + validate(groupName, actionModel, formRule.rules) } } - enableDisableMolecule.enableField?(valid) } - - public func enableIgnoreGroupName(_ enableDisableMolecules: FormValidationEnableDisableProtocol) { + + public func validate(_ groupName: String, _ actionModel: FormActionFieldProtocol, _ rules: [RulesProtocol]) { var valid = true - for molecule in fieldMolecules { - valid = valid && molecule.isValidField() - if (!valid) { + for rule in rules { + valid = valid && rule.isValid(self) + if !valid { break } } - let enableField = valid && (extraValidationBlock?() ?? true) - enableDisableMolecules.enableField?(enableField) + actionModel.updateEnable(valid) + } + + public func formField(for fieldKey: String) -> FormFieldProtocol? { + return fieldMolecules.first(where: { $0.fieldKey == fieldKey }) + } +} + +// mark Form params +@objc public extension FormValidator { + @objc func addFormParams(requestParameters: MVMCoreRequestParameters) { + requestParameters.add(self.getFormParams()) + } + + @objc func getFormParams() -> [String: Any] { + var extraParam: [String: Any] = [:] + MVMCoreDispatchUtility.performSyncBlock(onMainThread: { + for molecule in self.fieldMolecules { + if let formFieldName = molecule.fieldKey, + let formFieldValue = molecule.formFieldValue() { + extraParam[formFieldName] = formFieldValue + } + } + }) + return extraParam } } diff --git a/MVMCoreUI/FormUIHelpers/New/FormActionFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormActionFieldProtocol.swift new file mode 100644 index 00000000..2f4b758d --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/FormActionFieldProtocol.swift @@ -0,0 +1,15 @@ +// +// FormActionFieldProtocol.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 1/31/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol FormActionFieldProtocol: EnableableModelProtocol, FormItemProtocol { + var groupName: String? { get set } + func updateEnable(_ enabled: Bool) + var updateUI: (() -> Void)? { get set } +} diff --git a/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift new file mode 100644 index 00000000..d6073943 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift @@ -0,0 +1,15 @@ +// +// FormFieldProtocol.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 1/31/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + + +public protocol FormFieldProtocol: FormItemProtocol { + var fieldKey: String? { get set } + func formFieldValue() -> Any? +} diff --git a/MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift new file mode 100644 index 00000000..57c41a21 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift @@ -0,0 +1,17 @@ +// +// FormHolderProtocol.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/26/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + + +//Protocol for Validation +public protocol FormHolderProtocol: NSObjectProtocol { + var formValidator: FormValidator? { get set } + /// Should call formValidator's validate method + func validate() +} diff --git a/MVMCoreUI/FormUIHelpers/New/FormItemProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormItemProtocol.swift new file mode 100644 index 00000000..47911f0c --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/FormItemProtocol.swift @@ -0,0 +1,13 @@ +// +// FormItemProtocol.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/25/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol FormItemProtocol { + +} diff --git a/MVMCoreUI/FormUIHelpers/New/FormProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormProtocol.swift new file mode 100644 index 00000000..bef7f547 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/FormProtocol.swift @@ -0,0 +1,15 @@ +// +// Validatable.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/5/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +//Protocol for Validation +public protocol FormProtocol: class { + var formRules: [FormGroupRule]? { get set } + var formValidator: FormValidator? { get set } +} diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift b/MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift new file mode 100644 index 00000000..bc3bd023 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift @@ -0,0 +1,49 @@ +// +// FormRule.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/24/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +extension KeyedDecodingContainer where Key: CodingKey { + /// Decodes the list of molecule models with the given coding key based on moleculeName + public func decodeFormRules(codingKey: KeyedDecodingContainer.Key) throws -> [RulesProtocol] { + guard let models = try decodeModels(codingKey: codingKey, typeCodingKey: RulesCodingKey.ruleType) as? [RulesProtocol] else { + throw ModelRegistry.Error.decoderError + } + return models + } +} + + +open class FormGroupRule: Codable { +// public static var identifier: String = "formRule" + var groupName: String + var rules: [RulesProtocol] + + init(_ groupName: String, _ rules: [RulesProtocol]) { + self.groupName = groupName + self.rules = rules + } + + private enum CodingKeys: String, CodingKey { + case groupName + case rules + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + self.groupName = try typeContainer.decode(String.self, forKey: .groupName) + self.rules = try typeContainer.decodeFormRules(codingKey: .rules) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(groupName, forKey: .groupName) + try container.encodeModels(rules, forKey: .rules) + } +} + diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyModel.swift new file mode 100644 index 00000000..3e10b7af --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyModel.swift @@ -0,0 +1,20 @@ +// +// RuleAnyModel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/24/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class RuleAnyModel: RulesProtocol { + + public static var identifier: String = "any" + public var ruleType: String = RuleAnyModel.identifier + public var fields: [String] + + public func isValid(_ formField: FormFieldProtocol) -> Bool { + return false + } +} diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift new file mode 100644 index 00000000..7d1532d8 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift @@ -0,0 +1,20 @@ +// +// RuleEqualsModel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/24/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + + +public class RuleEqualsModel: RulesProtocol { + public static var identifier: String = "equals" + public var ruleType: String = RuleEqualsModel.identifier + public var fields: [String] + + public func isValid(_ formField: FormFieldProtocol) -> Bool { + return false + } +} diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift new file mode 100644 index 00000000..9ef00426 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift @@ -0,0 +1,19 @@ +// +// RuleRegexModel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/24/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class RuleRegexModel: RulesProtocol { + public static var identifier: String = "regex" + public var ruleType: String = RuleRegexModel.identifier + public var fields: [String] + + public func isValid(_ formField: FormFieldProtocol) -> Bool { + return false + } +} diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift new file mode 100644 index 00000000..400c5b1b --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift @@ -0,0 +1,30 @@ +// +// FormFieldRuleRequiredModel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/24/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + + +public class RuleRequiredModel: RulesProtocol { + + public static var identifier: String = "required" + public var ruleType: String = RuleRequiredModel.identifier + public var fields: [String] + + public func isValid(_ formField: FormFieldProtocol) -> Bool { + guard let value = formField.formFieldValue() else { + return false + } + var valid = true + if let valueString = value as? String { + valid = valueString.count > 3 + } else if let valueBool = value as? Bool { + valid = valueBool + } + return valid + } +} diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleValueChangeModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleValueChangeModel.swift new file mode 100644 index 00000000..221c4b5d --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleValueChangeModel.swift @@ -0,0 +1,20 @@ +// +// RuleValueChangeModel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/24/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class RuleValueChangeModel: RulesProtocol { + + public static var identifier: String = "valueChanged" + public var ruleType: String = RuleAnyModel.identifier + public var fields: [String] + + public func isValid(_ formField: FormFieldProtocol) -> Bool { + return false + } +} diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift new file mode 100644 index 00000000..97485d66 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift @@ -0,0 +1,61 @@ +// +// FormBaseRulesProtocol.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 1/31/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + + +public enum RulesCodingKey: String, CodingKey { + case ruleType +} + +public protocol RulesProtocol: ModelProtocol { + var ruleType: String { get set } + var fields: [String] { get set } + func isValid(_ formValidator: FormValidator) -> Bool + func isValid(_ formField: FormFieldProtocol) -> Bool + func setValid(_ formField: FormFieldProtocol, _ isValid: Bool) +} + +public extension RulesProtocol { + + var ruleType: String? { + get { return Self.identifier } + } + + static var categoryCodingKey: String { + return "ruleType" + } + + static var categoryName: String { + return "\(RulesProtocol.self)" + } + + func isValid(_ formValidator: FormValidator) -> Bool { + var valid = true + for formKey in fields { + guard let formField = formValidator.formField(for: formKey) else { + continue + } + valid = valid && isValid(formField) + if !valid { + setValid(formField, valid) + break + } else { + setValid(formField, valid) + } + } + return valid + } + + func setValid(_ formField: FormFieldProtocol, _ isValid: Bool) { + guard let formFieldValid = formField as? ValidProtocol else { + return + } + formFieldValid.setValidity(isValid) + } +} diff --git a/MVMCoreUI/FormUIHelpers/New/ValidProtocol.swift b/MVMCoreUI/FormUIHelpers/New/ValidProtocol.swift new file mode 100644 index 00000000..20afd256 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/ValidProtocol.swift @@ -0,0 +1,15 @@ +// +// ValidProtocol.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 3/2/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public protocol ValidProtocol { + var isValid: Bool? { get set } + func setValidity(_ isValid: Bool) + var updateUI: (() -> Void)? { get set } +} diff --git a/MVMCoreUI/Legacy/Views/MFTextField.m b/MVMCoreUI/Legacy/Views/MFTextField.m index fec796bf..691e6677 100644 --- a/MVMCoreUI/Legacy/Views/MFTextField.m +++ b/MVMCoreUI/Legacy/Views/MFTextField.m @@ -560,11 +560,11 @@ - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { [super setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) { - [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; - FormValidator *formValidator = [FormValidator getFormValidatorForDelegate:delegateObject.formValidationProtocol]; +// [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; +// FormValidator *formValidator = [FormValidator getFormValidatorForDelegate:delegateObject.formValidationProtocol]; [self setWithMap:json]; - self.mfTextFieldDelegate = formValidator; +// self.mfTextFieldDelegate = formValidator; self.uiTextFieldDelegate = delegateObject.uiTextFieldDelegate; [MVMCoreUICommonViewsUtility addDismissToolbar:self.textField delegate:self.uiTextFieldDelegate]; } diff --git a/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m index 40fa987f..cfa1d20b 100644 --- a/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m @@ -60,7 +60,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { - [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; +// [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; self.delegateObject = delegateObject; self.fieldKey = [json stringForKey:KeyFieldKey]; @@ -350,7 +350,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; [self.checkMark updateCheckSelected:NO animated:animated]; } - [FormValidator enableByValidationWithDelegate:self.delegateObject.formValidationProtocol]; +// [FormValidator enableByValidationWithDelegate:self.delegateObject.formValidationProtocol]; } - (void)setColor:(nullable UIColor *)color forState:(UIControlState)state { diff --git a/MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m b/MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m index 1c40bc5a..c12e70a5 100644 --- a/MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m +++ b/MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m @@ -147,7 +147,7 @@ const CGFloat SwitchShakeIntensity = 2; self.json = json; self.delegate = delegateObject; - [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; +// [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; NSString *color = [json string:@"onTintColor"]; if (color) { @@ -339,12 +339,11 @@ const CGFloat SwitchShakeIntensity = 2; [self setState:state withoutBlockAnimated:animated]; if (self.valueChangedBlock) { self.valueChangedBlock(); - } - - if (self.delegate && [self.delegate respondsToSelector:@selector(formValidationProtocol)] && [[self.delegate performSelector:@selector(formValidationProtocol)] respondsToSelector:@selector(formValidatorModel)]) { - FormValidator *formValidator = [[self.delegate performSelector:@selector(formValidationProtocol)] performSelector:@selector(formValidatorModel)]; - [formValidator enableByValidation]; - } + } +// if (self.delegate && [self.delegate respondsToSelector:@selector(formValidationProtocol)] && [[self.delegate performSelector:@selector(formValidationProtocol)] respondsToSelector:@selector(formValidatorModel)]) { +// FormValidator *formValidator = [[self.delegate performSelector:@selector(formValidationProtocol)] performSelector:@selector(formValidatorModel)]; +// [formValidator enableByValidation]; +// } } - (void)setState:(BOOL)state withoutBlockAnimated:(BOOL)animated { diff --git a/MVMCoreUI/Legacy/Views/PrimaryButton.m b/MVMCoreUI/Legacy/Views/PrimaryButton.m index 439d5479..f39edefc 100644 --- a/MVMCoreUI/Legacy/Views/PrimaryButton.m +++ b/MVMCoreUI/Legacy/Views/PrimaryButton.m @@ -671,7 +671,7 @@ self.validationRequired = [json boolForKey:@"required"]; self.requiredGroupsList = [json array:@"requiredGroups"]; - [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; +// [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; self.primaryButtonType = PrimaryButtonTypeCustom; NSString *style = [json string:@"style"]; diff --git a/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift index 3ed37d6b..a981ec64 100644 --- a/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift +++ b/MVMCoreUI/Models/ModelProtocols/TemplateModelProtocol.swift @@ -9,7 +9,7 @@ import Foundation -public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol { +public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol, FormProtocol { var template: String { get } } diff --git a/MVMCoreUI/Molecules/RadioButtonLabel.swift b/MVMCoreUI/Molecules/RadioButtonLabel.swift index e889b4f2..0db4e191 100644 --- a/MVMCoreUI/Molecules/RadioButtonLabel.swift +++ b/MVMCoreUI/Molecules/RadioButtonLabel.swift @@ -8,7 +8,7 @@ import UIKit -@objcMembers public class RadioButtonLabel: ViewConstrainingView { +@objcMembers public class RadioButtonLabel: View { public let radioButton = RadioButton() var delegateObject: MVMCoreUIDelegateObject? @@ -65,26 +65,12 @@ import UIKit let rightView = ViewConstrainingView(constrainingView: label) return rightView } -} - -// MARK: - MVMCoreUIMoleculeViewProtocol -extension RadioButtonLabel { - @objc open override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - self.delegateObject = delegateObject - radioButton.setWithJSON(json?.optionalDictionaryForKey("radioButton"), delegateObject: delegateObject, additionalData: additionalData) - label.setWithJSON(json?.optionalDictionaryForKey(KeyLabel), - delegateObject: delegateObject, - additionalData: additionalData) - } - - public override func reset() { - super.reset() - radioButton.reset() - label.reset() - } - - public override class func estimatedHeight(forRow json: [AnyHashable : Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { - return 45 - } + + open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let radioButtonLabelModel = model as? RadioButtonLabelModel else { return } + + radioButton.set(with: radioButtonLabelModel.radioButton, delegateObject, additionalData) + label.set(with: radioButtonLabelModel.label, delegateObject, additionalData) + } + } diff --git a/MVMCoreUI/Molecules/RadioButtonLabelModel.swift b/MVMCoreUI/Molecules/RadioButtonLabelModel.swift new file mode 100644 index 00000000..28a0f558 --- /dev/null +++ b/MVMCoreUI/Molecules/RadioButtonLabelModel.swift @@ -0,0 +1,17 @@ +// +// RadioButtonLabelModel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 3/3/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +@objcMembers public class RadioButtonLabelModel: MoleculeModelProtocol { + public static var identifier: String = "radioButtonLabel" + public var backgroundColor: Color? + + public var radioButton: RadioButtonModel + public var label: LabelModel +} diff --git a/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift b/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift index f20ac3b2..7505fca1 100644 --- a/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift +++ b/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift @@ -9,21 +9,25 @@ import Foundation import UIKit -@objcMembers public class RadioButtonSelectionHelper: NSObject { - +@objcMembers public class RadioButtonSelectionHelper: FormFieldProtocol { + public var fieldKey: String? private var selectedRadioButton: RadioButton? private var fieldGroupName: String? + + init(_ fieldKey: String?) { + self.fieldKey = fieldKey + } - public static func setupForRadioButtonGroup(radioButton: RadioButton, formValidator: FormValidator?) -> RadioButtonSelectionHelper { - guard let groupName = radioButton.radioGroupName, + public static func setupForRadioButtonGroup(_ radioButtonModel: RadioButtonModel, formValidator: FormValidator?) -> RadioButtonSelectionHelper { + guard let groupName = radioButtonModel.radioGroupName ?? radioButtonModel.fieldKey, let formValidator = formValidator else { - return RadioButtonSelectionHelper() + return RadioButtonSelectionHelper(radioButtonModel.fieldKey) } - let radioButtonModel = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonSelectionHelper() - radioButtonModel.fieldGroupName = radioButton.formFieldGroupName() - formValidator.radioButtonsModelByGroup[groupName] = radioButtonModel - return radioButtonModel + let radioButtonSelectionHelper = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonSelectionHelper(radioButtonModel.fieldKey) + radioButtonSelectionHelper.fieldGroupName = radioButtonModel.radioGroupName + formValidator.radioButtonsModelByGroup[groupName] = radioButtonSelectionHelper + return radioButtonSelectionHelper } public func selected(_ radioButton: RadioButton) { @@ -34,21 +38,12 @@ import UIKit } // MARK: - FormValidationFormFieldProtocol -extension RadioButtonSelectionHelper: FormValidationFormFieldProtocol { +extension RadioButtonSelectionHelper { public func formFieldGroupName() -> String? { return selectedRadioButton?.formFieldGroupName() ?? self.fieldGroupName } - // Used to check the validity of the field, to enable/disable the primary button. - @objc public func isValidField() -> Bool { - return selectedRadioButton != nil ? true : false - } - // Name of the field to send to server - @objc public func formFieldName() -> String? { - return selectedRadioButton?.fieldKey - } - // The field value key value pair for sending to server - @objc public func formFieldValue() -> Any? { - return selectedRadioButton != nil ? true : false + public func formFieldValue() -> Any? { + return selectedRadioButton?.formFieldValue() } } diff --git a/MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift b/MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift index f64162db..54de3802 100644 --- a/MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift +++ b/MVMCoreUI/OtherHandlers/MVMCoreUIDelegateObject.swift @@ -9,16 +9,18 @@ import UIKit open class MVMCoreUIDelegateObject: DelegateObject { - public weak var formValidationProtocol: FormValidationProtocol? + public weak var formHolderDelegate: FormHolderProtocol? public weak var buttonDelegate: ButtonDelegateProtocol? public weak var uiTextFieldDelegate: UITextFieldDelegate? + public weak var observingTextFieldDelegate: ObservingTextFieldDelegate? public var moleculeDelegate: MoleculeDelegateProtocol? open override func setAll(withDelegate delegate: Any) { super.setAll(withDelegate: delegate) - formValidationProtocol = delegate as? FormValidationProtocol + formHolderDelegate = delegate as? FormHolderProtocol buttonDelegate = delegate as? ButtonDelegateProtocol uiTextFieldDelegate = delegate as? UITextFieldDelegate + observingTextFieldDelegate = delegate as? ObservingTextFieldDelegate moleculeDelegate = delegate as? MoleculeDelegateProtocol } diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 34da2080..ae8f19fe 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -51,8 +51,9 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Toggle.self, viewModelClass: ToggleModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Checkbox.self, viewModelClass: CheckboxModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: CheckboxLabel.self, viewModelClass: CheckboxLabelModel.self) - MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: RadioButton.self, viewModelClass: RadioButtonModel.self) MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: Arrow.self, viewModelClass: ArrowModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: RadioButton.self, viewModelClass: RadioButtonModel.self) + MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: RadioButtonLabel.self, viewModelClass: RadioButtonLabelModel.self) // Horizontal Combination Molecules MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: StringAndMoleculeView.self, viewModelClass: StringAndMoleculeModel.self) @@ -113,10 +114,16 @@ import Foundation MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(DateDropdownEntryField.self, forKey: "dateDropdownEntryField" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(Checkbox.self, forKey: "checkbox" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(CheckboxLabel.self, forKey: "checkboxLabel" as NSString) - MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(RadioButtonLabel.self, forKey: "radioButtonLabel" as NSString) MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(MVMCoreUIPageControl.self, forKey: "barsPager" as NSString) // TODO: Need View try? ModelRegistry.register(TabsModel.self) + + // Helper models + try? ModelRegistry.register(RuleRequiredModel.self) + try? ModelRegistry.register(RuleAnyModel.self) + try? ModelRegistry.register(RuleValueChangeModel.self) + try? ModelRegistry.register(RuleEqualsModel.self) + try? ModelRegistry.register(RuleRegexModel.self) } } diff --git a/MVMCoreUI/Templates/ListPageTemplateModel.swift b/MVMCoreUI/Templates/ListPageTemplateModel.swift index 4ce4c6f5..5f8da7fc 100644 --- a/MVMCoreUI/Templates/ListPageTemplateModel.swift +++ b/MVMCoreUI/Templates/ListPageTemplateModel.swift @@ -9,6 +9,10 @@ import Foundation @objcMembers public class ListPageTemplateModel: TemplateModelProtocol { + + public var formRules: [FormGroupRule]? + public var formValidator: FormValidator? + //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -47,6 +51,7 @@ import Foundation case footer case line case isAtomicTabs + case formRules } //-------------------------------------------------- @@ -62,6 +67,7 @@ import Foundation header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header) footer = try typeContainer.decodeMoleculeIfPresent(codingKey: .footer) line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) + formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules) } public func encode(to encoder: Encoder) throws { @@ -73,6 +79,7 @@ import Foundation try container.encodeModelIfPresent(header, forKey: .header) try container.encodeModelIfPresent(footer, forKey: .footer) try container.encode(line, forKey: .line) + try container.encodeIfPresent(formRules, forKey: .formRules) } } diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 33d6beb0..360fc86e 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -12,7 +12,12 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol //-------------------------------------------------- // MARK: - Stored Properties //-------------------------------------------------- - + + public var formValidator: FormValidator? + public func validate() { + + } + public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]? var observer: NSKeyValueObservation? diff --git a/MVMCoreUI/Templates/MoleculeStackTemplate.swift b/MVMCoreUI/Templates/MoleculeStackTemplate.swift index e05a067a..6a895120 100644 --- a/MVMCoreUI/Templates/MoleculeStackTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeStackTemplate.swift @@ -9,6 +9,11 @@ import UIKit open class MoleculeStackTemplate: ThreeLayerViewController, TemplateProtocol { + public func validate() { + + } + + public var formValidator: FormValidator? var observer: NSKeyValueObservation? public var templateModel: StackPageTemplateModel? diff --git a/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift b/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift index 86c09b6d..66cd0365 100644 --- a/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift +++ b/MVMCoreUI/Templates/StackCenteredPageTemplateModel.swift @@ -10,8 +10,35 @@ import Foundation @objcMembers public class StackCenteredPageTemplateModel: TemplateModelProtocol { + public var formRules: [FormGroupRule]? + public var formValidator: FormValidator? + public static var identifier: String = "stackCenterTemplate" public var pageType: String public var screenHeading: String? public var isAtomicTabs: Bool? + + public init(pageType: String) { + self.pageType = pageType + } + + private enum CodingKeys: String, CodingKey { + case pageType + case screenHeading + case isAtomicTabs + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + pageType = try typeContainer.decode(String.self, forKey: .pageType) + screenHeading = try typeContainer.decodeIfPresent(String.self, forKey: .screenHeading) + isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(pageType, forKey: .pageType) + try container.encodeIfPresent(screenHeading, forKey: .screenHeading) + try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs) + } } diff --git a/MVMCoreUI/Templates/StackPageTemplateModel.swift b/MVMCoreUI/Templates/StackPageTemplateModel.swift index 10a2cf6f..1e5541eb 100644 --- a/MVMCoreUI/Templates/StackPageTemplateModel.swift +++ b/MVMCoreUI/Templates/StackPageTemplateModel.swift @@ -10,6 +10,9 @@ import Foundation @objcMembers public class StackPageTemplateModel: TemplateModelProtocol { + public var formRules: [FormGroupRule]? + public var formValidator: FormValidator? + public static var identifier: String = "stack" public var pageType: String @@ -32,6 +35,7 @@ import Foundation case footer case stack case isAtomicTabs + case formRules } required public init(from decoder: Decoder) throws { @@ -42,6 +46,7 @@ import Foundation isAtomicTabs = try typeContainer.decodeIfPresent(Bool.self, forKey: .isAtomicTabs) header = try typeContainer.decodeMoleculeIfPresent(codingKey: .header) footer = try typeContainer.decodeMoleculeIfPresent(codingKey: .footer) + formRules = try typeContainer.decodeIfPresent([FormGroupRule].self, forKey: .formRules) } public func encode(to encoder: Encoder) throws { @@ -52,5 +57,6 @@ import Foundation try container.encodeIfPresent(isAtomicTabs, forKey: .isAtomicTabs) try container.encodeModelIfPresent(header, forKey: .header) try container.encodeModelIfPresent(footer, forKey: .footer) + try container.encodeIfPresent(formRules, forKey: .formRules) } } diff --git a/MVMCoreUI/Templates/TemplateProtocol.swift b/MVMCoreUI/Templates/TemplateProtocol.swift index 63c66263..1e3dbdcc 100644 --- a/MVMCoreUI/Templates/TemplateProtocol.swift +++ b/MVMCoreUI/Templates/TemplateProtocol.swift @@ -8,18 +8,22 @@ import Foundation -public protocol TemplateProtocol: class { + +public protocol TemplateProtocol: FormHolderProtocol { associatedtype TemplateModel: TemplateModelProtocol var templateModel: TemplateModel? { get set } } public extension TemplateProtocol where Self: MFViewController { - func parseTemplateJSON() throws { guard let pageJSON = self.loadObject?.pageJSON else { return } let data = try JSONSerialization.data(withJSONObject: pageJSON) let decoder = JSONDecoder() let templateModel = try decoder.decode(TemplateModel.self, from: data) + + if self.formValidator == nil, let rules = templateModel.formRules { + self.formValidator = FormValidator(rules) + } self.templateModel = templateModel } } diff --git a/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift b/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift index 689a7c62..d22b6675 100644 --- a/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift +++ b/MVMCoreUI/Templates/ThreeLayerPageTemplateModel.swift @@ -9,6 +9,10 @@ import Foundation @objcMembers public class ThreeLayerPageTemplateModel: TemplateModelProtocol { + + public var formRules: [FormGroupRule]? + public var formValidator: FormValidator? + public static var identifier: String = "threeLayer" public var pageType: String diff --git a/MVMCoreUI/Templates/ThreeLayerTemplate.swift b/MVMCoreUI/Templates/ThreeLayerTemplate.swift index eb822279..148d102d 100644 --- a/MVMCoreUI/Templates/ThreeLayerTemplate.swift +++ b/MVMCoreUI/Templates/ThreeLayerTemplate.swift @@ -9,6 +9,11 @@ import UIKit @objcMembers open class ThreeLayerTemplate: ThreeLayerViewController, TemplateProtocol { + public func validate() { + + } + + public var formValidator: FormValidator? public var templateModel: ThreeLayerPageTemplateModel? From 9d8953d229304f08ee4437974dedb5f71096ceb8 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 4 Mar 2020 10:52:40 -0500 Subject: [PATCH 02/27] clean up --- MVMCoreUI.xcodeproj/project.pbxproj | 8 -- MVMCoreUI/Atoms/TextFields/EntryField.swift | 27 ----- MVMCoreUI/Atoms/Views/Toggle.swift | 110 +++++++----------- MVMCoreUI/BaseControllers/MFViewController.m | 2 +- .../FormValidationProtocol.swift | 41 ------- .../FormValidator+FormParams.swift | 10 -- MVMCoreUI/Legacy/Views/MFTextField.m | 27 +---- MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m | 19 +-- MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m | 20 +--- MVMCoreUI/Legacy/Views/PrimaryButton.m | 20 +--- 10 files changed, 50 insertions(+), 234 deletions(-) delete mode 100644 MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift delete mode 100644 MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index d15c400c..3dd1fad9 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -11,7 +11,6 @@ 0103B84E23D7E33A009C315C /* HeadlineBodyToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0103B84D23D7E33A009C315C /* HeadlineBodyToggleModel.swift */; }; 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618A224BBE7700E1557D /* FormValidator.swift */; }; 0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */; }; - 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */; }; 0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */; }; 011B58F023A2AA980085F53C /* ListItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */; }; 011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */; }; @@ -64,7 +63,6 @@ 017BEB4A236235BA0024EF95 /* ModelMoleculeViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */; }; 017BEB7B236763000024EF95 /* LineModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB7A236763000024EF95 /* LineModel.swift */; }; 017BEB7F23676E870024EF95 /* MoleculeObjectMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB7E23676E870024EF95 /* MoleculeObjectMapping.swift */; }; - 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0198F79E225679870066C936 /* FormValidationProtocol.swift */; }; 0198F7A62256A80B0066C936 /* MFRadioButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 0198F7A02256A80A0066C936 /* MFRadioButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0198F7A82256A80B0066C936 /* MFRadioButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 0198F7A22256A80A0066C936 /* MFRadioButton.m */; }; 01C851D323CF9E740021F976 /* LabelToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01C851D223CF9E740021F976 /* LabelToggleModel.swift */; }; @@ -381,7 +379,6 @@ 0103B84D23D7E33A009C315C /* HeadlineBodyToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyToggleModel.swift; sourceTree = ""; }; 0105618A224BBE7700E1557D /* FormValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidator.swift; sourceTree = ""; }; 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = ""; }; - 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+FormParams.swift"; sourceTree = ""; }; 0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonSelectionHelper.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 = ""; }; @@ -434,7 +431,6 @@ 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelMoleculeViewProtocol.swift; sourceTree = ""; }; 017BEB7A236763000024EF95 /* LineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineModel.swift; sourceTree = ""; }; 017BEB7E23676E870024EF95 /* MoleculeObjectMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeObjectMapping.swift; sourceTree = ""; }; - 0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = ""; }; 0198F7A02256A80A0066C936 /* MFRadioButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFRadioButton.h; sourceTree = ""; }; 0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = ""; }; 01C851D223CF9E740021F976 /* LabelToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelToggleModel.swift; sourceTree = ""; }; @@ -827,9 +823,7 @@ isa = PBXGroup; children = ( 011D9583240422BF000E3791 /* New */, - 0198F79E225679870066C936 /* FormValidationProtocol.swift */, 0105618A224BBE7700E1557D /* FormValidator.swift */, - 0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */, 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */, ); path = FormUIHelpers; @@ -1896,7 +1890,6 @@ 0A7EF85D23D8A95600B2AAD1 /* TextEntryFieldModel.swift in Sources */, D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, 01EB368F23609801006832FA /* LabelModel.swift in Sources */, - 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */, 01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */, 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */, 011B58F023A2AA980085F53C /* ListItemModelProtocol.swift in Sources */, @@ -1966,7 +1959,6 @@ 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */, D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */, D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */, - 0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */, D243859923A16B1800332775 /* Container.swift in Sources */, D2C521A923EDE79E00CA2634 /* ViewController.swift in Sources */, D260105B23D0BB7100764D80 /* StackModelProtocol.swift in Sources */, diff --git a/MVMCoreUI/Atoms/TextFields/EntryField.swift b/MVMCoreUI/Atoms/TextFields/EntryField.swift index bbea1c62..43a15a3b 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryField.swift @@ -48,8 +48,6 @@ import UIKit //-------------------------------------------------- public var isValid: Bool = false - public var fieldKey: String? - public var errorMessage: String? public var standardMessage: String? { didSet { @@ -259,10 +257,6 @@ import UIKit } else if let isSelected = model.isSelected{ self.isSelected = isSelected } - - if let fieldKey = model.fieldKey { - self.fieldKey = fieldKey - } } } @@ -300,11 +294,6 @@ extension EntryField { if let isSelected = dictionary["isSelected"] as? Bool { self.isSelected = isSelected } - - // Key used to send text value to server - if let fieldKey = dictionary[KeyFieldKey] as? String { - self.fieldKey = fieldKey - } } @objc open class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { @@ -312,22 +301,6 @@ extension EntryField { } } -// MARK: - Form Validation -extension EntryField: FormValidationProtocol { - - @objc public func isValidField() -> Bool { - return isValid - } - - @objc public func formFieldName() -> String? { - return fieldKey - } - - @objc public func formFieldValue() -> Any? { - return text - } -} - // MARK: - Accessibility extension EntryField { diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index c53b4be6..d6082292 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -19,7 +19,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) Container: The background of the toggle control. Knob: The circular indicator that slides on the container. */ -@objcMembers open class Toggle: Control, MVMCoreUIViewConstrainingProtocol, FormValidationFormFieldProtocol { +@objcMembers open class Toggle: Control, MVMCoreUIViewConstrainingProtocol { //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -339,82 +339,60 @@ public typealias ActionBlockConfirmation = () -> (Bool) return } + self.delegateObject = delegateObject let toggleModelJSON = toggleModel.toJSON() + + FormValidator.setupValidation(molecule: toggleModel, delegate: delegateObject?.formHolderDelegate) setWithJSON(toggleModelJSON, delegateObject: delegateObject, additionalData: additionalData) } + + //TODO: change to setWith Model + public override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { + super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) + + guard let dictionary = json else { return } + + if let color = dictionary["onTintColor"] as? String { + containerTintColor?.on = UIColor.mfGet(forHex: color) + } + + if let color = dictionary["offTintColor"] as? String { + containerTintColor?.off = UIColor.mfGet(forHex: color) + } + + if let color = dictionary["onKnobTintColor"] as? String { + knobTintColor?.on = UIColor.mfGet(forHex: color) + } + + if let color = dictionary["offKnobTintColor"] as? String { + knobTintColor?.off = UIColor.mfGet(forHex: color) + } + + if let state = dictionary["state"] as? Bool { + changeStateNoAnimation(state) + } + + if let actionMap = dictionary.optionalDictionaryForKey("action") { + didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } + } + + if let isAnimated = dictionary["isAnimated"] as? Bool { + self.isAnimated = isAnimated + } + + if let isEnabled = dictionary["isEnabled"] as? Bool{ + self.isEnabled = isEnabled + } + } public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { return Self.getContainerHeight() } } -// MARK: - Accessibility -extension Toggle { - - public func formFieldGroupName() -> String? { - return json?["groupName"] as? String - } -} - -// MARK: - FormValidationProtocol -extension Toggle { - - public func isValidField() -> Bool { - return isOn && json?["required"] as? Bool ?? false - } - - public func formFieldName() -> String? { - return json?[KeyFieldKey] as? String ?? "" - } - - public func formFieldValue() -> Any? { - return NSNumber(value: isOn) - } -} - // MARK: - MVMCoreUIMoleculeViewProtocol extension Toggle { - - public override func setWithJSON(_ json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { - super.setWithJSON(json, delegateObject: delegateObject, additionalData: additionalData) - self.delegateObject = delegateObject - -// FormValidator.setupValidation(molecule: self, delegate: delegateObject?.formValidationProtocol) - - guard let dictionary = json else { return } - - if let color = dictionary["onTintColor"] as? String { - containerTintColor?.on = UIColor.mfGet(forHex: color) - } - - if let color = dictionary["offTintColor"] as? String { - containerTintColor?.off = UIColor.mfGet(forHex: color) - } - - if let color = dictionary["onKnobTintColor"] as? String { - knobTintColor?.on = UIColor.mfGet(forHex: color) - } - - if let color = dictionary["offKnobTintColor"] as? String { - knobTintColor?.off = UIColor.mfGet(forHex: color) - } - - if let state = dictionary["state"] as? Bool { - changeStateNoAnimation(state) - } - - if let actionMap = dictionary.optionalDictionaryForKey("action") { - didToggleAction = { MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject) } - } - - if let isAnimated = dictionary["isAnimated"] as? Bool { - self.isAnimated = isAnimated - } - - if let isEnabled = dictionary["isEnabled"] as? Bool{ - self.isEnabled = isEnabled - } - } + public class func estimatedHeight(forRow json: [AnyHashable: Any]?, delegateObject: MVMCoreUIDelegateObject?) -> CGFloat { return Self.getContainerHeight() diff --git a/MVMCoreUI/BaseControllers/MFViewController.m b/MVMCoreUI/BaseControllers/MFViewController.m index 1af64e34..d15a1b9e 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.m +++ b/MVMCoreUI/BaseControllers/MFViewController.m @@ -38,7 +38,7 @@ #import @import MVMAnimationFramework; -@interface MFViewController() +@interface MFViewController() // A flag for if this view controller is observing for cache updates or not. @property (nonatomic) BOOL observingForResponseJSONUpdates; diff --git a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift b/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift deleted file mode 100644 index 49cfacc9..00000000 --- a/MVMCoreUI/FormUIHelpers/FormValidationProtocol.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// FormValidationProtocol.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 3/26/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - -@objc public protocol FormValidationProtocol: NSObjectProtocol { - - // Getter method to get the FormValidator from the delegate (Mostly from the parent View Controller) - @objc optional func formValidatorModel() -> FormValidator? -} - -@objc public protocol FormValidationFormFieldProtocol: FormValidationProtocol { - // Used to check the validity of the field. For example, to enable/disable the primary button. - @objc func isValidField() -> Bool - - // The Field name key value pair for sending to server - @objc func formFieldName() -> String? - - // Returns the group name for validation. The class should always return a value. - @objc func formFieldGroupName() -> String? - - // The Field value key value pair for sending to server - @objc func formFieldValue() -> Any? -} - -@objc public protocol FormValidationEnableDisableProtocol: FormValidationProtocol { - - // Returns true if the button needs to be enabled/disabled based on the validation - @objc func isValidationRequired() -> Bool - - // Based on the isValidField(), the fields which needs to be enabled can call this method - @objc optional func enableField(_ enable: Bool) - - // Returns the list of field keys required to enable/disable - @objc optional func requiredGroups() -> [String]? -} diff --git a/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift b/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift deleted file mode 100644 index 97668df4..00000000 --- a/MVMCoreUI/FormUIHelpers/FormValidator+FormParams.swift +++ /dev/null @@ -1,10 +0,0 @@ -// -// MVMCoreUIFormValidator+FormParams.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 3/21/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - diff --git a/MVMCoreUI/Legacy/Views/MFTextField.m b/MVMCoreUI/Legacy/Views/MFTextField.m index 691e6677..4ad018a4 100644 --- a/MVMCoreUI/Legacy/Views/MFTextField.m +++ b/MVMCoreUI/Legacy/Views/MFTextField.m @@ -18,7 +18,7 @@ @import MVMCore.NSDictionary_MFConvenience; @import MVMCore.MVMCoreJSONConstants; -@interface MFTextField() +@interface MFTextField() @property (strong, nonatomic) UIColor *customPlaceHolderColor; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *separatorHeightConstraint; @@ -560,11 +560,8 @@ - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { [super setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) { -// [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; -// FormValidator *formValidator = [FormValidator getFormValidatorForDelegate:delegateObject.formValidationProtocol]; - [self setWithMap:json]; -// self.mfTextFieldDelegate = formValidator; + self.mfTextFieldDelegate = delegateObject.uiTextFieldDelegate; self.uiTextFieldDelegate = delegateObject.uiTextFieldDelegate; [MVMCoreUICommonViewsUtility addDismissToolbar:self.textField delegate:self.uiTextFieldDelegate]; } @@ -574,24 +571,4 @@ + (CGFloat)estimatedHeightForRow:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject { return 76; } - -#pragma mark - FormValidationProtocol - - -- (BOOL)isValidField { - return self.isValid; -} - -- (nullable NSString *)formFieldName { - return self.fieldKey; -} - -- (nullable id)formFieldValue { - return self.text; -} - -- (NSString * _Nullable)formFieldGroupName { - return self.groupName; -} - @end diff --git a/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m index cfa1d20b..ab906bd7 100644 --- a/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m @@ -21,7 +21,7 @@ static const CGFloat FaultTolerance = 20.f; static const CGFloat CheckBoxHeightWidth = 18.0; -@interface MVMCoreUICheckBox () +@interface MVMCoreUICheckBox () @property (nonatomic, readwrite) BOOL isSelected; @property (weak, nonatomic) UIView *checkedSquare; @@ -109,23 +109,6 @@ static const CGFloat CheckBoxHeightWidth = 18.0; return checkBox; } -#pragma mark - FormValidationProtocol - -- (BOOL)isValidField { - if (self.isRequired) { - return self.isSelected; - } - return true; -} - -- (nullable NSString *)formFieldName { - return self.fieldKey; -} - -- (nullable id)formFieldValue { - return @(self.isSelected); -} - #pragma mark - inits - (instancetype)init { diff --git a/MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m b/MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m index c12e70a5..e4c3c38b 100644 --- a/MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m +++ b/MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m @@ -22,7 +22,7 @@ const CGFloat SwitchKnobWidth = 20; const CGFloat SwitchKnobHeight = 20; const CGFloat SwitchShakeIntensity = 2; -@interface MVMCoreUISwitch () +@interface MVMCoreUISwitch () @property (weak, nonatomic) UIView *baseView; @property (weak, nonatomic) UIView *knobView; @@ -426,22 +426,4 @@ const CGFloat SwitchShakeIntensity = 2; return [MVMCoreUIUtility hardcodedStringWithKey:@"AccToggleHint"]; } -#pragma mark FormValidationProtocol - -- (NSString * _Nullable)formFieldGroupName { - return [self.json string:@"groupName"]; -} - -- (BOOL)isValidField { - return self.isOn && [self.json boolForKey:@"required"]; -} - -- (NSString *)formFieldName { - return [self.json string:KeyFieldKey]; -} - -- (id)formFieldValue { - return @(self.isOn); -} - @end diff --git a/MVMCoreUI/Legacy/Views/PrimaryButton.m b/MVMCoreUI/Legacy/Views/PrimaryButton.m index f39edefc..4ced32ac 100644 --- a/MVMCoreUI/Legacy/Views/PrimaryButton.m +++ b/MVMCoreUI/Legacy/Views/PrimaryButton.m @@ -18,7 +18,7 @@ @import MVMCore.MVMCoreGetterUtility; @import MVMCore.NSDictionary_MFConvenience; -@interface PrimaryButton() +@interface PrimaryButton() @property (nonatomic) BOOL smallButton; @property (assign, nonatomic) BOOL tinyButton; @@ -781,22 +781,4 @@ } } -#pragma mark - FormValidationEnableDisableProtocol - -- (BOOL)isValidationRequired { - return self.validationRequired; -} - -- (NSArray *)requiredGroups { - return self.requiredGroupsList; -} - -- (void)enableField:(BOOL)enable { - if (!self.validationRequired) { - self.enabled = YES; - } else { - self.enabled = enable; - } -} - @end From 97cf39eaeedbad590b74eae48a0b9419787f8051 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 4 Mar 2020 15:17:45 -0500 Subject: [PATCH 03/27] textfield enhancement --- MVMCoreUI/Atoms/TextFields/TextEntryField.swift | 15 ++++++--------- MVMCoreUI/Atoms/Views/Toggle.swift | 4 +++- MVMCoreUI/BaseControllers/MFViewController.m | 4 ++-- .../FormUIHelpers/New/Rules/RulesProtocol.swift | 10 +++------- MVMCoreUI/Legacy/Views/MFTextField.m | 3 +-- 5 files changed, 15 insertions(+), 21 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index 870d669a..49fb0953 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -45,7 +45,7 @@ import UIKit private var observingForChange: Bool = false /// Validate on each entry in the textField. Default: false - public var validateEachCharacter: Bool = false + public var validateEachCharacter: Bool = true /// Validate when user resigns editing. Default: true public var validateWhenDoneEditing: Bool = true @@ -233,18 +233,17 @@ import UIKit } @objc public func updateValidation(_ isValid: Bool) { + let previousValidity = self.isValid self.isValid = isValid - if isValid { - showError = false - observingTextFieldDelegate?.isValid?(textfield: self) - } else { + if previousValidity && !isValid { showError = true observingTextFieldDelegate?.isInvalid?(textfield: self) + } else if (!previousValidity && isValid) { + showError = false + observingTextFieldDelegate?.isValid?(textfield: self) } } - - /// Executes on UITextField.textDidBeginEditingNotification @objc func startEditing() { @@ -254,9 +253,7 @@ import UIKit /// Executes on UITextField.textDidChangeNotification (each character entry) @objc func valueChanged() { - guard validateEachCharacter else { return } - validateTextField() } diff --git a/MVMCoreUI/Atoms/Views/Toggle.swift b/MVMCoreUI/Atoms/Views/Toggle.swift index d6082292..7e45c567 100644 --- a/MVMCoreUI/Atoms/Views/Toggle.swift +++ b/MVMCoreUI/Atoms/Views/Toggle.swift @@ -100,7 +100,8 @@ public typealias ActionBlockConfirmation = () -> (Bool) knobView.backgroundColor = isOn ? knobTintColor?.on : knobTintColor?.off self.constrainKnob() } - + + (model as? ToggleModel)?.state = isOn FormValidator.validate(delegate: delegateObject?.formHolderDelegate) accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") setNeedsLayout() @@ -339,6 +340,7 @@ public typealias ActionBlockConfirmation = () -> (Bool) return } + self.model = model self.delegateObject = delegateObject let toggleModelJSON = toggleModel.toJSON() diff --git a/MVMCoreUI/BaseControllers/MFViewController.m b/MVMCoreUI/BaseControllers/MFViewController.m index d15a1b9e..fef3b860 100644 --- a/MVMCoreUI/BaseControllers/MFViewController.m +++ b/MVMCoreUI/BaseControllers/MFViewController.m @@ -468,7 +468,7 @@ // Since we have new data, build stuff for the screen and update the ui once the screen is done laying out. [self newDataBuildAndUpdate]; - + self.needToupdateUIOnScreenSizeChanges = YES; if (UIAccessibilityIsVoiceOverRunning()) { @@ -479,12 +479,12 @@ [self setupIntroAnimations]; } - [self startValidation]; } - (void)newDataBuildAndUpdate { [MVMCoreDispatchUtility performBlockOnMainThread:^{ [self newDataBuildScreen]; + [self startValidation]; self.needToUpdateUI = YES; [self.view setNeedsLayout]; }]; diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift index 97485d66..536bf468 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift @@ -41,13 +41,9 @@ public extension RulesProtocol { guard let formField = formValidator.formField(for: formKey) else { continue } - valid = valid && isValid(formField) - if !valid { - setValid(formField, valid) - break - } else { - setValid(formField, valid) - } + let fieldValidity = isValid(formField) + setValid(formField, fieldValidity) + valid = valid && fieldValidity } return valid } diff --git a/MVMCoreUI/Legacy/Views/MFTextField.m b/MVMCoreUI/Legacy/Views/MFTextField.m index 4ad018a4..081f9fe8 100644 --- a/MVMCoreUI/Legacy/Views/MFTextField.m +++ b/MVMCoreUI/Legacy/Views/MFTextField.m @@ -560,8 +560,7 @@ - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { [super setWithJSON:json delegateObject:delegateObject additionalData:additionalData]; if ([delegateObject isKindOfClass:[MVMCoreUIDelegateObject class]]) { - [self setWithMap:json]; - self.mfTextFieldDelegate = delegateObject.uiTextFieldDelegate; + [self setWithMap:json]; self.uiTextFieldDelegate = delegateObject.uiTextFieldDelegate; [MVMCoreUICommonViewsUtility addDismissToolbar:self.textField delegate:self.uiTextFieldDelegate]; } From 1bbfb0390a89ad52fd3e06cd9bd21de5a30f3371 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 6 Mar 2020 10:51:09 -0500 Subject: [PATCH 04/27] fixes --- MVMCoreUI.xcodeproj/project.pbxproj | 4 --- MVMCoreUI/Atoms/Buttons/ButtonModel.swift | 6 +++-- .../Atoms/TextFields/EntryFieldModel.swift | 8 +++++- .../Atoms/TextFields/TextEntryField.swift | 6 ++--- .../Atoms/TextFields/TextFieldModel.swift | 2 +- MVMCoreUI/Atoms/Views/CheckboxModel.swift | 6 +++++ MVMCoreUI/Atoms/Views/RadioButton.swift | 4 +-- MVMCoreUI/Atoms/Views/RadioButtonModel.swift | 2 +- MVMCoreUI/Atoms/Views/ToggleModel.swift | 9 ++++--- MVMCoreUI/FormUIHelpers/FormValidator.swift | 27 +++++++++++++++---- .../New/FormActionFieldProtocol.swift | 3 +-- .../FormUIHelpers/New/FormFieldProtocol.swift | 2 +- .../FormUIHelpers/New/FormItemProtocol.swift | 8 +++++- .../New/Rules/RuleRequiredModel.swift | 2 +- .../ModelProtocols/FormModelProtocol.swift | 16 ----------- .../RadioButtonSelectionHelper.swift | 5 ++-- 16 files changed, 64 insertions(+), 46 deletions(-) delete mode 100644 MVMCoreUI/Models/ModelProtocols/FormModelProtocol.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 3dd1fad9..113ebc13 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -57,7 +57,6 @@ 017BEB382360C6AC0024EF95 /* RadioButtonLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */; }; 017BEB3C2361EA1D0024EF95 /* MFViewController+Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */; }; 017BEB4023620A230024EF95 /* TextFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB3F23620A230024EF95 /* TextFieldModel.swift */; }; - 017BEB4223620AD20024EF95 /* FormModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB4123620AD20024EF95 /* FormModelProtocol.swift */; }; 017BEB442362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB432362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift */; }; 017BEB48236230DB0024EF95 /* MoleculeViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */; }; 017BEB4A236235BA0024EF95 /* ModelMoleculeViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */; }; @@ -425,7 +424,6 @@ 017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonLabel.swift; sourceTree = ""; }; 017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFViewController+Model.swift"; sourceTree = ""; }; 017BEB3F23620A230024EF95 /* TextFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldModel.swift; sourceTree = ""; }; - 017BEB4123620AD20024EF95 /* FormModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormModelProtocol.swift; sourceTree = ""; }; 017BEB432362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUIMoleculeMappingObject+ModelExtension.swift"; sourceTree = ""; }; 017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeViewProtocol.swift; sourceTree = ""; }; 017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelMoleculeViewProtocol.swift; sourceTree = ""; }; @@ -762,7 +760,6 @@ isa = PBXGroup; children = ( 014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */, - 017BEB4123620AD20024EF95 /* FormModelProtocol.swift */, 012A88C3238D86E600FE3DA1 /* CarouselItemModelProtocol.swift */, 012A88B0238C880100FE3DA1 /* CarouselPagingModelProtocol.swift */, 01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */, @@ -1947,7 +1944,6 @@ D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */, C695A67F23C9830600BFB94E /* UnOrderedListModel.swift in Sources */, 0AE98BB523FF18D2004C5109 /* Arrow.swift in Sources */, - 017BEB4223620AD20024EF95 /* FormModelProtocol.swift in Sources */, D2D90B442404789000DD6EC9 /* MoleculeContainerProtocol.swift in Sources */, 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */, D29DF28C21E7AC2B003B2FB9 /* ViewConstrainingView.m in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift index 77b7addc..2826ac03 100644 --- a/MVMCoreUI/Atoms/Buttons/ButtonModel.swift +++ b/MVMCoreUI/Atoms/Buttons/ButtonModel.swift @@ -33,7 +33,7 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormAction public var disabledFillColor: Color? public var disabledTextColor: Color? public var disabledBorderColor: Color? - public var groupName: String? + public var groupName: String? = FormValidator.defaultGroupName public func updateEnable(_ enabled: Bool) { self.enabled = enabled @@ -82,7 +82,9 @@ public class ButtonModel: ButtonModelProtocol, MoleculeModelProtocol, FormAction 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) - groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { + self.groupName = groupName + } if let style = try typeContainer.decodeIfPresent(ButtonStyle.self, forKey: .style) { self.style = style } diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index e9ca5e65..5ccb67d7 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -27,7 +27,7 @@ import Foundation public var isLocked: Bool? public var isSelected: Bool? public var fieldKey: String? - public var isRequired: Bool? + public var groupName: String? = FormValidator.defaultGroupName public var text: String? public var isValid: Bool? { @@ -57,6 +57,7 @@ import Foundation case isValid case isRequired = "required" case text + case groupName } public func formFieldValue() -> Any? { @@ -79,6 +80,10 @@ import Foundation fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) isValid = try typeContainer.decodeIfPresent(Bool.self, forKey: .isValid) text = try typeContainer.decodeIfPresent(String.self, forKey: .text) + + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { + self.groupName = groupName + } } public func encode(to encoder: Encoder) throws { @@ -94,5 +99,6 @@ import Foundation try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(isValid, forKey: .isValid) try container.encodeIfPresent(text, forKey: .text) + try container.encodeIfPresent(groupName, forKey: .groupName) } } diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index 49fb0953..993aed59 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -197,9 +197,8 @@ import UIKit @objc deinit { setBothTextDelegates(to: nil) } - + @objc public func setBothTextDelegates(to delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?) { - observingTextFieldDelegate = delegate uiTextFieldDelegate = delegate } @@ -246,7 +245,6 @@ import UIKit } /// Executes on UITextField.textDidBeginEditingNotification @objc func startEditing() { - isSelected = true textField.becomeFirstResponder() } @@ -254,6 +252,7 @@ import UIKit /// Executes on UITextField.textDidChangeNotification (each character entry) @objc func valueChanged() { guard validateEachCharacter else { return } + isSelected = true validateTextField() } @@ -310,7 +309,6 @@ import UIKit defaultValidationBlock() } -// observingTextFieldDelegate = FormValidator.getFormValidatorFor(delegate: delegateObject?.formHolderDelegate) uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate) diff --git a/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift b/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift index e26995d6..d901d13a 100644 --- a/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/TextFieldModel.swift @@ -8,7 +8,7 @@ import UIKit -@objcMembers public class TextFieldModel: MoleculeModelProtocol, FormModelProtocol { +@objcMembers public class TextFieldModel: MoleculeModelProtocol { public static var identifier: String = "textField" public var backgroundColor: Color? diff --git a/MVMCoreUI/Atoms/Views/CheckboxModel.swift b/MVMCoreUI/Atoms/Views/CheckboxModel.swift index 60aade23..77fffecd 100644 --- a/MVMCoreUI/Atoms/Views/CheckboxModel.swift +++ b/MVMCoreUI/Atoms/Views/CheckboxModel.swift @@ -32,6 +32,7 @@ import Foundation public var disabledCheckColor: Color = Color(uiColor: .mvmCoolGray3) public var fieldKey: String? + public var groupName: String? = FormValidator.defaultGroupName //-------------------------------------------------- // MARK: - Keys @@ -53,6 +54,7 @@ import Foundation case isRound case isEnabled case action + case groupName } init(isChecked: Bool = false) {} @@ -81,6 +83,9 @@ import Foundation isRound = try typeContainer.decodeIfPresent(Bool.self, forKey: .isRound) ?? false isEnabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? true action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { + self.groupName = groupName + } } public func encode(to encoder: Encoder) throws { @@ -100,5 +105,6 @@ import Foundation try container.encodeIfPresent(isRound, forKey: .isRound) try container.encodeIfPresent(isEnabled, forKey: .isEnabled) try container.encodeModelIfPresent(action, forKey: .action) + try container.encodeIfPresent(groupName, forKey: .groupName) } } diff --git a/MVMCoreUI/Atoms/Views/RadioButton.swift b/MVMCoreUI/Atoms/Views/RadioButton.swift index f6484326..2883c4ec 100644 --- a/MVMCoreUI/Atoms/Views/RadioButton.swift +++ b/MVMCoreUI/Atoms/Views/RadioButton.swift @@ -33,7 +33,7 @@ import UIKit } lazy var radioGroupName: String? = { - [unowned self] in return radioModel?.radioGroupName ?? radioModel?.fieldKey + [unowned self] in return radioModel?.fieldKey }() lazy var radioButtonSelectionHelper: RadioButtonSelectionHelper? = { @@ -80,7 +80,7 @@ import UIKit } public func formFieldGroupName() -> String? { - return radioModel?.radioGroupName + return radioModel?.fieldKey } public func formFieldValue() -> String? { diff --git a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift index a058ada6..f185971d 100644 --- a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift +++ b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift @@ -14,8 +14,8 @@ public class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { public static var identifier: String = "radioButton" public var backgroundColor: Color? public var state: Bool? = false - public var radioGroupName: String? public var fieldKey: String? + public var groupName: String? = FormValidator.defaultGroupName public var fieldValue: String public func formFieldValue() -> Any? { return fieldValue diff --git a/MVMCoreUI/Atoms/Views/ToggleModel.swift b/MVMCoreUI/Atoms/Views/ToggleModel.swift index 54c86514..14f43d02 100644 --- a/MVMCoreUI/Atoms/Views/ToggleModel.swift +++ b/MVMCoreUI/Atoms/Views/ToggleModel.swift @@ -15,8 +15,8 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { public var state: Bool = true public var action: ActionModelProtocol? public var alternateAction: ActionModelProtocol? - public var required: Bool? public var fieldKey: String? + public var groupName: String? = FormValidator.defaultGroupName private enum CodingKeys: String, CodingKey { case moleculeName @@ -26,6 +26,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { case required case fieldKey case alternateAction + case groupName } public func formFieldValue() -> Any? { @@ -44,8 +45,10 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { action = try typeContainer.decodeModelIfPresent(codingKey: .action, typeCodingKey: ActionCodingKey.actionType) alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction, typeCodingKey: ActionCodingKey.actionType) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { + self.groupName = groupName + } } public func encode(to encoder: Encoder) throws { @@ -55,7 +58,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction) try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(state, forKey: .state) - try container.encodeIfPresent(required, forKey: .required) try container.encodeIfPresent(fieldKey, forKey: .fieldKey) + try container.encodeIfPresent(groupName, forKey: .groupName) } } diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index fd4dd6e8..d3f238af 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -11,9 +11,8 @@ import MVMCore @objcMembers public class FormValidator: NSObject { + static var defaultGroupName: String = "default" var extraValidationBlock: (() -> Bool)? - var dummyGroupName = "dummyGroupName" - var formRules: [FormGroupRule] var delegate: FormHolderProtocol? var fieldMolecules: [FormFieldProtocol] = [] @@ -75,15 +74,19 @@ import MVMCore // mark Form params @objc public extension FormValidator { @objc func addFormParams(requestParameters: MVMCoreRequestParameters) { - requestParameters.add(self.getFormParams()) + let formButton = getFormButton(forPageType: requestParameters.pageType) + let groupName = formButton?.groupName ?? FormValidator.defaultGroupName + let formParams = self.getFormParams(forGroup: groupName) + requestParameters.add(formParams) } - @objc func getFormParams() -> [String: Any] { + @objc func getFormParams( forGroup groupName: String) -> [String: Any] { var extraParam: [String: Any] = [:] MVMCoreDispatchUtility.performSyncBlock(onMainThread: { for molecule in self.fieldMolecules { if let formFieldName = molecule.fieldKey, - let formFieldValue = molecule.formFieldValue() { + let formFieldValue = molecule.formFieldValue(), + groupName == molecule.groupName { extraParam[formFieldName] = formFieldValue } } @@ -91,3 +94,17 @@ import MVMCore return extraParam } } + +// Temporary +public extension FormValidator { + func getFormButton(forPageType pageType: String?) -> ButtonModel? { + for actionItem in formActionMolecules { + if let buttonModel = actionItem as? ButtonModel, + pageType == (buttonModel.action as? ActionOpenPageModel)?.pageType { + return buttonModel + } + } + return nil + } +} + diff --git a/MVMCoreUI/FormUIHelpers/New/FormActionFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormActionFieldProtocol.swift index 2f4b758d..31208e95 100644 --- a/MVMCoreUI/FormUIHelpers/New/FormActionFieldProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/FormActionFieldProtocol.swift @@ -8,8 +8,7 @@ import Foundation -public protocol FormActionFieldProtocol: EnableableModelProtocol, FormItemProtocol { - var groupName: String? { get set } +public protocol FormActionFieldProtocol: EnableableModelProtocol, FormItemProtocol { func updateEnable(_ enabled: Bool) var updateUI: (() -> Void)? { get set } } diff --git a/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift index d6073943..9ba8ad4d 100644 --- a/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift @@ -10,6 +10,6 @@ import Foundation public protocol FormFieldProtocol: FormItemProtocol { - var fieldKey: String? { get set } + var fieldKey: String? { get set } func formFieldValue() -> Any? } diff --git a/MVMCoreUI/FormUIHelpers/New/FormItemProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormItemProtocol.swift index 47911f0c..9b671238 100644 --- a/MVMCoreUI/FormUIHelpers/New/FormItemProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/FormItemProtocol.swift @@ -9,5 +9,11 @@ import Foundation public protocol FormItemProtocol { - + static var defaultGroupName: String? { get } + var groupName: String? { get set } +} +extension FormItemProtocol{ + public static var defaultGroupName: String? { + return "default" + } } diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift index 400c5b1b..252808a0 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift @@ -21,7 +21,7 @@ public class RuleRequiredModel: RulesProtocol { } var valid = true if let valueString = value as? String { - valid = valueString.count > 3 + valid = valueString.count > 0 } else if let valueBool = value as? Bool { valid = valueBool } diff --git a/MVMCoreUI/Models/ModelProtocols/FormModelProtocol.swift b/MVMCoreUI/Models/ModelProtocols/FormModelProtocol.swift deleted file mode 100644 index 28840f06..00000000 --- a/MVMCoreUI/Models/ModelProtocols/FormModelProtocol.swift +++ /dev/null @@ -1,16 +0,0 @@ -// -// FormModelProtocol.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 10/24/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - - -public protocol FormModelProtocol: ModelProtocol { - var required: Bool? { get } - var fieldKey: String? { get } - var groupName: String? { get } -} diff --git a/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift b/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift index 7505fca1..8297a2a3 100644 --- a/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift +++ b/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift @@ -11,6 +11,7 @@ import UIKit @objcMembers public class RadioButtonSelectionHelper: FormFieldProtocol { public var fieldKey: String? + public var groupName: String? = FormValidator.defaultGroupName private var selectedRadioButton: RadioButton? private var fieldGroupName: String? @@ -19,13 +20,13 @@ import UIKit } public static func setupForRadioButtonGroup(_ radioButtonModel: RadioButtonModel, formValidator: FormValidator?) -> RadioButtonSelectionHelper { - guard let groupName = radioButtonModel.radioGroupName ?? radioButtonModel.fieldKey, + guard let groupName = radioButtonModel.fieldKey, let formValidator = formValidator else { return RadioButtonSelectionHelper(radioButtonModel.fieldKey) } let radioButtonSelectionHelper = formValidator.radioButtonsModelByGroup[groupName] ?? RadioButtonSelectionHelper(radioButtonModel.fieldKey) - radioButtonSelectionHelper.fieldGroupName = radioButtonModel.radioGroupName + radioButtonSelectionHelper.fieldGroupName = radioButtonModel.fieldKey formValidator.radioButtonsModelByGroup[groupName] = radioButtonSelectionHelper return radioButtonSelectionHelper } From 521ad8711df8868476d9b598d3adb2c0de284137 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 6 Mar 2020 17:26:42 -0500 Subject: [PATCH 05/27] value changed rules --- MVMCoreUI.xcodeproj/project.pbxproj | 16 +++++----- .../Atoms/TextFields/EntryFieldModel.swift | 9 ++++-- MVMCoreUI/Atoms/Views/CheckboxModel.swift | 6 ++-- MVMCoreUI/Atoms/Views/RadioButton.swift | 7 ++-- MVMCoreUI/Atoms/Views/RadioButtonModel.swift | 20 ++++++------ MVMCoreUI/Atoms/Views/ToggleModel.swift | 5 +-- MVMCoreUI/FormUIHelpers/FormValidator.swift | 3 +- .../FormUIHelpers/New/FormFieldProtocol.swift | 9 +++++- ...l.swift => RuleAllValueChangedModel.swift} | 8 ++--- .../New/Rules/RuleAnyModel.swift | 20 ------------ .../New/Rules/RuleAnyValueChangedModel.swift | 32 +++++++++++++++++++ .../RadioButtonSelectionHelper.swift | 5 ++- .../OtherHandlers/MoleculeObjectMapping.swift | 4 +-- 13 files changed, 88 insertions(+), 56 deletions(-) rename MVMCoreUI/FormUIHelpers/New/Rules/{RuleValueChangeModel.swift => RuleAllValueChangedModel.swift} (53%) delete mode 100644 MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyModel.swift create mode 100644 MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyValueChangedModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 113ebc13..b29cdf75 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -18,8 +18,8 @@ 011D958724042492000E3791 /* FormFieldProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D958624042492000E3791 /* FormFieldProtocol.swift */; }; 011D95892404249B000E3791 /* FormProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95882404249B000E3791 /* FormProtocol.swift */; }; 011D959B240451E3000E3791 /* RuleRequiredModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959A240451E3000E3791 /* RuleRequiredModel.swift */; }; - 011D959D2404536F000E3791 /* RuleAnyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959C2404536F000E3791 /* RuleAnyModel.swift */; }; - 011D959F240453A1000E3791 /* RuleValueChangeModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959E240453A1000E3791 /* RuleValueChangeModel.swift */; }; + 011D959D2404536F000E3791 /* RuleAnyValueChangedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */; }; + 011D959F240453A1000E3791 /* RuleAllValueChangedModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D959E240453A1000E3791 /* RuleAllValueChangedModel.swift */; }; 011D95A1240453D0000E3791 /* RuleEqualsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95A0240453D0000E3791 /* RuleEqualsModel.swift */; }; 011D95A3240453F8000E3791 /* RuleRegexModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95A2240453F8000E3791 /* RuleRegexModel.swift */; }; 011D95A5240455DC000E3791 /* FormGroupRule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011D95A4240455DC000E3791 /* FormGroupRule.swift */; }; @@ -385,8 +385,8 @@ 011D958624042492000E3791 /* FormFieldProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormFieldProtocol.swift; sourceTree = ""; }; 011D95882404249B000E3791 /* FormProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormProtocol.swift; sourceTree = ""; }; 011D959A240451E3000E3791 /* RuleRequiredModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleRequiredModel.swift; sourceTree = ""; }; - 011D959C2404536F000E3791 /* RuleAnyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModel.swift; sourceTree = ""; }; - 011D959E240453A1000E3791 /* RuleValueChangeModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleValueChangeModel.swift; sourceTree = ""; }; + 011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyValueChangedModel.swift; sourceTree = ""; }; + 011D959E240453A1000E3791 /* RuleAllValueChangedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAllValueChangedModel.swift; sourceTree = ""; }; 011D95A0240453D0000E3791 /* RuleEqualsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleEqualsModel.swift; sourceTree = ""; }; 011D95A2240453F8000E3791 /* RuleRegexModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleRegexModel.swift; sourceTree = ""; }; 011D95A4240455DC000E3791 /* FormGroupRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormGroupRule.swift; sourceTree = ""; }; @@ -790,8 +790,8 @@ children = ( 011D958424042432000E3791 /* RulesProtocol.swift */, 011D959A240451E3000E3791 /* RuleRequiredModel.swift */, - 011D959C2404536F000E3791 /* RuleAnyModel.swift */, - 011D959E240453A1000E3791 /* RuleValueChangeModel.swift */, + 011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */, + 011D959E240453A1000E3791 /* RuleAllValueChangedModel.swift */, 011D95A0240453D0000E3791 /* RuleEqualsModel.swift */, 011D95A2240453F8000E3791 /* RuleRegexModel.swift */, 011D95A4240455DC000E3791 /* FormGroupRule.swift */, @@ -2010,7 +2010,7 @@ D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */, 014AA72E23C5059B006F3E93 /* StackCenteredPageTemplateModel.swift in Sources */, D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */, - 011D959D2404536F000E3791 /* RuleAnyModel.swift in Sources */, + 011D959D2404536F000E3791 /* RuleAnyValueChangedModel.swift in Sources */, D260105923D0A92900764D80 /* ContainerProtocol.swift in Sources */, C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */, D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */, @@ -2028,7 +2028,7 @@ D22D1F1B220341F60077CEC0 /* MVMCoreUICheckBox.m in Sources */, C695A69823C990C200BFB94E /* DoughnutChartView.swift in Sources */, D29DF2CB21E7BFCC003B2FB9 /* MFSizeThreshold.m in Sources */, - 011D959F240453A1000E3791 /* RuleValueChangeModel.swift in Sources */, + 011D959F240453A1000E3791 /* RuleAllValueChangedModel.swift in Sources */, 011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */, 946EE1BA237B66D80036751F /* MoleculeModelHelper.swift in Sources */, 01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */, diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index 5ccb67d7..2b2ef27b 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -29,6 +29,7 @@ import Foundation public var fieldKey: String? public var groupName: String? = FormValidator.defaultGroupName public var text: String? + public var baseValue: JSONValue? public var isValid: Bool? { didSet { @@ -60,8 +61,12 @@ import Foundation case groupName } - public func formFieldValue() -> Any? { - return text + public func formFieldValue() -> JSONValue? { + if let text = text { + return JSONValue(stringLiteral: text) + } else { + return nil + } } //-------------------------------------------------- diff --git a/MVMCoreUI/Atoms/Views/CheckboxModel.swift b/MVMCoreUI/Atoms/Views/CheckboxModel.swift index 77fffecd..cf7f7298 100644 --- a/MVMCoreUI/Atoms/Views/CheckboxModel.swift +++ b/MVMCoreUI/Atoms/Views/CheckboxModel.swift @@ -9,7 +9,6 @@ import Foundation @objcMembers public class CheckboxModel: MoleculeModelProtocol, FormFieldProtocol { - //-------------------------------------------------- // MARK: - Properties //-------------------------------------------------- @@ -33,6 +32,7 @@ import Foundation public var fieldKey: String? public var groupName: String? = FormValidator.defaultGroupName + public var baseValue: JSONValue? //-------------------------------------------------- // MARK: - Keys @@ -59,8 +59,8 @@ import Foundation init(isChecked: Bool = false) {} - public func formFieldValue() -> Any? { - return isChecked + public func formFieldValue() -> JSONValue? { + return JSONValue(booleanLiteral: isChecked) } //-------------------------------------------------- diff --git a/MVMCoreUI/Atoms/Views/RadioButton.swift b/MVMCoreUI/Atoms/Views/RadioButton.swift index 2883c4ec..49625eb2 100644 --- a/MVMCoreUI/Atoms/Views/RadioButton.swift +++ b/MVMCoreUI/Atoms/Views/RadioButton.swift @@ -83,8 +83,11 @@ import UIKit return radioModel?.fieldKey } - public func formFieldValue() -> String? { - return radioModel?.fieldValue + public func formFieldValue() -> JSONValue? { + if let fieldValue = radioModel?.fieldValue { + return JSONValue(stringLiteral: fieldValue) + } + return nil } // MARK: - MVMViewProtocol diff --git a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift index f185971d..a8a5de28 100644 --- a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift +++ b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift @@ -7,22 +7,22 @@ // import Foundation - +import MVMCore public class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { - public static var identifier: String = "radioButton" public var backgroundColor: Color? public var state: Bool? = false public var fieldKey: String? public var groupName: String? = FormValidator.defaultGroupName - public var fieldValue: String - public func formFieldValue() -> Any? { - return fieldValue - } - - init(_ fieldKey: String, _ fieldValue: String) { - self.fieldKey = fieldKey - self.fieldValue = fieldValue + public var fieldValue: String? + public var baseValue: JSONValue? + + public func formFieldValue() -> JSONValue? { + if let fieldValue = fieldValue { + return JSONValue(stringLiteral: fieldValue) + } else { + return nil + } } } diff --git a/MVMCoreUI/Atoms/Views/ToggleModel.swift b/MVMCoreUI/Atoms/Views/ToggleModel.swift index 14f43d02..51f49828 100644 --- a/MVMCoreUI/Atoms/Views/ToggleModel.swift +++ b/MVMCoreUI/Atoms/Views/ToggleModel.swift @@ -17,6 +17,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { public var alternateAction: ActionModelProtocol? public var fieldKey: String? public var groupName: String? = FormValidator.defaultGroupName + public var baseValue: JSONValue? private enum CodingKeys: String, CodingKey { case moleculeName @@ -29,8 +30,8 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { case groupName } - public func formFieldValue() -> Any? { - return state + public func formFieldValue() -> JSONValue? { + return JSONValue(booleanLiteral: state) } public init(_ state: Bool) { diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index d3f238af..ebc47f23 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -24,7 +24,8 @@ import MVMCore } public func insertMolecule(_ molecule: FormItemProtocol) { - if let molecule = molecule as? FormFieldProtocol { + if var molecule = molecule as? FormFieldProtocol { + molecule.baseValue = molecule.formFieldValue() fieldMolecules.append(molecule) } if let molecule = molecule as? FormActionFieldProtocol { diff --git a/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift index 9ba8ad4d..0a099000 100644 --- a/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift @@ -11,5 +11,12 @@ import Foundation public protocol FormFieldProtocol: FormItemProtocol { var fieldKey: String? { get set } - func formFieldValue() -> Any? + var baseValue: JSONValue? { get set } + func formFieldValue() -> JSONValue? +} + +extension FormFieldProtocol { + var baseValue: JSONValue? { + return nil + } } diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleValueChangeModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAllValueChangedModel.swift similarity index 53% rename from MVMCoreUI/FormUIHelpers/New/Rules/RuleValueChangeModel.swift rename to MVMCoreUI/FormUIHelpers/New/Rules/RuleAllValueChangedModel.swift index 221c4b5d..a33cb64c 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RuleValueChangeModel.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAllValueChangedModel.swift @@ -8,13 +8,13 @@ import Foundation -public class RuleValueChangeModel: RulesProtocol { +public class RuleAllValueChangedModel: RulesProtocol { - public static var identifier: String = "valueChanged" - public var ruleType: String = RuleAnyModel.identifier + public static var identifier: String = "allValueChanged" + public var ruleType: String = RuleAllValueChangedModel.identifier public var fields: [String] public func isValid(_ formField: FormFieldProtocol) -> Bool { - return false + return formField.baseValue != formField.formFieldValue() } } diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyModel.swift deleted file mode 100644 index 3e10b7af..00000000 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyModel.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// RuleAnyModel.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 2/24/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import Foundation - -public class RuleAnyModel: RulesProtocol { - - public static var identifier: String = "any" - public var ruleType: String = RuleAnyModel.identifier - public var fields: [String] - - public func isValid(_ formField: FormFieldProtocol) -> Bool { - return false - } -} diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyValueChangedModel.swift new file mode 100644 index 00000000..80b95514 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyValueChangedModel.swift @@ -0,0 +1,32 @@ +// +// RuleAnyModel.swift +// MVMCoreUI +// +// Created by Suresh, Kamlesh on 2/24/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import Foundation + +public class RuleAnyValueChangedModel: RulesProtocol { + + public static var identifier: String = "anyValueChanged" + public var ruleType: String = RuleAnyValueChangedModel.identifier + public var fields: [String] + + public func isValid(_ formField: FormFieldProtocol) -> Bool { + return formField.baseValue != formField.formFieldValue() + } + + public func isValid(_ formValidator: FormValidator) -> Bool { + for formKey in fields { + guard let formField = formValidator.formField(for: formKey) else { + continue + } + if isValid(formField) { + return true + } + } + return false + } +} diff --git a/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift b/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift index 8297a2a3..6674fe4d 100644 --- a/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift +++ b/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift @@ -10,10 +10,13 @@ import Foundation import UIKit @objcMembers public class RadioButtonSelectionHelper: FormFieldProtocol { + + public var fieldKey: String? public var groupName: String? = FormValidator.defaultGroupName private var selectedRadioButton: RadioButton? private var fieldGroupName: String? + public var baseValue: JSONValue? init(_ fieldKey: String?) { self.fieldKey = fieldKey @@ -44,7 +47,7 @@ extension RadioButtonSelectionHelper { return selectedRadioButton?.formFieldGroupName() ?? self.fieldGroupName } - public func formFieldValue() -> Any? { + public func formFieldValue() -> JSONValue? { return selectedRadioButton?.formFieldValue() } } diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index ae8f19fe..8d150395 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -121,8 +121,8 @@ import Foundation // Helper models try? ModelRegistry.register(RuleRequiredModel.self) - try? ModelRegistry.register(RuleAnyModel.self) - try? ModelRegistry.register(RuleValueChangeModel.self) + try? ModelRegistry.register(RuleAnyValueChangedModel.self) + try? ModelRegistry.register(RuleAllValueChangedModel.self) try? ModelRegistry.register(RuleEqualsModel.self) try? ModelRegistry.register(RuleRegexModel.self) } From 8df94a2f56c1e1f51512a572c7049882fbbabea8 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Sun, 8 Mar 2020 19:14:51 -0400 Subject: [PATCH 06/27] moving back to any --- .../Atoms/TextFields/EntryFieldModel.swift | 10 ++-- MVMCoreUI/Atoms/Views/CheckboxModel.swift | 6 +-- MVMCoreUI/Atoms/Views/RadioButton.swift | 7 +-- MVMCoreUI/Atoms/Views/RadioButtonModel.swift | 46 ++++++++++++++++--- MVMCoreUI/Atoms/Views/ToggleModel.swift | 6 +-- .../FormUIHelpers/New/FormFieldProtocol.swift | 6 +-- .../New/Rules/FormGroupRule.swift | 1 - .../New/Rules/RuleAllValueChangedModel.swift | 2 +- .../New/Rules/RuleAnyValueChangedModel.swift | 2 +- .../New/Rules/RuleEqualsModel.swift | 2 +- .../New/Rules/RuleRegexModel.swift | 2 +- .../New/Rules/RuleRequiredModel.swift | 2 +- .../New/Rules/RulesProtocol.swift | 2 +- .../RadioButtonSelectionHelper.swift | 4 +- 14 files changed, 62 insertions(+), 36 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift index 2b2ef27b..54b441f7 100644 --- a/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atoms/TextFields/EntryFieldModel.swift @@ -29,7 +29,7 @@ import Foundation public var fieldKey: String? public var groupName: String? = FormValidator.defaultGroupName public var text: String? - public var baseValue: JSONValue? + public var baseValue: AnyHashable? public var isValid: Bool? { didSet { @@ -61,12 +61,8 @@ import Foundation case groupName } - public func formFieldValue() -> JSONValue? { - if let text = text { - return JSONValue(stringLiteral: text) - } else { - return nil - } + public func formFieldValue() -> AnyHashable? { + return text } //-------------------------------------------------- diff --git a/MVMCoreUI/Atoms/Views/CheckboxModel.swift b/MVMCoreUI/Atoms/Views/CheckboxModel.swift index 70224200..13b730a6 100644 --- a/MVMCoreUI/Atoms/Views/CheckboxModel.swift +++ b/MVMCoreUI/Atoms/Views/CheckboxModel.swift @@ -33,7 +33,7 @@ import Foundation public var fieldKey: String? public var fieldValue: JSONValue? public var groupName: String? = FormValidator.defaultGroupName - public var baseValue: JSONValue? + public var baseValue: AnyHashable? //-------------------------------------------------- // MARK: - Keys @@ -61,8 +61,8 @@ import Foundation init(isChecked: Bool = false) {} - public func formFieldValue() -> JSONValue? { - return JSONValue(booleanLiteral: isChecked) + public func formFieldValue() -> AnyHashable? { + return isChecked } //-------------------------------------------------- diff --git a/MVMCoreUI/Atoms/Views/RadioButton.swift b/MVMCoreUI/Atoms/Views/RadioButton.swift index 49625eb2..2c110b4e 100644 --- a/MVMCoreUI/Atoms/Views/RadioButton.swift +++ b/MVMCoreUI/Atoms/Views/RadioButton.swift @@ -83,11 +83,8 @@ import UIKit return radioModel?.fieldKey } - public func formFieldValue() -> JSONValue? { - if let fieldValue = radioModel?.fieldValue { - return JSONValue(stringLiteral: fieldValue) - } - return nil + public func formFieldValue() -> AnyHashable? { + return radioModel?.fieldValue } // MARK: - MVMViewProtocol diff --git a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift index a8a5de28..0927866c 100644 --- a/MVMCoreUI/Atoms/Views/RadioButtonModel.swift +++ b/MVMCoreUI/Atoms/Views/RadioButtonModel.swift @@ -10,19 +10,53 @@ import Foundation import MVMCore public class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol { + public static var identifier: String = "radioButton" public var backgroundColor: Color? public var state: Bool? = false public var fieldKey: String? public var groupName: String? = FormValidator.defaultGroupName public var fieldValue: String? - public var baseValue: JSONValue? + public var baseValue: AnyHashable? - public func formFieldValue() -> JSONValue? { - if let fieldValue = fieldValue { - return JSONValue(stringLiteral: fieldValue) - } else { - return nil + public func formFieldValue() -> AnyHashable? { + return fieldValue + } + + private enum CodingKeys: String, CodingKey { + case moleculeName + case state + case backgroundColor + case fieldKey + case groupName + case fieldValue + } + + public init(_ state: Bool) { + self.state = state + } + + required public init(from decoder: Decoder) throws { + let typeContainer = try decoder.container(keyedBy: CodingKeys.self) + if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { + self.state = state + } + + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) + fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue) + if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { + self.groupName = groupName } } + + public 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) + try container.encodeIfPresent(state, forKey: .state) + try container.encodeIfPresent(fieldKey, forKey: .fieldKey) + try container.encodeIfPresent(fieldValue, forKey: .fieldValue) + try container.encodeIfPresent(groupName, forKey: .groupName) + } } diff --git a/MVMCoreUI/Atoms/Views/ToggleModel.swift b/MVMCoreUI/Atoms/Views/ToggleModel.swift index afe9ed41..18022833 100644 --- a/MVMCoreUI/Atoms/Views/ToggleModel.swift +++ b/MVMCoreUI/Atoms/Views/ToggleModel.swift @@ -17,7 +17,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { public var alternateAction: ActionModelProtocol? public var fieldKey: String? public var groupName: String? = FormValidator.defaultGroupName - public var baseValue: JSONValue? + public var baseValue: AnyHashable? private enum CodingKeys: String, CodingKey { case moleculeName @@ -30,8 +30,8 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol { case groupName } - public func formFieldValue() -> JSONValue? { - return JSONValue(booleanLiteral: state) + public func formFieldValue() -> AnyHashable? { + return state } public init(_ state: Bool) { diff --git a/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift index 0a099000..c59ccd08 100644 --- a/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift @@ -11,12 +11,12 @@ import Foundation public protocol FormFieldProtocol: FormItemProtocol { var fieldKey: String? { get set } - var baseValue: JSONValue? { get set } - func formFieldValue() -> JSONValue? + var baseValue: AnyHashable? { get set } + func formFieldValue() -> AnyHashable? } extension FormFieldProtocol { - var baseValue: JSONValue? { + var baseValue: AnyHashable? { return nil } } diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift b/MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift index 29872de7..d416ef3c 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift @@ -10,7 +10,6 @@ import Foundation open class FormGroupRule: Codable { -// public static var identifier: String = "formRule" var groupName: String var rules: [RulesProtocol] diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAllValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAllValueChangedModel.swift index a33cb64c..7535c6dd 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAllValueChangedModel.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAllValueChangedModel.swift @@ -11,7 +11,7 @@ import Foundation public class RuleAllValueChangedModel: RulesProtocol { public static var identifier: String = "allValueChanged" - public var ruleType: String = RuleAllValueChangedModel.identifier + public var type: String = RuleAllValueChangedModel.identifier public var fields: [String] public func isValid(_ formField: FormFieldProtocol) -> Bool { diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyValueChangedModel.swift index 80b95514..f52dd92d 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyValueChangedModel.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyValueChangedModel.swift @@ -11,7 +11,7 @@ import Foundation public class RuleAnyValueChangedModel: RulesProtocol { public static var identifier: String = "anyValueChanged" - public var ruleType: String = RuleAnyValueChangedModel.identifier + public var type: String = RuleAnyValueChangedModel.identifier public var fields: [String] public func isValid(_ formField: FormFieldProtocol) -> Bool { diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift index 7d1532d8..fd7331f0 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift @@ -11,7 +11,7 @@ import Foundation public class RuleEqualsModel: RulesProtocol { public static var identifier: String = "equals" - public var ruleType: String = RuleEqualsModel.identifier + public var type: String = RuleEqualsModel.identifier public var fields: [String] public func isValid(_ formField: FormFieldProtocol) -> Bool { diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift index 9ef00426..bc66fd1a 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift @@ -10,7 +10,7 @@ import Foundation public class RuleRegexModel: RulesProtocol { public static var identifier: String = "regex" - public var ruleType: String = RuleRegexModel.identifier + public var type: String = RuleRegexModel.identifier public var fields: [String] public func isValid(_ formField: FormFieldProtocol) -> Bool { diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift index 252808a0..3900249a 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift @@ -12,7 +12,7 @@ import Foundation public class RuleRequiredModel: RulesProtocol { public static var identifier: String = "required" - public var ruleType: String = RuleRequiredModel.identifier + public var type: String = RuleRequiredModel.identifier public var fields: [String] public func isValid(_ formField: FormFieldProtocol) -> Bool { diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift index 536bf468..24bedd01 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift @@ -14,7 +14,7 @@ public enum RulesCodingKey: String, CodingKey { } public protocol RulesProtocol: ModelProtocol { - var ruleType: String { get set } + var type: String { get set } var fields: [String] { get set } func isValid(_ formValidator: FormValidator) -> Bool func isValid(_ formField: FormFieldProtocol) -> Bool diff --git a/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift b/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift index 6674fe4d..263a85a4 100644 --- a/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift +++ b/MVMCoreUI/Molecules/RadioButtonSelectionHelper.swift @@ -16,7 +16,7 @@ import UIKit public var groupName: String? = FormValidator.defaultGroupName private var selectedRadioButton: RadioButton? private var fieldGroupName: String? - public var baseValue: JSONValue? + public var baseValue: AnyHashable? init(_ fieldKey: String?) { self.fieldKey = fieldKey @@ -47,7 +47,7 @@ extension RadioButtonSelectionHelper { return selectedRadioButton?.formFieldGroupName() ?? self.fieldGroupName } - public func formFieldValue() -> JSONValue? { + public func formFieldValue() -> AnyHashable? { return selectedRadioButton?.formFieldValue() } } From c53c76d7f36fdb869d8ef62ddf1a5f5d7ad96241 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 9 Mar 2020 12:02:04 -0400 Subject: [PATCH 07/27] fixes --- MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift | 1 - MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift b/MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift index d416ef3c..34dfb7b8 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift @@ -27,7 +27,6 @@ open class FormGroupRule: Codable { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) self.groupName = try typeContainer.decode(String.self, forKey: .groupName) self.rules = try typeContainer.decodeModels(codingKey: .rules) - //try typeContainer.decodeFormRules(codingKey: .rules) } public func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift index 24bedd01..16fe77b3 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift @@ -28,7 +28,7 @@ public extension RulesProtocol { } static var categoryCodingKey: String { - return "ruleType" + return "type" } static var categoryName: String { From 3970b34719cb4b082446cfd9f86684586a00df34 Mon Sep 17 00:00:00 2001 From: "Khan, Arshad" Date: Tue, 10 Mar 2020 01:15:37 +0530 Subject: [PATCH 08/27] Making few properties public. Constraint fixes. --- MVMCoreUI/Organisms/Carousel.swift | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/MVMCoreUI/Organisms/Carousel.swift b/MVMCoreUI/Organisms/Carousel.swift index 9e2422e6..f8e2f37f 100644 --- a/MVMCoreUI/Organisms/Carousel.swift +++ b/MVMCoreUI/Organisms/Carousel.swift @@ -10,7 +10,7 @@ import UIKit open class Carousel: View { - let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) + public let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: MVMCoreUISplitViewController.getDetailViewWidth(), height: 300), collectionViewLayout: UICollectionViewFlowLayout()) /// The current index of the collection view. Includes dummy cells when looping. var currentIndex = 0 @@ -26,7 +26,7 @@ open class Carousel: View { } /// The number of pages that there are. Used for the page control and for calculations. Should not include the looping dummy cells. Be sure to set this if subclassing and not using the molecules. - var numberOfPages = 0 + open var numberOfPages = 0 /// The json for the molecules. var molecules: [MoleculeModelProtocol]? @@ -35,10 +35,10 @@ open class Carousel: View { var itemAlignment = UICollectionView.ScrollPosition.left /// From 0-1. The item width as a percent of the carousel width. - var itemWidthPercent: Float = 1 + public var itemWidthPercent: Float = 1 /// The height of the carousel. Default is 300. - var collectionViewHeight: NSLayoutConstraint? + public var collectionViewHeight: NSLayoutConstraint? /// The view that we use for paging var pagingView: (UIView & MVMCoreUIPagingProtocol)? @@ -65,7 +65,7 @@ open class Carousel: View { addSubview(collectionView) bottomPin = NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView)?[ConstraintBot] as? NSLayoutConstraint - collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 300) + collectionViewHeight = collectionView.heightAnchor.constraint(greaterThanOrEqualToConstant: 300) collectionViewHeight?.isActive = false } @@ -114,6 +114,7 @@ open class Carousel: View { layout.scrollDirection = .horizontal layout.minimumLineSpacing = CGFloat(carouselModel?.spacing ?? 1) layout.minimumInteritemSpacing = 0 + layout.itemSize = CGSize(width: MVMCoreUISplitViewController.getDetailViewWidth(), height: 300) collectionView.collectionViewLayout = layout } @@ -190,12 +191,12 @@ open class Carousel: View { pagingView.translatesAutoresizingMaskIntoConstraints = false addSubview(pagingView) pagingView.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true - collectionView.bottomAnchor.constraint(equalTo: pagingView.centerYAnchor, constant: position).isActive = true + collectionView.bottomAnchor.constraint(equalTo: pagingView.topAnchor, constant: position).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor).isActive = true bottomPin?.isActive = false bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) bottomPin?.priority = .defaultLow - bottomPin?.isActive = true + bottomPin?.isActive = false pagingView.setNumberOfPages(numberOfPages) (pagingView as? MVMCoreUIViewConstrainingProtocol)?.alignHorizontal?(.fill) @@ -230,7 +231,7 @@ open class Carousel: View { } } - func setAccessiblity(_ cell: UICollectionViewCell?, index: Int) { + public func setAccessiblity(_ cell: UICollectionViewCell?, index: Int) { guard let cell = cell else { return } @@ -252,7 +253,7 @@ open class Carousel: View { } extension Carousel: UICollectionViewDelegateFlowLayout { - public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let itemWidth = collectionView.bounds.width * CGFloat(itemWidthPercent) return CGSize(width: itemWidth, height: collectionView.bounds.height) } @@ -263,11 +264,11 @@ extension Carousel: UICollectionViewDelegateFlowLayout { } extension Carousel: UICollectionViewDataSource { - public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return molecules?.count ?? 0 } - public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { guard let molecule = molecules?[indexPath.row], let moleculeInfo = getMoleculeInfo(with: molecule, delegateObject: nil) else { return UICollectionViewCell() @@ -343,6 +344,8 @@ extension Carousel: UIScrollViewDelegate { // Let the pager know our progress if needed. pagingView?.scrollViewDidScroll?(collectionView) + + collectionView.collectionViewLayout.invalidateLayout() } public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { From 2ce25e340c44c18eccd177aa09a83192d3c9da12 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 9 Mar 2020 22:04:41 -0400 Subject: [PATCH 09/27] optimise --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index ebc47f23..daadf81f 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -15,7 +15,7 @@ import MVMCore var extraValidationBlock: (() -> Bool)? var formRules: [FormGroupRule] var delegate: FormHolderProtocol? - var fieldMolecules: [FormFieldProtocol] = [] + var fieldMolecules: [String: FormFieldProtocol] = [:] var formActionMolecules: [FormActionFieldProtocol] = [] var radioButtonsModelByGroup: [String: RadioButtonSelectionHelper] = [:] @@ -24,9 +24,10 @@ import MVMCore } public func insertMolecule(_ molecule: FormItemProtocol) { - if var molecule = molecule as? FormFieldProtocol { + if var molecule = molecule as? FormFieldProtocol, + let fieldKey = molecule.fieldKey { molecule.baseValue = molecule.formFieldValue() - fieldMolecules.append(molecule) + fieldMolecules[fieldKey] = molecule } if let molecule = molecule as? FormActionFieldProtocol { formActionMolecules.append(molecule) @@ -68,7 +69,7 @@ import MVMCore } public func formField(for fieldKey: String) -> FormFieldProtocol? { - return fieldMolecules.first(where: { $0.fieldKey == fieldKey }) + return fieldMolecules[fieldKey] } } @@ -84,11 +85,10 @@ import MVMCore @objc func getFormParams( forGroup groupName: String) -> [String: Any] { var extraParam: [String: Any] = [:] MVMCoreDispatchUtility.performSyncBlock(onMainThread: { - for molecule in self.fieldMolecules { - if let formFieldName = molecule.fieldKey, - let formFieldValue = molecule.formFieldValue(), + for (fieldKey, molecule) in self.fieldMolecules { + if let formFieldValue = molecule.formFieldValue(), groupName == molecule.groupName { - extraParam[formFieldName] = formFieldValue + extraParam[fieldKey] = formFieldValue } } }) From 21f38af0c372d8c648c0da42a78f6450c162fc3f Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Mon, 9 Mar 2020 22:26:01 -0400 Subject: [PATCH 10/27] equal rules --- .../New/Rules/RuleEqualsModel.swift | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift index fd7331f0..ac148a29 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift @@ -17,4 +17,24 @@ public class RuleEqualsModel: RulesProtocol { public func isValid(_ formField: FormFieldProtocol) -> Bool { return false } + + public func isValid(_ formValidator: FormValidator) -> Bool { + var valid = true + var compareValue: AnyHashable? + for formKey in fields { + guard let formField = formValidator.formField(for: formKey) else { + continue + } + + if compareValue == nil { + compareValue = formField.formFieldValue() + continue + } + if compareValue != formField.formFieldValue(){ + valid = false + break + } + } + return valid + } } From 955d398262e4aa925f1a2ddb4f415eea47ff3bcc Mon Sep 17 00:00:00 2001 From: "Khan, Arshad" Date: Tue, 10 Mar 2020 20:11:25 +0530 Subject: [PATCH 11/27] making properties and function public --- MVMCoreUI/Organisms/Carousel.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Organisms/Carousel.swift b/MVMCoreUI/Organisms/Carousel.swift index f8e2f37f..6fab0f68 100644 --- a/MVMCoreUI/Organisms/Carousel.swift +++ b/MVMCoreUI/Organisms/Carousel.swift @@ -41,14 +41,14 @@ open class Carousel: View { public var collectionViewHeight: NSLayoutConstraint? /// The view that we use for paging - var pagingView: (UIView & MVMCoreUIPagingProtocol)? + public var pagingView: (UIView & MVMCoreUIPagingProtocol)? /// If the carousel should loop after scrolling past the first and final cells. var loop = false private var dragging = false // For adding pager - private var bottomPin: NSLayoutConstraint? + public var bottomPin: NSLayoutConstraint? // MARK: - MVMCoreViewProtocol open override func setupView() { @@ -258,7 +258,7 @@ extension Carousel: UICollectionViewDelegateFlowLayout { return CGSize(width: itemWidth, height: collectionView.bounds.height) } - public func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { + open func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { (cell as? MoleculeCollectionViewCell)?.setPeaking(false, animated: false) } } From c1047d42b82d265b84ef06d30679dcd37dd10aa3 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 10 Mar 2020 11:37:08 -0400 Subject: [PATCH 12/27] regex --- MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift index bc66fd1a..db1c4859 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift @@ -12,8 +12,12 @@ public class RuleRegexModel: RulesProtocol { public static var identifier: String = "regex" public var type: String = RuleRegexModel.identifier public var fields: [String] + public var regex: String public func isValid(_ formField: FormFieldProtocol) -> Bool { + if let stringToValidate = formField.formFieldValue() as? String { + return MVMCoreUIUtility.validate(stringToValidate, withRegularExpression: regex) + } return false } } From 7965c4ac6a7c33d38b53bab3d0d9791b9f8318de Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 10 Mar 2020 15:25:49 -0400 Subject: [PATCH 13/27] clean up --- MVMCoreUI.xcodeproj/project.pbxproj | 10 --- ...maryButton+MoleculeProtocolExtension.swift | 5 -- .../MFTextField+ModelExtension.swift | 79 ------------------- .../Atoms/TextFields/MdnEntryField.swift | 42 +++++----- .../FormValidator+TextFields.swift | 69 ---------------- MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m | 4 +- MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m | 2 - MVMCoreUI/Legacy/Views/PrimaryButton.m | 1 - .../Templates/MoleculeListTemplate.swift | 2 +- 9 files changed, 23 insertions(+), 191 deletions(-) delete mode 100644 MVMCoreUI/Atoms/TextFields/MFTextField+ModelExtension.swift delete mode 100644 MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 4066abcc..b5985e36 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -10,7 +10,6 @@ 01004F3022721C3800991ECC /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01004F2F22721C3800991ECC /* RadioButton.swift */; }; 0103B84E23D7E33A009C315C /* HeadlineBodyToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0103B84D23D7E33A009C315C /* HeadlineBodyToggleModel.swift */; }; 0105618D224BBE7700E1557D /* FormValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618A224BBE7700E1557D /* FormValidator.swift */; }; - 0105618E224BBE7700E1557D /* FormValidator+TextFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */; }; 0116A4E5228B19640094F3ED /* RadioButtonSelectionHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */; }; 011B58F023A2AA980085F53C /* ListItemModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */; }; 011B58F223A2AE2C0085F53C /* DropDownListItemModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */; }; @@ -40,7 +39,6 @@ 012A88DB238ED45900FE3DA1 /* CarouselModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88AE238C626E00FE3DA1 /* CarouselModel.swift */; }; 012A88EC238F084D00FE3DA1 /* FooterModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88EB238F084D00FE3DA1 /* FooterModel.swift */; }; 012A88F123985E0100FE3DA1 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012A88F023985E0100FE3DA1 /* Color.swift */; }; - 012CA99A2384A687003F810F /* MFTextField+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */; }; 012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */; }; 013F801923FB4A8E00AD8013 /* UIContentMode+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */; }; 014AA72423C501E2006F3E93 /* MoleculeContainerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */; }; @@ -383,7 +381,6 @@ 01004F2F22721C3800991ECC /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = ""; }; 0103B84D23D7E33A009C315C /* HeadlineBodyToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyToggleModel.swift; sourceTree = ""; }; 0105618A224BBE7700E1557D /* FormValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidator.swift; sourceTree = ""; }; - 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = ""; }; 0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonSelectionHelper.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 = ""; }; @@ -413,7 +410,6 @@ 012A88C7238DB02000FE3DA1 /* ModelMoleculeDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelMoleculeDelegateProtocol.swift; sourceTree = ""; }; 012A88EB238F084D00FE3DA1 /* FooterModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterModel.swift; sourceTree = ""; }; 012A88F023985E0100FE3DA1 /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; - 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFTextField+ModelExtension.swift"; sourceTree = ""; }; 012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFView+ModelExtension.swift"; sourceTree = ""; }; 013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIContentMode+Extension.swift"; sourceTree = ""; }; 014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeContainerModel.swift; sourceTree = ""; }; @@ -832,7 +828,6 @@ children = ( 011D9583240422BF000E3791 /* New */, 0105618A224BBE7700E1557D /* FormValidator.swift */, - 0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */, ); path = FormUIHelpers; sourceTree = ""; @@ -1457,7 +1452,6 @@ 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */, 0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */, 017BEB3F23620A230024EF95 /* TextFieldModel.swift */, - 012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */, ); path = TextFields; sourceTree = ""; @@ -1910,7 +1904,6 @@ D2D6CD4222E78FAB00D701B8 /* ThreeLayerTemplate.swift in Sources */, 01EB368F23609801006832FA /* LabelModel.swift in Sources */, 942C378E2412F5B60066E45E /* ModalMoleculeStackTemplate.swift in Sources */, - 0105618F224BBE7700E1557D /* FormValidator+FormParams.swift in Sources */, 01F2A03223A4498200D954D8 /* CaretLinkModel.swift in Sources */, 0A7BAFA1232BE61800FB8E22 /* Checkbox.swift in Sources */, 011B58F023A2AA980085F53C /* ListItemModelProtocol.swift in Sources */, @@ -1976,7 +1969,6 @@ D29DF17B21E69E1F003B2FB9 /* PrimaryButton.m in Sources */, 017BEB4A236235BA0024EF95 /* ModelMoleculeViewProtocol.swift in Sources */, C695A68123C9830D00BFB94E /* NumberedListModel.swift in Sources */, - 012CA99A2384A687003F810F /* MFTextField+ModelExtension.swift in Sources */, 01EB3684236097C0006832FA /* MoleculeModelProtocol.swift in Sources */, D27CD4102339057800C1DC07 /* EyebrowHeadlineBodyLink.swift in Sources */, D29DF11D21E684A9003B2FB9 /* MVMCoreUISplitViewController.m in Sources */, @@ -2028,7 +2020,6 @@ 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 */, @@ -2056,7 +2047,6 @@ D29DF2CB21E7BFCC003B2FB9 /* MFSizeThreshold.m in Sources */, 011D959F240453A1000E3791 /* RuleAllValueChangedModel.swift in Sources */, 011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */, - 946EE1BA237B66D80036751F /* MoleculeModelHelper.swift in Sources */, 01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */, D260106523D0CEA700764D80 /* StackModel.swift in Sources */, D29770F521F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m in Sources */, diff --git a/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift b/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift index f354ac85..6cf0df21 100644 --- a/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift +++ b/MVMCoreUI/Atoms/Buttons/PrimaryButton+MoleculeProtocolExtension.swift @@ -16,11 +16,6 @@ extension PrimaryButton: ModelMoleculeViewProtocol { setTitle(model.title, for: .normal) backgroundColor = model.backgroundColor?.uiColor -// if self.validationRequired, -// let selfForm = self as? FormValidationEnableDisableProtocol { -// FormValidator.setupValidation(molecule: selfForm, delegate: delegateObject?.formValidationProtocol) -// } - if let style = model.style { switch style { case .primary: diff --git a/MVMCoreUI/Atoms/TextFields/MFTextField+ModelExtension.swift b/MVMCoreUI/Atoms/TextFields/MFTextField+ModelExtension.swift deleted file mode 100644 index 63e01b3a..00000000 --- a/MVMCoreUI/Atoms/TextFields/MFTextField+ModelExtension.swift +++ /dev/null @@ -1,79 +0,0 @@ -// -// MFTextField+ModelExtension.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 11/19/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import UIKit - -enum TextType: String { - case dropDown = "dropDown" - case password = "password" - case number = "number" - case email = "email" -} -extension MFTextField: ModelMoleculeViewProtocol { - // - public func setWithModel(_ model: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { -// //TODO: Need to create setWithModel in ViewConstraining View -// #warning("This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView.") -// //TODO: This below call should be repaced with super.setWithModel once we get rid of ViewConstrainingView. -// setUpDefaultWithModel(model, delegateObject, additionalData) -// -// guard let textFieldModel = model as? TextFieldModel, -// let delegateObject = delegateObject else { -// return -// } -// -// if let delegate = delegateObject.formValidationProtocol { -// let formValidator = FormValidator.getFormValidatorFor(delegate: delegate) -// mfTextFieldDelegate = formValidator -// uiTextFieldDelegate = delegateObject.uiTextFieldDelegate -// if let textField = textField { -// MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate) -// } -// } -// -// formText = textFieldModel.label as NSString? -// text = textFieldModel.value as NSString? -// if let disabled = textFieldModel.disabled { -// enable(disabled) -// } -// errMessage = textFieldModel.errorMsg -// fieldKey = textFieldModel.fieldKey -// groupName = textFieldModel.groupName -// -// -// switch textFieldModel.type { -// case TextType.dropDown.rawValue: -// dropDownCarrotLabel?.isHidden = true -// hasDropDown = true -// break -// case TextType.password.rawValue: -// textField?.isSecureTextEntry = true -// break -// case TextType.number.rawValue: -// textField?.keyboardType = .numberPad -// break -// case TextType.email.rawValue: -// textField?.keyboardType = .emailAddress -// break -// default: -// print("default") -// } -// -// if let regex = textFieldModel.regex { -// validationBlock = {(enteredValue: String?) -> Bool in -// if let enteredValue = enteredValue { -// return MVMCoreUIUtility.validate(enteredValue, withRegularExpression: regex) -// } -// return true -// } -// } else { -// setDefaultValidationBlock() -// } - } -} - diff --git a/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift b/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift index b42349c6..92a1e073 100644 --- a/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/MdnEntryField.swift @@ -97,25 +97,25 @@ import MVMCore return MVMCoreUIUtility.validateInternationalMDNString(MDN) } - @objc public override func validateTextField() { + @objc public func validateMDNTextField() -> Bool { -// guard !shouldValidateMDN, let MDN = mdn, !MDN.isEmpty else { -// isValid = true -// return true -// } -// -// let isValid = hasValidMDN() -// -// if isValid { -// showError = false -// -// } else { -// errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message") -// showError = true -// UIAccessibility.post(notification: .layoutChanged, argument: textField) -// } -// -// return isValid + guard !shouldValidateMDN, let MDN = mdn, !MDN.isEmpty else { + isValid = true + return true + } + + let isValid = hasValidMDN() + + if isValid { + showError = false + + } else { + errorMessage = errorMessage ?? MVMCoreUIUtility.hardcodedString(withKey: "textfield_phone_format_error_message") + showError = true + UIAccessibility.post(notification: .layoutChanged, argument: textField) + } + + return isValid } @objc public func getContacts(_ sender: Any?) { @@ -186,9 +186,9 @@ import MVMCore proprietorTextDelegate?.textFieldDidEndEditing?(textField) -// if validateTextField() && isNationalMDN { -// textField.text = MVMCoreUIUtility.formatMdn(textField.text) -// } + if validateMDNTextField() && isNationalMDN { + textField.text = MVMCoreUIUtility.formatMdn(textField.text) + } } @objc public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { diff --git a/MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift b/MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift deleted file mode 100644 index 0455b689..00000000 --- a/MVMCoreUI/FormUIHelpers/FormValidator+TextFields.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// MVMCoreUIFormValidator+TextFields.swift -// MVMCoreUI -// -// Created by Suresh, Kamlesh on 3/21/19. -// Copyright © 2019 Verizon Wireless. All rights reserved. -// - -import Foundation - -//@objc extension FormValidator: MFTextFieldDelegate { -// -// public func dismissFieldInput(_ sender: Any?) { -// -// if let delegate = delegate as? MFTextFieldDelegate { -// delegate.dismissFieldInput?(sender) -// } -// } -// -// public func entryIsValid(_ textfield: MFTextField?) { -// -// MVMCoreDispatchUtility.performBlock(onMainThread: { -// self.enableByValidation() -// if let delegate = self.delegate as? MFTextFieldDelegate { -// delegate.entryIsValid?(textfield) -// } -// }) -// } -// -// public func entryIsInvalid(_ textfield: MFTextField?) { -// -// MVMCoreDispatchUtility.performBlock(onMainThread: { -// self.enableByValidation() -// if let delegate = self.delegate as? MFTextFieldDelegate { -// delegate.entryIsInvalid?(textfield) -// } -// }) -// } -//} -// -// Temporary: Looking to either combine or separate entirely with MFTextFieldDelegate. -//extension FormValidator: ObservingTextFieldDelegate { -// -// public func dismissField(_ sender: Any?) { -// if let delegate = delegate as? MFTextFieldDelegate { -// delegate.dismissFieldInput?(sender) -// } -// } -// -// @nonobjc public func isValid(_ textfield: MFTextField?) { -// -// MVMCoreDispatchUtility.performBlock(onMainThread: { -// self.enableByValidation() -// if let delegate = self.delegate as? MFTextFieldDelegate { -// delegate.entryIsValid?(textfield) -// } -// }) -// } -// -// public func isInvalid(_ textfield: MFTextField?) { -// -// MVMCoreDispatchUtility.performBlock(onMainThread: { -// self.enableByValidation() -// if let delegate = self.delegate as? MFTextFieldDelegate { -// delegate.entryIsInvalid?(textfield) -// } -// }) -// } -//} diff --git a/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m b/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m index ab906bd7..4c6bf8a5 100644 --- a/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m +++ b/MVMCoreUI/Legacy/Views/MVMCoreUICheckBox.m @@ -59,9 +59,7 @@ static const CGFloat CheckBoxHeightWidth = 18.0; } - (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData { - -// [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; - + self.delegateObject = delegateObject; self.fieldKey = [json stringForKey:KeyFieldKey]; self.isRequired = [json boolForKey:KeyRequired]; diff --git a/MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m b/MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m index e4c3c38b..8cbb434d 100644 --- a/MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m +++ b/MVMCoreUI/Legacy/Views/MVMCoreUISwitch.m @@ -147,8 +147,6 @@ const CGFloat SwitchShakeIntensity = 2; self.json = json; self.delegate = delegateObject; -// [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; - NSString *color = [json string:@"onTintColor"]; if (color) { self.onTintColor = [UIColor mfGetColorForHex:color]; diff --git a/MVMCoreUI/Legacy/Views/PrimaryButton.m b/MVMCoreUI/Legacy/Views/PrimaryButton.m index 4ced32ac..0e16ce8e 100644 --- a/MVMCoreUI/Legacy/Views/PrimaryButton.m +++ b/MVMCoreUI/Legacy/Views/PrimaryButton.m @@ -671,7 +671,6 @@ self.validationRequired = [json boolForKey:@"required"]; self.requiredGroupsList = [json array:@"requiredGroups"]; -// [FormValidator setupValidationWithMolecule:self delegate:delegateObject.formValidationProtocol]; self.primaryButtonType = PrimaryButtonTypeCustom; NSString *style = [json string:@"style"]; diff --git a/MVMCoreUI/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Templates/MoleculeListTemplate.swift index 360fc86e..1ea13b4c 100644 --- a/MVMCoreUI/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Templates/MoleculeListTemplate.swift @@ -15,7 +15,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol public var formValidator: FormValidator? public func validate() { - + // Can override } public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]? From c55a9f3faa4ba331f049e83bcbe27ab968ec6d36 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Tue, 10 Mar 2020 15:42:44 -0400 Subject: [PATCH 14/27] rules should be optional --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 10 +++++++--- MVMCoreUI/Templates/TemplateProtocol.swift | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index daadf81f..b81804e8 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -13,13 +13,13 @@ import MVMCore static var defaultGroupName: String = "default" var extraValidationBlock: (() -> Bool)? - var formRules: [FormGroupRule] + var formRules: [FormGroupRule]? var delegate: FormHolderProtocol? var fieldMolecules: [String: FormFieldProtocol] = [:] var formActionMolecules: [FormActionFieldProtocol] = [] var radioButtonsModelByGroup: [String: RadioButtonSelectionHelper] = [:] - public init(_ formRules: [FormGroupRule]) { + public init(_ formRules: [FormGroupRule]?) { self.formRules = formRules } @@ -50,8 +50,12 @@ import MVMCore } public func validate() { + guard let formRules = formRules else { + return + } formActionMolecules.forEach { (actionModel) in - if let groupName = actionModel.groupName, let formRule = formRules.first(where: { $0.groupName == groupName }) { + if let groupName = actionModel.groupName, + let formRule = formRules.first(where: { $0.groupName == groupName }) { validate(groupName, actionModel, formRule.rules) } } diff --git a/MVMCoreUI/Templates/TemplateProtocol.swift b/MVMCoreUI/Templates/TemplateProtocol.swift index 1e3dbdcc..fcb6bde2 100644 --- a/MVMCoreUI/Templates/TemplateProtocol.swift +++ b/MVMCoreUI/Templates/TemplateProtocol.swift @@ -21,7 +21,8 @@ public extension TemplateProtocol where Self: MFViewController { let decoder = JSONDecoder() let templateModel = try decoder.decode(TemplateModel.self, from: data) - if self.formValidator == nil, let rules = templateModel.formRules { + if self.formValidator == nil { + let rules = templateModel.formRules self.formValidator = FormValidator(rules) } self.templateModel = templateModel From dfc9157c2650d7858a57ca2f7d9bdef290d2b81a Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 11 Mar 2020 10:45:17 -0400 Subject: [PATCH 15/27] nil check --- MVMCoreUI/FormUIHelpers/FormValidator.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index b81804e8..f2cdb8ea 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -26,7 +26,9 @@ import MVMCore public func insertMolecule(_ molecule: FormItemProtocol) { if var molecule = molecule as? FormFieldProtocol, let fieldKey = molecule.fieldKey { - molecule.baseValue = molecule.formFieldValue() + if molecule.baseValue == nil { + molecule.baseValue = molecule.formFieldValue() + } fieldMolecules[fieldKey] = molecule } if let molecule = molecule as? FormActionFieldProtocol { From bd4450a7fc856d439e7af4a78e3af1ee8ec2a830 Mon Sep 17 00:00:00 2001 From: "Khan, Arshad" Date: Wed, 11 Mar 2020 22:42:08 +0530 Subject: [PATCH 16/27] making pageIndex public --- MVMCoreUI/Organisms/Carousel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Organisms/Carousel.swift b/MVMCoreUI/Organisms/Carousel.swift index 6fab0f68..b9847487 100644 --- a/MVMCoreUI/Organisms/Carousel.swift +++ b/MVMCoreUI/Organisms/Carousel.swift @@ -16,7 +16,7 @@ open class Carousel: View { var currentIndex = 0 /// The index of the page, does not include dummy cells. - var pageIndex: Int { + public var pageIndex: Int { get { return loop ? currentIndex - 2 : currentIndex } From 73230fa3411d0a4315cc4fdde49b0bf055277a46 Mon Sep 17 00:00:00 2001 From: "Khan, Arshad" Date: Fri, 13 Mar 2020 01:55:58 +0530 Subject: [PATCH 17/27] implemented feedback --- MVMCoreUI/Organisms/Carousel.swift | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/MVMCoreUI/Organisms/Carousel.swift b/MVMCoreUI/Organisms/Carousel.swift index b9847487..94c47f4b 100644 --- a/MVMCoreUI/Organisms/Carousel.swift +++ b/MVMCoreUI/Organisms/Carousel.swift @@ -13,7 +13,7 @@ open class Carousel: View { public let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: MVMCoreUISplitViewController.getDetailViewWidth(), height: 300), collectionViewLayout: UICollectionViewFlowLayout()) /// The current index of the collection view. Includes dummy cells when looping. - var currentIndex = 0 + public var currentIndex = 0 /// The index of the page, does not include dummy cells. public var pageIndex: Int { @@ -114,7 +114,6 @@ open class Carousel: View { layout.scrollDirection = .horizontal layout.minimumLineSpacing = CGFloat(carouselModel?.spacing ?? 1) layout.minimumInteritemSpacing = 0 - layout.itemSize = CGSize(width: MVMCoreUISplitViewController.getDetailViewWidth(), height: 300) collectionView.collectionViewLayout = layout } @@ -184,19 +183,19 @@ open class Carousel: View { pagingView?.removeFromSuperview() guard let pagingView = view else { bottomPin?.isActive = false - bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) + bottomPin = safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) bottomPin?.isActive = true return } pagingView.translatesAutoresizingMaskIntoConstraints = false addSubview(pagingView) pagingView.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true - collectionView.bottomAnchor.constraint(equalTo: pagingView.topAnchor, constant: position).isActive = true - bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor).isActive = true + collectionView.bottomAnchor.constraint(equalTo: pagingView.bottomAnchor, constant: position).isActive = true + safeAreaLayoutGuide.bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor).isActive = true bottomPin?.isActive = false - bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) + bottomPin = safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) bottomPin?.priority = .defaultLow - bottomPin?.isActive = false + bottomPin?.isActive = true pagingView.setNumberOfPages(numberOfPages) (pagingView as? MVMCoreUIViewConstrainingProtocol)?.alignHorizontal?(.fill) From 022f76b8b218c230c5d7cb3ce0ad0e9dddd59ea7 Mon Sep 17 00:00:00 2001 From: "Khan, Arshad" Date: Fri, 13 Mar 2020 19:28:55 +0530 Subject: [PATCH 18/27] Removing hard coded width. --- MVMCoreUI/Organisms/Carousel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Organisms/Carousel.swift b/MVMCoreUI/Organisms/Carousel.swift index 94c47f4b..8ddeca5f 100644 --- a/MVMCoreUI/Organisms/Carousel.swift +++ b/MVMCoreUI/Organisms/Carousel.swift @@ -10,7 +10,7 @@ import UIKit open class Carousel: View { - public let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: MVMCoreUISplitViewController.getDetailViewWidth(), height: 300), collectionViewLayout: UICollectionViewFlowLayout()) + public let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) /// The current index of the collection view. Includes dummy cells when looping. public var currentIndex = 0 From 9b8046009af7c5efdb0908cc4e2a481024572f89 Mon Sep 17 00:00:00 2001 From: "Khan, Arshad" Date: Fri, 13 Mar 2020 20:23:20 +0530 Subject: [PATCH 19/27] Removed un-necessary code. --- MVMCoreUI/Organisms/Carousel.swift | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/MVMCoreUI/Organisms/Carousel.swift b/MVMCoreUI/Organisms/Carousel.swift index 8ddeca5f..b1cd0f37 100644 --- a/MVMCoreUI/Organisms/Carousel.swift +++ b/MVMCoreUI/Organisms/Carousel.swift @@ -183,7 +183,7 @@ open class Carousel: View { pagingView?.removeFromSuperview() guard let pagingView = view else { bottomPin?.isActive = false - bottomPin = safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) + bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) bottomPin?.isActive = true return } @@ -191,9 +191,9 @@ open class Carousel: View { addSubview(pagingView) pagingView.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true collectionView.bottomAnchor.constraint(equalTo: pagingView.bottomAnchor, constant: position).isActive = true - safeAreaLayoutGuide.bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor).isActive = true + bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor).isActive = true bottomPin?.isActive = false - bottomPin = safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) + bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) bottomPin?.priority = .defaultLow bottomPin?.isActive = true @@ -336,15 +336,13 @@ extension Carousel: UIScrollViewDelegate { handleUserOnBufferCell() } - public func scrollViewDidScroll(_ scrollView: UIScrollView) { + open func scrollViewDidScroll(_ scrollView: UIScrollView) { // Check if the user is dragging the card even further past the next card. checkForDraggingOutOfBounds(scrollView) // Let the pager know our progress if needed. pagingView?.scrollViewDidScroll?(collectionView) - - collectionView.collectionViewLayout.invalidateLayout() } public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { From d99090bc4425f93d592a70358a0667aa88bdd1f2 Mon Sep 17 00:00:00 2001 From: "Khan, Arshad" Date: Fri, 13 Mar 2020 20:29:02 +0530 Subject: [PATCH 20/27] Reverted back centerYAnchor --- MVMCoreUI/Organisms/Carousel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Organisms/Carousel.swift b/MVMCoreUI/Organisms/Carousel.swift index b1cd0f37..64284cbd 100644 --- a/MVMCoreUI/Organisms/Carousel.swift +++ b/MVMCoreUI/Organisms/Carousel.swift @@ -190,7 +190,7 @@ open class Carousel: View { pagingView.translatesAutoresizingMaskIntoConstraints = false addSubview(pagingView) pagingView.centerXAnchor.constraint(equalTo: collectionView.centerXAnchor).isActive = true - collectionView.bottomAnchor.constraint(equalTo: pagingView.bottomAnchor, constant: position).isActive = true + collectionView.bottomAnchor.constraint(equalTo: pagingView.centerYAnchor, constant: position).isActive = true bottomAnchor.constraint(greaterThanOrEqualTo: pagingView.bottomAnchor).isActive = true bottomPin?.isActive = false bottomPin = bottomAnchor.constraint(equalTo: collectionView.bottomAnchor) From 09be34e4f8f218800a5f2d7ac1134f997c2b2824 Mon Sep 17 00:00:00 2001 From: "Khan, Arshad" Date: Fri, 13 Mar 2020 20:39:36 +0530 Subject: [PATCH 21/27] Reverted collectioViewHeight constraint. --- MVMCoreUI/Organisms/Carousel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Organisms/Carousel.swift b/MVMCoreUI/Organisms/Carousel.swift index 64284cbd..ba675adf 100644 --- a/MVMCoreUI/Organisms/Carousel.swift +++ b/MVMCoreUI/Organisms/Carousel.swift @@ -65,7 +65,7 @@ open class Carousel: View { addSubview(collectionView) bottomPin = NSLayoutConstraint.constraintPinSubview(toSuperview: collectionView)?[ConstraintBot] as? NSLayoutConstraint - collectionViewHeight = collectionView.heightAnchor.constraint(greaterThanOrEqualToConstant: 300) + collectionViewHeight = collectionView.heightAnchor.constraint(equalToConstant: 300) collectionViewHeight?.isActive = false } From 6d3946f0e7541b328130211fe37d942fc34da400 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 13 Mar 2020 11:52:09 -0400 Subject: [PATCH 22/27] anyrequiredmodel --- MVMCoreUI.xcodeproj/project.pbxproj | 4 ++++ .../New/Rules/RuleAnyRequiredModel.swift | 23 +++++++++++++++++++ .../OtherHandlers/MoleculeObjectMapping.swift | 1 + 3 files changed, 28 insertions(+) create mode 100644 MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyRequiredModel.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 8ece6dd9..aeaac929 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -91,6 +91,7 @@ 0A41BA6E2344FCD400D4C0BC /* CATransaction+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */; }; 0A41BA7F23453A6400D4C0BC /* TextEntryField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */; }; 0A5D59C223AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */; }; + 0A69F611241BDEA700F7231B /* RuleAnyRequiredModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */; }; 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 */; }; @@ -452,6 +453,7 @@ 0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = ""; }; 0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryField.swift; sourceTree = ""; }; 0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleGuidelinesProtocol.swift; sourceTree = ""; }; + 0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyRequiredModel.swift; sourceTree = ""; }; 0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDropdownEntryField.swift; sourceTree = ""; }; 0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = ""; }; 0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = ""; }; @@ -807,6 +809,7 @@ 011D95A0240453D0000E3791 /* RuleEqualsModel.swift */, 011D95A2240453F8000E3791 /* RuleRegexModel.swift */, 011D95A4240455DC000E3791 /* FormGroupRule.swift */, + 0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */, ); path = Rules; sourceTree = ""; @@ -1781,6 +1784,7 @@ D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */, DBC4391822442197001AB423 /* CaretView.swift in Sources */, C07065C42395677300FBF997 /* Link.swift in Sources */, + 0A69F611241BDEA700F7231B /* RuleAnyRequiredModel.swift in Sources */, D29770F221F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsTableViewController.m in Sources */, D29B771022C281F400D6ACE0 /* ModuleMolecule.swift in Sources */, D28A838923CCCFCB00DFE4FC /* LinkModel.swift in Sources */, diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyRequiredModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyRequiredModel.swift new file mode 100644 index 00000000..0eab62a7 --- /dev/null +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyRequiredModel.swift @@ -0,0 +1,23 @@ +// +// RuleAnyRequiredModel.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 3/13/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + + +public class RuleAnyRequiredModel: RulesProtocol { + + public static var identifier: String = "anyRequired" + public var type: String = RuleRequiredModel.identifier + public var fields: [String] + + public func isValid(_ formField: FormFieldProtocol) -> Bool { + guard let value = formField.formFieldValue() else { return false } + + return true + } +} diff --git a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift index 17a9972c..640dbebe 100644 --- a/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift +++ b/MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift @@ -124,6 +124,7 @@ import Foundation // Helper models try? ModelRegistry.register(RuleRequiredModel.self) + try? ModelRegistry.register(RuleAnyRequiredModel.self) try? ModelRegistry.register(RuleAnyValueChangedModel.self) try? ModelRegistry.register(RuleAllValueChangedModel.self) try? ModelRegistry.register(RuleEqualsModel.self) From 62fd6c988eb3428163e6437af315e609cd941ad9 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 13 Mar 2020 12:13:32 -0400 Subject: [PATCH 23/27] merge --- MVMCoreUI.xcodeproj/project.pbxproj | 25 +++++++------------ .../{New => }/FormActionFieldProtocol.swift | 0 .../{New => }/FormFieldProtocol.swift | 0 .../{New => }/FormHolderProtocol.swift | 0 .../{New => }/FormItemProtocol.swift | 0 .../{New => }/FormProtocol.swift | 0 .../{New => Rules}/Rules/FormGroupRule.swift | 0 .../Rules/RuleAllValueChangedModel.swift | 0 .../Rules/RuleAnyValueChangedModel.swift | 0 .../Rules/RuleEqualsModel.swift | 0 .../{New => Rules}/Rules/RuleRegexModel.swift | 0 .../Rules/RuleRequiredModel.swift | 0 .../{New => Rules}/Rules/RulesProtocol.swift | 0 .../{New => }/ValidProtocol.swift | 0 14 files changed, 9 insertions(+), 16 deletions(-) rename MVMCoreUI/FormUIHelpers/{New => }/FormActionFieldProtocol.swift (100%) rename MVMCoreUI/FormUIHelpers/{New => }/FormFieldProtocol.swift (100%) rename MVMCoreUI/FormUIHelpers/{New => }/FormHolderProtocol.swift (100%) rename MVMCoreUI/FormUIHelpers/{New => }/FormItemProtocol.swift (100%) rename MVMCoreUI/FormUIHelpers/{New => }/FormProtocol.swift (100%) rename MVMCoreUI/FormUIHelpers/{New => Rules}/Rules/FormGroupRule.swift (100%) rename MVMCoreUI/FormUIHelpers/{New => Rules}/Rules/RuleAllValueChangedModel.swift (100%) rename MVMCoreUI/FormUIHelpers/{New => Rules}/Rules/RuleAnyValueChangedModel.swift (100%) rename MVMCoreUI/FormUIHelpers/{New => Rules}/Rules/RuleEqualsModel.swift (100%) rename MVMCoreUI/FormUIHelpers/{New => Rules}/Rules/RuleRegexModel.swift (100%) rename MVMCoreUI/FormUIHelpers/{New => Rules}/Rules/RuleRequiredModel.swift (100%) rename MVMCoreUI/FormUIHelpers/{New => Rules}/Rules/RulesProtocol.swift (100%) rename MVMCoreUI/FormUIHelpers/{New => }/ValidProtocol.swift (100%) diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index b5985e36..e795475d 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -779,20 +779,6 @@ path = ModelProtocols; sourceTree = ""; }; - 011D9583240422BF000E3791 /* New */ = { - isa = PBXGroup; - children = ( - 011D958A24042794000E3791 /* Rules */, - 011D95882404249B000E3791 /* FormProtocol.swift */, - 011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */, - 011D95AA2405C553000E3791 /* FormItemProtocol.swift */, - 011D958624042492000E3791 /* FormFieldProtocol.swift */, - 011D95A824057AC7000E3791 /* FormActionFieldProtocol.swift */, - 011D9601240DA20A000E3791 /* ValidProtocol.swift */, - ); - path = New; - sourceTree = ""; - }; 011D958A24042794000E3791 /* Rules */ = { isa = PBXGroup; children = ( @@ -804,7 +790,8 @@ 011D95A2240453F8000E3791 /* RuleRegexModel.swift */, 011D95A4240455DC000E3791 /* FormGroupRule.swift */, ); - path = Rules; + name = Rules; + path = Rules/Rules; sourceTree = ""; }; 012A88EF23985E0100FE3DA1 /* CustomPrimitives */ = { @@ -826,8 +813,14 @@ 01C74D87224298E2009C25A3 /* FormUIHelpers */ = { isa = PBXGroup; children = ( - 011D9583240422BF000E3791 /* New */, + 011D95882404249B000E3791 /* FormProtocol.swift */, + 011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */, + 011D95AA2405C553000E3791 /* FormItemProtocol.swift */, + 011D958624042492000E3791 /* FormFieldProtocol.swift */, + 011D95A824057AC7000E3791 /* FormActionFieldProtocol.swift */, + 011D9601240DA20A000E3791 /* ValidProtocol.swift */, 0105618A224BBE7700E1557D /* FormValidator.swift */, + 011D958A24042794000E3791 /* Rules */, ); path = FormUIHelpers; sourceTree = ""; diff --git a/MVMCoreUI/FormUIHelpers/New/FormActionFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/FormActionFieldProtocol.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/FormActionFieldProtocol.swift rename to MVMCoreUI/FormUIHelpers/FormActionFieldProtocol.swift diff --git a/MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/FormFieldProtocol.swift rename to MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift diff --git a/MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift b/MVMCoreUI/FormUIHelpers/FormHolderProtocol.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/FormHolderProtocol.swift rename to MVMCoreUI/FormUIHelpers/FormHolderProtocol.swift diff --git a/MVMCoreUI/FormUIHelpers/New/FormItemProtocol.swift b/MVMCoreUI/FormUIHelpers/FormItemProtocol.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/FormItemProtocol.swift rename to MVMCoreUI/FormUIHelpers/FormItemProtocol.swift diff --git a/MVMCoreUI/FormUIHelpers/New/FormProtocol.swift b/MVMCoreUI/FormUIHelpers/FormProtocol.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/FormProtocol.swift rename to MVMCoreUI/FormUIHelpers/FormProtocol.swift diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/FormGroupRule.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/Rules/FormGroupRule.swift rename to MVMCoreUI/FormUIHelpers/Rules/Rules/FormGroupRule.swift diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAllValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAllValueChangedModel.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/Rules/RuleAllValueChangedModel.swift rename to MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAllValueChangedModel.swift diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyValueChangedModel.swift rename to MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/Rules/RuleEqualsModel.swift rename to MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRegexModel.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/Rules/RuleRegexModel.swift rename to MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRegexModel.swift diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRequiredModel.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/Rules/RuleRequiredModel.swift rename to MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRequiredModel.swift diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift rename to MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift diff --git a/MVMCoreUI/FormUIHelpers/New/ValidProtocol.swift b/MVMCoreUI/FormUIHelpers/ValidProtocol.swift similarity index 100% rename from MVMCoreUI/FormUIHelpers/New/ValidProtocol.swift rename to MVMCoreUI/FormUIHelpers/ValidProtocol.swift From f888358336380e3628fcb37c547c1a9410784750 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Fri, 13 Mar 2020 12:31:32 -0400 Subject: [PATCH 24/27] refactor --- MVMCoreUI/Atoms/TextFields/TextEntryField.swift | 2 +- MVMCoreUI/FormUIHelpers/FormValidator.swift | 2 +- .../Rules/Rules/RuleAnyValueChangedModel.swift | 4 ++-- MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift | 4 ++-- MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift index 993aed59..5df115d9 100644 --- a/MVMCoreUI/Atoms/TextFields/TextEntryField.swift +++ b/MVMCoreUI/Atoms/TextFields/TextEntryField.swift @@ -44,7 +44,7 @@ import UIKit private var observingForChange: Bool = false - /// Validate on each entry in the textField. Default: false + /// Validate on each entry in the textField. Default: true public var validateEachCharacter: Bool = true /// Validate when user resigns editing. Default: true diff --git a/MVMCoreUI/FormUIHelpers/FormValidator.swift b/MVMCoreUI/FormUIHelpers/FormValidator.swift index f2cdb8ea..8977fad5 100644 --- a/MVMCoreUI/FormUIHelpers/FormValidator.swift +++ b/MVMCoreUI/FormUIHelpers/FormValidator.swift @@ -66,7 +66,7 @@ import MVMCore public func validate(_ groupName: String, _ actionModel: FormActionFieldProtocol, _ rules: [RulesProtocol]) { var valid = true for rule in rules { - valid = valid && rule.isValid(self) + valid = valid && rule.isValid(fieldMolecules) if !valid { break } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift index f52dd92d..042243db 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleAnyValueChangedModel.swift @@ -18,9 +18,9 @@ public class RuleAnyValueChangedModel: RulesProtocol { return formField.baseValue != formField.formFieldValue() } - public func isValid(_ formValidator: FormValidator) -> Bool { + public func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { for formKey in fields { - guard let formField = formValidator.formField(for: formKey) else { + guard let formField = fieldMolecules[formKey] else { continue } if isValid(formField) { diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift index ac148a29..e6b338a4 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift @@ -18,11 +18,11 @@ public class RuleEqualsModel: RulesProtocol { return false } - public func isValid(_ formValidator: FormValidator) -> Bool { + public func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { var valid = true var compareValue: AnyHashable? for formKey in fields { - guard let formField = formValidator.formField(for: formKey) else { + guard let formField = fieldMolecules[formKey] else { continue } diff --git a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift index 16fe77b3..4c4a716d 100644 --- a/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift @@ -16,7 +16,7 @@ public enum RulesCodingKey: String, CodingKey { public protocol RulesProtocol: ModelProtocol { var type: String { get set } var fields: [String] { get set } - func isValid(_ formValidator: FormValidator) -> Bool + func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool func isValid(_ formField: FormFieldProtocol) -> Bool func setValid(_ formField: FormFieldProtocol, _ isValid: Bool) } @@ -35,10 +35,10 @@ public extension RulesProtocol { return "\(RulesProtocol.self)" } - func isValid(_ formValidator: FormValidator) -> Bool { + func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool { var valid = true for formKey in fields { - guard let formField = formValidator.formField(for: formKey) else { + guard let formField = fieldMolecules[formKey] else { continue } let fieldValidity = isValid(formField) From 227248afe014fdaa738274260cbceb229a1d2c2f Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 13 Mar 2020 15:16:19 -0400 Subject: [PATCH 25/27] logic for anyRequired --- .../New/Rules/RuleAnyRequiredModel.swift | 30 +++++++++++++++++-- .../New/Rules/RulesProtocol.swift | 13 ++++---- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyRequiredModel.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyRequiredModel.swift index 0eab62a7..af6f9095 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyRequiredModel.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RuleAnyRequiredModel.swift @@ -10,14 +10,40 @@ import UIKit public class RuleAnyRequiredModel: RulesProtocol { + //-------------------------------------------------- + // MARK: - Properties + //-------------------------------------------------- public static var identifier: String = "anyRequired" public var type: String = RuleRequiredModel.identifier public var fields: [String] - + + //-------------------------------------------------- + // MARK: - Methods + //-------------------------------------------------- + public func isValid(_ formField: FormFieldProtocol) -> Bool { guard let value = formField.formFieldValue() else { return false } - return true + if let valueString = value as? String { + return valueString.count > 0 + + } else if let valueBool = value as? Bool { + return valueBool + } + + return false + } + + public func isValid(_ formValidator: FormValidator) -> Bool { + + for formKey in fields { + guard let formField = formValidator.formField(for: formKey) else { continue } + + if isValid(formField) { + return true + } + } + return false } } diff --git a/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift b/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift index 16fe77b3..b666b895 100644 --- a/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/New/Rules/RulesProtocol.swift @@ -18,6 +18,7 @@ public protocol RulesProtocol: ModelProtocol { var fields: [String] { get set } func isValid(_ formValidator: FormValidator) -> Bool func isValid(_ formField: FormFieldProtocol) -> Bool +// func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool func setValid(_ formField: FormFieldProtocol, _ isValid: Bool) } @@ -36,22 +37,22 @@ public extension RulesProtocol { } func isValid(_ formValidator: FormValidator) -> Bool { + var valid = true + for formKey in fields { - guard let formField = formValidator.formField(for: formKey) else { - continue - } + guard let formField = formValidator.formField(for: formKey) else { continue } let fieldValidity = isValid(formField) setValid(formField, fieldValidity) valid = valid && fieldValidity } + return valid } func setValid(_ formField: FormFieldProtocol, _ isValid: Bool) { - guard let formFieldValid = formField as? ValidProtocol else { - return - } + guard let formFieldValid = formField as? ValidProtocol else { return } + formFieldValid.setValidity(isValid) } } From 86d2669beccee6fb32c84a4207c7eaca59a469c6 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 13 Mar 2020 18:05:01 -0400 Subject: [PATCH 26/27] changing so that page does not break if server doesn't send the value --- 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 99d493b8..0cd2f5ef 100644 --- a/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift +++ b/MVMCoreUI/Molecules/Items/DropDownListItemModel.swift @@ -51,7 +51,7 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) - molecules = try typeContainer.decodeModels2D(codingKey: .molecules) + molecules = try typeContainer.decodeModels2DIfPresent(codingKey: .molecules) ?? [[]] dropDown = try typeContainer.decode(ItemDropdownEntryFieldModel.self, forKey: .dropDown) try super.init(from: decoder) } From dd19a51417bdf521533178be9a5e189a1a11b36b Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Fri, 13 Mar 2020 19:03:12 -0400 Subject: [PATCH 27/27] additional change for empty --- MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift index f9b9d976..6b6f5a32 100644 --- a/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift +++ b/MVMCoreUI/Molecules/Items/DropDownFilterTableViewCell.swift @@ -30,7 +30,8 @@ import UIKit let self = self, let index = self.dropDown.pickerData.firstIndex(of: newValue), let dropListItemJSON = (self.listItemModel as? DropDownListItemModel).toJSON(), - let json2d = dropListItemJSON.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]] + let json2d = dropListItemJSON.optionalArrayForKey("molecules") as? [[[AnyHashable: Any]]], + !json2d.isEmpty && !(json2d.first?.isEmpty ?? false) else { return } if self.previousIndex != NSNotFound {