Merge branch 'develop' into feature/Headers_H2_NoButtons_BodyText
# Conflicts: # MVMCoreUI.xcodeproj/project.pbxproj # MVMCoreUI/OtherHandlers/MoleculeObjectMapping.swift
This commit is contained in:
commit
ce9d2be44f
@ -10,12 +10,25 @@
|
||||
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 */; };
|
||||
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 */; };
|
||||
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 /* 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 */; };
|
||||
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 */; };
|
||||
@ -26,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 */; };
|
||||
@ -43,13 +55,11 @@
|
||||
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 */; };
|
||||
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 */; };
|
||||
@ -81,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 */; };
|
||||
@ -110,8 +121,14 @@
|
||||
525019DE2406430800EED91C /* ListProgressBarData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525019DC2406430800EED91C /* ListProgressBarData.swift */; };
|
||||
525019E52406852100EED91C /* ListFourColumnDataUsageDividerModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525019E42406852100EED91C /* ListFourColumnDataUsageDividerModel.swift */; };
|
||||
525019E72406853600EED91C /* ListFourColumnDataUsageDivider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525019E62406853600EED91C /* ListFourColumnDataUsageDivider.swift */; };
|
||||
525239C02407BCFF00454969 /* ListTwoColumnPriceDetailsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525239BF2407BCFF00454969 /* ListTwoColumnPriceDetailsModel.swift */; };
|
||||
525239C22407BD1000454969 /* ListTwoColumnPriceDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 525239C12407BD1000454969 /* ListTwoColumnPriceDetails.swift */; };
|
||||
526A265C240D1FF700B0D828 /* ListTwoColumnCompareChangesModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 526A265B240D1FF700B0D828 /* ListTwoColumnCompareChangesModel.swift */; };
|
||||
526A265E240D200500B0D828 /* ListTwoColumnCompareChanges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 526A265D240D200500B0D828 /* ListTwoColumnCompareChanges.swift */; };
|
||||
52B201D224081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */; };
|
||||
52B201D324081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */; };
|
||||
8D084AD02410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */; };
|
||||
8D084AD22410BF7600951227 /* ListOneColumnFullWidthTextBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D084AD12410BF7600951227 /* ListOneColumnFullWidthTextBodyText.swift */; };
|
||||
8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */; };
|
||||
8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */; };
|
||||
8D448E5524050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */; };
|
||||
@ -185,6 +202,9 @@
|
||||
D22D1F47220496A30077CEC0 /* MVMCoreUISwitch.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */; };
|
||||
D22D1F562204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D22D1F572204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */; };
|
||||
D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */; };
|
||||
D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */; };
|
||||
D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */; };
|
||||
D243859923A16B1800332775 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = D243859823A16B1800332775 /* Container.swift */; };
|
||||
D256E9932412880000360572 /* Header.swift in Sources */ = {isa = PBXBuildFile; fileRef = D256E9922412880000360572 /* Header.swift */; };
|
||||
D260105323CEA61600764D80 /* ToggleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D260105223CEA61600764D80 /* ToggleModel.swift */; };
|
||||
@ -373,12 +393,25 @@
|
||||
01004F2F22721C3800991ECC /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = "<group>"; };
|
||||
0103B84D23D7E33A009C315C /* HeadlineBodyToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyToggleModel.swift; sourceTree = "<group>"; };
|
||||
0105618A224BBE7700E1557D /* FormValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidator.swift; sourceTree = "<group>"; };
|
||||
0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+TextFields.swift"; sourceTree = "<group>"; };
|
||||
0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FormValidator+FormParams.swift"; sourceTree = "<group>"; };
|
||||
0116A4E4228B19640094F3ED /* RadioButtonSelectionHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonSelectionHelper.swift; sourceTree = "<group>"; };
|
||||
011B58EF23A2AA980085F53C /* ListItemModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListItemModelProtocol.swift; sourceTree = "<group>"; };
|
||||
011B58F123A2AE2C0085F53C /* DropDownListItemModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DropDownListItemModel.swift; sourceTree = "<group>"; };
|
||||
011D958424042432000E3791 /* RulesProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RulesProtocol.swift; sourceTree = "<group>"; };
|
||||
011D958624042492000E3791 /* FormFieldProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormFieldProtocol.swift; sourceTree = "<group>"; };
|
||||
011D95882404249B000E3791 /* FormProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormProtocol.swift; sourceTree = "<group>"; };
|
||||
011D959A240451E3000E3791 /* RuleRequiredModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleRequiredModel.swift; sourceTree = "<group>"; };
|
||||
011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyValueChangedModel.swift; sourceTree = "<group>"; };
|
||||
011D959E240453A1000E3791 /* RuleAllValueChangedModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAllValueChangedModel.swift; sourceTree = "<group>"; };
|
||||
011D95A0240453D0000E3791 /* RuleEqualsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleEqualsModel.swift; sourceTree = "<group>"; };
|
||||
011D95A2240453F8000E3791 /* RuleRegexModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleRegexModel.swift; sourceTree = "<group>"; };
|
||||
011D95A4240455DC000E3791 /* FormGroupRule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormGroupRule.swift; sourceTree = "<group>"; };
|
||||
011D95A824057AC7000E3791 /* FormActionFieldProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormActionFieldProtocol.swift; sourceTree = "<group>"; };
|
||||
011D95AA2405C553000E3791 /* FormItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormItemProtocol.swift; sourceTree = "<group>"; };
|
||||
011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormHolderProtocol.swift; sourceTree = "<group>"; };
|
||||
011D95AE2407266E000E3791 /* RadioButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButtonModel.swift; sourceTree = "<group>"; };
|
||||
011D9601240DA20A000E3791 /* ValidProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidProtocol.swift; sourceTree = "<group>"; };
|
||||
011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonLabelModel.swift; sourceTree = "<group>"; };
|
||||
011D9627240EFA1E000E3791 /* MFViewController+Form.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFViewController+Form.swift"; sourceTree = "<group>"; };
|
||||
012A889B23889E8400FE3DA1 /* TemplateModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateModelProtocol.swift; sourceTree = "<group>"; };
|
||||
012A88AC238C418100FE3DA1 /* TemplateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateProtocol.swift; sourceTree = "<group>"; };
|
||||
012A88AE238C626E00FE3DA1 /* CarouselModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselModel.swift; sourceTree = "<group>"; };
|
||||
@ -389,7 +422,6 @@
|
||||
012A88C7238DB02000FE3DA1 /* ModelMoleculeDelegateProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelMoleculeDelegateProtocol.swift; sourceTree = "<group>"; };
|
||||
012A88EB238F084D00FE3DA1 /* FooterModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FooterModel.swift; sourceTree = "<group>"; };
|
||||
012A88F023985E0100FE3DA1 /* Color.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = "<group>"; };
|
||||
012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFTextField+ModelExtension.swift"; sourceTree = "<group>"; };
|
||||
012CA99D2385A2D3003F810F /* MFView+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFView+ModelExtension.swift"; sourceTree = "<group>"; };
|
||||
013F801823FB4A8E00AD8013 /* UIContentMode+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIContentMode+Extension.swift"; sourceTree = "<group>"; };
|
||||
014AA72123C501E2006F3E93 /* MoleculeContainerModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoleculeContainerModel.swift; sourceTree = "<group>"; };
|
||||
@ -406,13 +438,11 @@
|
||||
017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadioButtonLabel.swift; sourceTree = "<group>"; };
|
||||
017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MFViewController+Model.swift"; sourceTree = "<group>"; };
|
||||
017BEB3F23620A230024EF95 /* TextFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldModel.swift; sourceTree = "<group>"; };
|
||||
017BEB4123620AD20024EF95 /* FormModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormModelProtocol.swift; sourceTree = "<group>"; };
|
||||
017BEB432362192F0024EF95 /* MVMCoreUIMoleculeMappingObject+ModelExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MVMCoreUIMoleculeMappingObject+ModelExtension.swift"; sourceTree = "<group>"; };
|
||||
017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeViewProtocol.swift; sourceTree = "<group>"; };
|
||||
017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModelMoleculeViewProtocol.swift; sourceTree = "<group>"; };
|
||||
017BEB7A236763000024EF95 /* LineModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineModel.swift; sourceTree = "<group>"; };
|
||||
017BEB7E23676E870024EF95 /* MoleculeObjectMapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoleculeObjectMapping.swift; sourceTree = "<group>"; };
|
||||
0198F79E225679870066C936 /* FormValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormValidationProtocol.swift; sourceTree = "<group>"; };
|
||||
0198F7A02256A80A0066C936 /* MFRadioButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MFRadioButton.h; sourceTree = "<group>"; };
|
||||
0198F7A22256A80A0066C936 /* MFRadioButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MFRadioButton.m; sourceTree = "<group>"; };
|
||||
01C851D223CF9E740021F976 /* LabelToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LabelToggleModel.swift; sourceTree = "<group>"; };
|
||||
@ -432,6 +462,7 @@
|
||||
0A41BA6D2344FCD400D4C0BC /* CATransaction+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CATransaction+Extension.swift"; sourceTree = "<group>"; };
|
||||
0A41BA7E23453A6400D4C0BC /* TextEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextEntryField.swift; sourceTree = "<group>"; };
|
||||
0A5D59C123AD2F5700EFD9E9 /* AppleGuidelinesProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleGuidelinesProtocol.swift; sourceTree = "<group>"; };
|
||||
0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyRequiredModel.swift; sourceTree = "<group>"; };
|
||||
0A6BF4712360C56C0028F841 /* BaseDropdownEntryField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseDropdownEntryField.swift; sourceTree = "<group>"; };
|
||||
0A7BAD73232A8DC700FB8E22 /* HeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadlineBodyButton.swift; sourceTree = "<group>"; };
|
||||
0A7BAFA0232BE61800FB8E22 /* Checkbox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checkbox.swift; sourceTree = "<group>"; };
|
||||
@ -464,8 +495,14 @@
|
||||
525019DC2406430800EED91C /* ListProgressBarData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListProgressBarData.swift; sourceTree = "<group>"; };
|
||||
525019E42406852100EED91C /* ListFourColumnDataUsageDividerModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageDividerModel.swift; sourceTree = "<group>"; };
|
||||
525019E62406853600EED91C /* ListFourColumnDataUsageDivider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFourColumnDataUsageDivider.swift; sourceTree = "<group>"; };
|
||||
525239BF2407BCFF00454969 /* ListTwoColumnPriceDetailsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDetailsModel.swift; sourceTree = "<group>"; };
|
||||
525239C12407BD1000454969 /* ListTwoColumnPriceDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDetails.swift; sourceTree = "<group>"; };
|
||||
526A265B240D1FF700B0D828 /* ListTwoColumnCompareChangesModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnCompareChangesModel.swift; sourceTree = "<group>"; };
|
||||
526A265D240D200500B0D828 /* ListTwoColumnCompareChanges.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListTwoColumnCompareChanges.swift; sourceTree = "<group>"; };
|
||||
52B201D024081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonAndPaymentMethod.swift; sourceTree = "<group>"; };
|
||||
52B201D124081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListLeftVariableRadioButtonAndPaymentMethodModel.swift; sourceTree = "<group>"; };
|
||||
8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextBodyTextModel.swift; sourceTree = "<group>"; };
|
||||
8D084AD12410BF7600951227 /* ListOneColumnFullWidthTextBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextBodyText.swift; sourceTree = "<group>"; };
|
||||
8D24041023E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaret.swift; sourceTree = "<group>"; };
|
||||
8D24041423E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconWithRightCaretModel.swift; sourceTree = "<group>"; };
|
||||
8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListOneColumnFullWidthTextAllTextAndLinksModel.swift; sourceTree = "<group>"; };
|
||||
@ -538,6 +575,9 @@
|
||||
D22D1F45220496A30077CEC0 /* MVMCoreUISwitch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUISwitch.m; sourceTree = "<group>"; };
|
||||
D22D1F542204CE5D0077CEC0 /* MVMCoreUIStackableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MVMCoreUIStackableViewController.h; sourceTree = "<group>"; };
|
||||
D22D1F552204CE5D0077CEC0 /* MVMCoreUIStackableViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MVMCoreUIStackableViewController.m; sourceTree = "<group>"; };
|
||||
D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStackView+Extension.swift"; sourceTree = "<group>"; };
|
||||
D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescription.swift; sourceTree = "<group>"; };
|
||||
D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListTwoColumnPriceDescriptionModel.swift; sourceTree = "<group>"; };
|
||||
D243859823A16B1800332775 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = "<group>"; };
|
||||
D256E9922412880000360572 /* Header.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Header.swift; sourceTree = "<group>"; };
|
||||
D260105223CEA61600764D80 /* ToggleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleModel.swift; sourceTree = "<group>"; };
|
||||
@ -752,7 +792,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
014AA72323C501E2006F3E93 /* ContainerModelProtocol.swift */,
|
||||
017BEB4123620AD20024EF95 /* FormModelProtocol.swift */,
|
||||
012A88C3238D86E600FE3DA1 /* CarouselItemModelProtocol.swift */,
|
||||
012A88B0238C880100FE3DA1 /* CarouselPagingModelProtocol.swift */,
|
||||
01EB3683236097C0006832FA /* MoleculeModelProtocol.swift */,
|
||||
@ -764,6 +803,22 @@
|
||||
path = ModelProtocols;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
011D958A24042794000E3791 /* Rules */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
011D958424042432000E3791 /* RulesProtocol.swift */,
|
||||
011D959A240451E3000E3791 /* RuleRequiredModel.swift */,
|
||||
011D959C2404536F000E3791 /* RuleAnyValueChangedModel.swift */,
|
||||
011D959E240453A1000E3791 /* RuleAllValueChangedModel.swift */,
|
||||
011D95A0240453D0000E3791 /* RuleEqualsModel.swift */,
|
||||
011D95A2240453F8000E3791 /* RuleRegexModel.swift */,
|
||||
011D95A4240455DC000E3791 /* FormGroupRule.swift */,
|
||||
0A69F610241BDEA700F7231B /* RuleAnyRequiredModel.swift */,
|
||||
);
|
||||
name = Rules;
|
||||
path = Rules/Rules;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
012A88EF23985E0100FE3DA1 /* CustomPrimitives */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -783,10 +838,14 @@
|
||||
01C74D87224298E2009C25A3 /* FormUIHelpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0198F79E225679870066C936 /* FormValidationProtocol.swift */,
|
||||
011D95882404249B000E3791 /* FormProtocol.swift */,
|
||||
011D95AC2406BB57000E3791 /* FormHolderProtocol.swift */,
|
||||
011D95AA2405C553000E3791 /* FormItemProtocol.swift */,
|
||||
011D958624042492000E3791 /* FormFieldProtocol.swift */,
|
||||
011D95A824057AC7000E3791 /* FormActionFieldProtocol.swift */,
|
||||
011D9601240DA20A000E3791 /* ValidProtocol.swift */,
|
||||
0105618A224BBE7700E1557D /* FormValidator.swift */,
|
||||
0105618C224BBE7700E1557D /* FormValidator+FormParams.swift */,
|
||||
0105618B224BBE7700E1557D /* FormValidator+TextFields.swift */,
|
||||
011D958A24042794000E3791 /* Rules */,
|
||||
);
|
||||
path = FormUIHelpers;
|
||||
sourceTree = "<group>";
|
||||
@ -836,6 +895,8 @@
|
||||
children = (
|
||||
8D448E5424050A46006211BB /* ListOneColumnFullWidthTextAllTextAndLinksModel.swift */,
|
||||
52267A0623FFE25000906CBA /* ListOneColumnFullWidthTextAllTextAndLinks.swift */,
|
||||
8D084ACF2410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift */,
|
||||
8D084AD12410BF7600951227 /* ListOneColumnFullWidthTextBodyText.swift */,
|
||||
);
|
||||
path = OneColumn;
|
||||
sourceTree = "<group>";
|
||||
@ -858,6 +919,13 @@
|
||||
path = LockUps;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
526A265A240D1FCE00B0D828 /* TwoColumn */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
path = TwoColumn;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
94C2D9822386F3E30006CF46 /* Label */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1075,6 +1143,7 @@
|
||||
D22B38EA23F4E08B00490EF6 /* List */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D22D8396241FDE4700D3DF69 /* TwoColumn */,
|
||||
52267A0523FFE0A900906CBA /* OneColumn */,
|
||||
AA4FC2A323F4F69600E251DB /* RightVariable */,
|
||||
D22B38EB23F4E0AE00490EF6 /* LeftVariable */,
|
||||
@ -1098,6 +1167,7 @@
|
||||
D22B38EC23F4E10700490EF6 /* SectionDividers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
526A265A240D1FCE00B0D828 /* TwoColumn */,
|
||||
525019E3240684E500EED91C /* FourColumn */,
|
||||
D22B38ED23F4E11100490EF6 /* ThreeColumn */,
|
||||
);
|
||||
@ -1122,6 +1192,19 @@
|
||||
path = Legacy;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D22D8396241FDE4700D3DF69 /* TwoColumn */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D236E5B3241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift */,
|
||||
D236E5B2241FEB1000C38625 /* ListTwoColumnPriceDescription.swift */,
|
||||
526A265B240D1FF700B0D828 /* ListTwoColumnCompareChangesModel.swift */,
|
||||
526A265D240D200500B0D828 /* ListTwoColumnCompareChanges.swift */,
|
||||
525239BF2407BCFF00454969 /* ListTwoColumnPriceDetailsModel.swift */,
|
||||
525239C12407BD1000454969 /* ListTwoColumnPriceDetails.swift */,
|
||||
);
|
||||
path = TwoColumn;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D260105723CF9CC500764D80 /* Doughnut */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -1233,6 +1316,7 @@
|
||||
D29B770F22C281F400D6ACE0 /* ModuleMolecule.swift */,
|
||||
D28A838423CCCA8900DFE4FC /* ScrollerModel.swift */,
|
||||
D2D6CD3F22E78C1A00D701B8 /* Scroller.swift */,
|
||||
011D9625240EBB16000E3791 /* RadioButtonLabelModel.swift */,
|
||||
017BEB372360C6AC0024EF95 /* RadioButtonLabel.swift */,
|
||||
017BEB47236230DB0024EF95 /* MoleculeViewProtocol.swift */,
|
||||
017BEB49236235BA0024EF95 /* ModelMoleculeViewProtocol.swift */,
|
||||
@ -1247,6 +1331,7 @@
|
||||
D29DF16021E69996003B2FB9 /* MFViewController.h */,
|
||||
D29DF15F21E69996003B2FB9 /* MFViewController.m */,
|
||||
017BEB3B2361EA1D0024EF95 /* MFViewController+Model.swift */,
|
||||
011D9627240EFA1E000E3791 /* MFViewController+Form.swift */,
|
||||
D29DF28F21E7ADB8003B2FB9 /* MFScrollingViewController.h */,
|
||||
D29DF29021E7ADB8003B2FB9 /* MFScrollingViewController.m */,
|
||||
D29DF29121E7ADB8003B2FB9 /* ProgrammaticScrollViewController.h */,
|
||||
@ -1274,6 +1359,7 @@
|
||||
D29DF11421E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m */,
|
||||
D22479932316AE5E003FCCF9 /* NSLayoutConstraintExtension.swift */,
|
||||
0AA33B33239813C50067DD0F /* UIColor+Extension.swift */,
|
||||
D22D8394241FB41200D3DF69 /* UIStackView+Extension.swift */,
|
||||
);
|
||||
path = Categories;
|
||||
sourceTree = "<group>";
|
||||
@ -1419,7 +1505,6 @@
|
||||
0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */,
|
||||
0ABD1370237DB0450081388D /* ItemDropdownEntryField.swift */,
|
||||
017BEB3F23620A230024EF95 /* TextFieldModel.swift */,
|
||||
012CA9992384A687003F810F /* MFTextField+ModelExtension.swift */,
|
||||
);
|
||||
path = TextFields;
|
||||
sourceTree = "<group>";
|
||||
@ -1743,6 +1828,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 */,
|
||||
@ -1765,6 +1851,8 @@
|
||||
D282AAB4223FDDAE00C46919 /* MFLoadImageView.swift in Sources */,
|
||||
D29DF11721E6805F003B2FB9 /* UIColor+MFConvenience.m in Sources */,
|
||||
D2B18B7F2360913400A9AEDC /* Control.swift in Sources */,
|
||||
011D95A924057AC7000E3791 /* FormActionFieldProtocol.swift in Sources */,
|
||||
D236E5B4241FEB1000C38625 /* ListTwoColumnPriceDescription.swift in Sources */,
|
||||
0AA33B3A2398524F0067DD0F /* Toggle.swift in Sources */,
|
||||
D29DF12F21E6851E003B2FB9 /* MVMCoreUITopAlertMainView.m in Sources */,
|
||||
942C378C2412F4FA0066E45E /* ModalMoleculeListTemplate.swift in Sources */,
|
||||
@ -1779,9 +1867,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 */,
|
||||
@ -1807,8 +1897,11 @@
|
||||
012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */,
|
||||
D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */,
|
||||
94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */,
|
||||
D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */,
|
||||
52B201D324081CFB00D2011E /* ListLeftVariableRadioButtonAndPaymentMethodModel.swift in Sources */,
|
||||
525239C02407BCFF00454969 /* ListTwoColumnPriceDetailsModel.swift in Sources */,
|
||||
D2E2A99A23D8D6B4000B42E6 /* HeadlineBodyButtonModel.swift in Sources */,
|
||||
8D084AD22410BF7600951227 /* ListOneColumnFullWidthTextBodyText.swift in Sources */,
|
||||
014AA73123C5059B006F3E93 /* ListPageTemplateModel.swift in Sources */,
|
||||
017BEB4023620A230024EF95 /* TextFieldModel.swift in Sources */,
|
||||
D29DF2A221E7AF4E003B2FB9 /* MVMCoreUIUtility.m in Sources */,
|
||||
@ -1821,6 +1914,7 @@
|
||||
AA11A42123F15D7000D7962F /* ListRightVariablePaymentsModel.swift in Sources */,
|
||||
01EB369223609801006832FA /* MoleculeStackModel.swift in Sources */,
|
||||
012CA99E2385A2D3003F810F /* MFView+ModelExtension.swift in Sources */,
|
||||
011D9626240EBB16000E3791 /* RadioButtonLabelModel.swift in Sources */,
|
||||
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */,
|
||||
D282AABA224131D100C46919 /* MFTransparentGIFView.swift in Sources */,
|
||||
944589232385DA9600DE9FD4 /* ImageViewModel.swift in Sources */,
|
||||
@ -1838,6 +1932,8 @@
|
||||
DBEFFA04225A829700230692 /* Label.swift in Sources */,
|
||||
D2D6CD4022E78C1A00D701B8 /* Scroller.swift in Sources */,
|
||||
0A7EF85F23D8ABC500B2AAD1 /* MdnEntryFieldModel.swift in Sources */,
|
||||
011D959B240451E3000E3791 /* RuleRequiredModel.swift in Sources */,
|
||||
526A265C240D1FF700B0D828 /* ListTwoColumnCompareChangesModel.swift in Sources */,
|
||||
01509D952327ED1900EF99AA /* HeadlineBodyLinkToggle.swift in Sources */,
|
||||
31BE15CB23D8924D00452370 /* CheckboxLabelModel.swift in Sources */,
|
||||
D260105523CEA7DC00764D80 /* MVMCoreUISwitch+Model.swift in Sources */,
|
||||
@ -1868,7 +1964,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 */,
|
||||
@ -1883,6 +1978,7 @@
|
||||
017BEB7B236763000024EF95 /* LineModel.swift in Sources */,
|
||||
D256E9932412880000360572 /* Header.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 */,
|
||||
@ -1895,15 +1991,18 @@
|
||||
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 */,
|
||||
526A265E240D200500B0D828 /* ListTwoColumnCompareChanges.swift in Sources */,
|
||||
8D24041523E7FC0B009E23BE /* ListLeftVariableIconWithRightCaretModel.swift in Sources */,
|
||||
D28A838F23CCDEDE00DFE4FC /* TwoButtonViewModel.swift in Sources */,
|
||||
D2D90B42240463E100DD6EC9 /* MoleculeHeaderModel.swift in Sources */,
|
||||
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 */,
|
||||
@ -1914,6 +2013,7 @@
|
||||
D29DF16121E69996003B2FB9 /* MFViewController.m in Sources */,
|
||||
AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */,
|
||||
522679C223FE886900906CBA /* ListLeftVariableCheckboxAllTextAndLinksModel.swift in Sources */,
|
||||
8D084AD02410BF4800951227 /* ListOneColumnFullWidthTextBodyTextModel.swift in Sources */,
|
||||
0ABD1371237DB0450081388D /* ItemDropdownEntryField.swift in Sources */,
|
||||
8D24041123E7FB9E009E23BE /* ListLeftVariableIconWithRightCaret.swift in Sources */,
|
||||
D2E1FAE12268E81D00AEFD8C /* MoleculeListTemplate.swift in Sources */,
|
||||
@ -1925,7 +2025,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 */,
|
||||
@ -1933,11 +2032,9 @@
|
||||
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 */,
|
||||
0198F79F225679880066C936 /* FormValidationProtocol.swift in Sources */,
|
||||
D243859923A16B1800332775 /* Container.swift in Sources */,
|
||||
D2C521A923EDE79E00CA2634 /* ViewController.swift in Sources */,
|
||||
D260105B23D0BB7100764D80 /* StackModelProtocol.swift in Sources */,
|
||||
@ -1955,15 +2052,19 @@
|
||||
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 */,
|
||||
525239C22407BD1000454969 /* ListTwoColumnPriceDetails.swift in Sources */,
|
||||
D2A5146122121FBF00345BFB /* MoleculeStackTemplate.swift in Sources */,
|
||||
D2E2A9A323E096B1000B42E6 /* DisableableModelProtocol.swift in Sources */,
|
||||
D29DF11821E6805F003B2FB9 /* NSLayoutConstraint+MFConvenience.m in Sources */,
|
||||
@ -1983,13 +2084,14 @@
|
||||
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 */,
|
||||
D236E5B5241FEB1000C38625 /* ListTwoColumnPriceDescriptionModel.swift in Sources */,
|
||||
D2B18B922361E65A00A9AEDC /* CoreUIObject.swift in Sources */,
|
||||
D29DF2BE21E7BEA4003B2FB9 /* TopTabbar.m in Sources */,
|
||||
014AA72E23C5059B006F3E93 /* StackCenteredPageTemplateModel.swift in Sources */,
|
||||
D2A514632213643100345BFB /* MoleculeStackCenteredTemplate.swift in Sources */,
|
||||
011D959D2404536F000E3791 /* RuleAnyValueChangedModel.swift in Sources */,
|
||||
D260105923D0A92900764D80 /* ContainerProtocol.swift in Sources */,
|
||||
C695A69423C9909000BFB94E /* DoughnutChartModel.swift in Sources */,
|
||||
D29DF32421ED0DA2003B2FB9 /* TextButtonView.m in Sources */,
|
||||
@ -1998,6 +2100,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 */,
|
||||
525019DD2406430800EED91C /* ListProgressBarDataModel.swift in Sources */,
|
||||
C6FA7D5223C77A4A00A3614A /* UnOrderedList.swift in Sources */,
|
||||
@ -2007,6 +2110,8 @@
|
||||
D22D1F1B220341F60077CEC0 /* MVMCoreUICheckBox.m in Sources */,
|
||||
C695A69823C990C200BFB94E /* DoughnutChartView.swift in Sources */,
|
||||
D29DF2CB21E7BFCC003B2FB9 /* MFSizeThreshold.m in Sources */,
|
||||
011D959F240453A1000E3791 /* RuleAllValueChangedModel.swift in Sources */,
|
||||
011D95AD2406BB57000E3791 /* FormHolderProtocol.swift in Sources */,
|
||||
01509D932327ECFB00EF99AA /* ProgressBar.swift in Sources */,
|
||||
D260106523D0CEA700764D80 /* StackModel.swift in Sources */,
|
||||
D29770F521F7C6D600B2F0D0 /* TopLabelsAndBottomButtonsViewController.m in Sources */,
|
||||
|
||||
@ -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? = FormValidator.defaultGroupName
|
||||
|
||||
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,9 @@ 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)
|
||||
required = try typeContainer.decodeIfPresent(Bool.self, forKey: .required)
|
||||
requiredGroups = try typeContainer.decodeIfPresent([String].self, forKey: .requiredGroups)
|
||||
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
|
||||
}
|
||||
@ -110,7 +117,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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,6 +36,13 @@ import UIKit
|
||||
context?.strokePath()
|
||||
}
|
||||
|
||||
open override var intrinsicContentSize: CGSize {
|
||||
guard let size = titleLabel?.intrinsicContentSize else {
|
||||
return super.intrinsicContentSize
|
||||
}
|
||||
return CGSize(width: size.width, height: size.height + 2)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - ModelMoleculeViewProtocol
|
||||
//--------------------------------------------------
|
||||
@ -81,6 +88,7 @@ extension Link {
|
||||
titleLabel?.lineBreakMode = .byTruncatingTail
|
||||
titleLabel?.textAlignment = .left
|
||||
contentHorizontalAlignment = .left
|
||||
contentVerticalAlignment = .top
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,14 +16,6 @@ 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 let style = model.style {
|
||||
switch style {
|
||||
case .primary:
|
||||
|
||||
@ -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 {
|
||||
|
||||
|
||||
@ -9,7 +9,8 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
@objcMembers public class EntryFieldModel: MoleculeModelProtocol {
|
||||
@objcMembers public class EntryFieldModel: MoleculeModelProtocol, FormFieldProtocol, ValidProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
@ -26,8 +27,19 @@ import Foundation
|
||||
public var isLocked: Bool?
|
||||
public var isSelected: Bool?
|
||||
public var fieldKey: String?
|
||||
public var isValid: Bool?
|
||||
public var isRequired: Bool?
|
||||
public var groupName: String? = FormValidator.defaultGroupName
|
||||
public var text: String?
|
||||
public var baseValue: AnyHashable?
|
||||
|
||||
public var isValid: Bool? {
|
||||
didSet {
|
||||
updateUI?()
|
||||
}
|
||||
}
|
||||
public var updateUI: (() -> Void)?
|
||||
public func setValidity(_ isValid: Bool) {
|
||||
self.isValid = isValid
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
@ -45,6 +57,12 @@ import Foundation
|
||||
case fieldKey
|
||||
case isValid
|
||||
case isRequired = "required"
|
||||
case text
|
||||
case groupName
|
||||
}
|
||||
|
||||
public func formFieldValue() -> AnyHashable? {
|
||||
return text
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
@ -62,6 +80,11 @@ 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)
|
||||
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
self.groupName = groupName
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -76,5 +99,7 @@ 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)
|
||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,24 +97,24 @@ import MVMCore
|
||||
return MVMCoreUIUtility.validateInternationalMDNString(MDN)
|
||||
}
|
||||
|
||||
@objc public override func validateTextField() -> Bool {
|
||||
@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
|
||||
}
|
||||
|
||||
@ -186,7 +186,7 @@ import MVMCore
|
||||
|
||||
proprietorTextDelegate?.textFieldDidEndEditing?(textField)
|
||||
|
||||
if validateTextField() && isNationalMDN {
|
||||
if validateMDNTextField() && isNationalMDN {
|
||||
textField.text = MVMCoreUIUtility.formatMdn(textField.text)
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,12 +44,12 @@ import UIKit
|
||||
|
||||
private var observingForChange: Bool = false
|
||||
|
||||
/// Validate on each entry in the textField. Default: false
|
||||
public var validateEachCharacter: Bool = false
|
||||
/// Validate on each entry in the textField. Default: true
|
||||
public var validateEachCharacter: Bool = true
|
||||
|
||||
/// Validate when user resigns editing. Default: true
|
||||
public var validateWhenDoneEditing: Bool = true
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Computed Properties
|
||||
//--------------------------------------------------
|
||||
@ -197,9 +197,8 @@ import UIKit
|
||||
@objc deinit {
|
||||
setBothTextDelegates(to: nil)
|
||||
}
|
||||
|
||||
|
||||
@objc public func setBothTextDelegates(to delegate: (UITextFieldDelegate & ObservingTextFieldDelegate)?) {
|
||||
|
||||
observingTextFieldDelegate = delegate
|
||||
uiTextFieldDelegate = delegate
|
||||
}
|
||||
@ -218,62 +217,55 @@ 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
|
||||
|
||||
if isValid {
|
||||
showError = false
|
||||
observingTextFieldDelegate?.isValid?(textfield: self)
|
||||
|
||||
} else {
|
||||
@objc public func validateTextField() {
|
||||
text = textField.text
|
||||
FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||
}
|
||||
|
||||
@objc public func updateValidation(_ isValid: Bool) {
|
||||
let previousValidity = self.isValid
|
||||
self.isValid = isValid
|
||||
|
||||
if previousValidity && !isValid {
|
||||
showError = true
|
||||
observingTextFieldDelegate?.isInvalid?(textfield: self)
|
||||
} else if (!previousValidity && isValid) {
|
||||
showError = false
|
||||
observingTextFieldDelegate?.isValid?(textfield: self)
|
||||
}
|
||||
|
||||
return isValid
|
||||
}
|
||||
|
||||
/// Executes on UITextField.textDidBeginEditingNotification
|
||||
@objc func startEditing() {
|
||||
|
||||
isSelected = true
|
||||
textField.becomeFirstResponder()
|
||||
}
|
||||
|
||||
/// Executes on UITextField.textDidChangeNotification (each character entry)
|
||||
@objc func valueChanged() {
|
||||
|
||||
guard validateEachCharacter else { return }
|
||||
|
||||
isSelected = true
|
||||
validateTextField()
|
||||
}
|
||||
|
||||
/// 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 +273,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 +309,8 @@ import UIKit
|
||||
defaultValidationBlock()
|
||||
}
|
||||
|
||||
if let formValidationProtocol = delegateObject?.formValidationProtocol {
|
||||
observingTextFieldDelegate = FormValidator.getFormValidatorFor(delegate: formValidationProtocol)
|
||||
}
|
||||
|
||||
uiTextFieldDelegate = delegateObject?.uiTextFieldDelegate
|
||||
observingTextFieldDelegate = delegateObject?.observingTextFieldDelegate
|
||||
MVMCoreUICommonViewsUtility.addDismissToolbar(textField, delegate: uiTextFieldDelegate)
|
||||
}
|
||||
}
|
||||
@ -330,9 +324,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 +366,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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
return "textField"
|
||||
}
|
||||
|
||||
public var text: String?
|
||||
public var placeholder: String?
|
||||
public var enabledTextColor: Color?
|
||||
public var disabledTextColor: Color?
|
||||
|
||||
@ -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?
|
||||
|
||||
@ -126,9 +126,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()
|
||||
}
|
||||
}
|
||||
@ -399,14 +400,9 @@ import MVMCore
|
||||
|
||||
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.fieldValue
|
||||
FormValidator.setupValidation(molecule: model, delegate: delegateObject?.formHolderDelegate)
|
||||
|
||||
if let fieldKey = model.fieldKey {
|
||||
self.fieldKey = fieldKey
|
||||
@ -440,23 +436,3 @@ import MVMCore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK:- FormValidationProtocol
|
||||
extension Checkbox: FormValidationFormFieldProtocol {
|
||||
|
||||
public func formFieldGroupName() -> String? {
|
||||
return groupName
|
||||
}
|
||||
|
||||
public func isValidField() -> Bool {
|
||||
return (fieldKey != nil) ? isSelected : true
|
||||
}
|
||||
|
||||
public func formFieldName() -> String? {
|
||||
return fieldKey
|
||||
}
|
||||
|
||||
public func formFieldValue() -> Any? {
|
||||
return fieldValue ?? (isSelected ? fieldValue : nil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,18 +8,13 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class CheckboxModel: MoleculeModelProtocol {
|
||||
@objcMembers public class CheckboxModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "checkbox"
|
||||
public var backgroundColor: Color?
|
||||
|
||||
public var groupName: String?
|
||||
public var fieldKey: String?
|
||||
public var fieldValue: JSONValue?
|
||||
|
||||
public var isChecked: Bool = false
|
||||
public var isEnabled: Bool = true
|
||||
public var isAnimated: Bool = true
|
||||
@ -34,13 +29,18 @@ import Foundation
|
||||
public var disabledCheckColor: Color = Color(uiColor: .mvmCoolGray3)
|
||||
public var action: ActionModelProtocol?
|
||||
|
||||
|
||||
public var fieldKey: String?
|
||||
public var fieldValue: JSONValue?
|
||||
public var groupName: String? = FormValidator.defaultGroupName
|
||||
public var baseValue: AnyHashable?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case groupName
|
||||
case fieldKey
|
||||
case fieldValue
|
||||
case isChecked = "checked"
|
||||
@ -56,17 +56,21 @@ import Foundation
|
||||
case disabledCheckColor
|
||||
case disabledBorderColor
|
||||
case action
|
||||
case groupName
|
||||
}
|
||||
|
||||
init(isChecked: Bool = false) {}
|
||||
|
||||
public func formFieldValue() -> AnyHashable? {
|
||||
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)
|
||||
fieldValue = try typeContainer.decodeIfPresent(JSONValue.self, forKey: .fieldValue)
|
||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||
borderWidth = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .borderWidth) ?? 1
|
||||
@ -82,6 +86,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)
|
||||
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||
self.groupName = groupName
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -103,5 +110,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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ import Foundation
|
||||
var location: Int
|
||||
var length: Int
|
||||
|
||||
init(_ location: Int, _ length: Int) {
|
||||
public init(_ location: Int, _ length: Int) {
|
||||
self.location = location
|
||||
self.length = length
|
||||
}
|
||||
|
||||
@ -19,4 +19,8 @@ import UIKit
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
}
|
||||
|
||||
public override init(_ location: Int, _ length: Int) {
|
||||
super.init(location, length)
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ public typealias CoreObjectActionLoadPresentDelegate = MVMCoreActionDelegateProt
|
||||
return NSRange(location: 0, length: frontText?.count ?? 0)
|
||||
}
|
||||
|
||||
private var actionRange: NSRange {
|
||||
public var actionRange: NSRange {
|
||||
return NSRange(location: frontText?.count ?? 0, length: actionText?.count ?? 0)
|
||||
}
|
||||
|
||||
|
||||
@ -8,14 +8,22 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers public class LeftRightLabelModel: MoleculeModelProtocol {
|
||||
@objcMembers open class LeftRightLabelModel: MoleculeModelProtocol {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
public static var identifier: String = "leftRightLabelView"
|
||||
public var moleculeName: String? = LeftRightLabelModel.identifier
|
||||
public var backgroundColor: Color?
|
||||
public var leftText: LabelModel
|
||||
public var rightText: LabelModel?
|
||||
|
||||
init(_ leftText: LabelModel) {
|
||||
//--------------------------------------------------
|
||||
// MARK: - Initializer
|
||||
//--------------------------------------------------
|
||||
|
||||
public init(_ leftText: LabelModel) {
|
||||
self.leftText = leftText
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,7 +181,7 @@ import UIKit
|
||||
let widthWillChange = !MVMCoreGetterUtility.cgfequal(widthConstraint?.constant ?? 0, width ?? 0)
|
||||
let heightWillChange = !MVMCoreGetterUtility.cgfequal(heightConstraint?.constant ?? 0, height ?? 0)
|
||||
let sizeWillChange = (width == nil || height == nil) && !(size?.equalTo(imageView.image?.size ?? CGSize.zero) ?? false)
|
||||
let heightChangeFromSpinner = ((height ?? size?.height) ?? 0) < loadingSpinnerHeightConstraint?.constant ?? CGFloat.leastNormalMagnitude
|
||||
let heightChangeFromSpinner = (heightConstraint?.isActive ?? false) ? false : ((height ?? size?.height) ?? 0) < loadingSpinnerHeightConstraint?.constant ?? CGFloat.leastNormalMagnitude
|
||||
return widthWillChange || heightWillChange || sizeWillChange || heightChangeFromSpinner
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 }
|
||||
|
||||
@ -8,34 +8,33 @@
|
||||
|
||||
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()
|
||||
|
||||
var disabledColor = UIColor.mfSilver()
|
||||
var delegateObject: MVMCoreUIDelegateObject?
|
||||
|
||||
var fieldKey: String?
|
||||
var formValue: Bool?
|
||||
var isRequired: Bool = false
|
||||
|
||||
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?.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 +57,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 +71,15 @@ import UIKit
|
||||
}
|
||||
|
||||
public func formFieldName() -> String? {
|
||||
return json?.optionalStringForKey("fieldKey")
|
||||
return radioModel?.fieldKey
|
||||
}
|
||||
|
||||
public func formFieldGroupName() -> String? {
|
||||
return json?.optionalStringForKey("groupName")
|
||||
return radioModel?.fieldKey
|
||||
}
|
||||
|
||||
public func formFieldValue() -> Any? {
|
||||
return isSelected
|
||||
public func formFieldValue() -> AnyHashable? {
|
||||
return radioModel?.fieldValue
|
||||
}
|
||||
|
||||
// MARK: - MVMViewProtocol
|
||||
@ -104,40 +103,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
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,11 +7,60 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import MVMCore
|
||||
|
||||
public class RadioButtonModel: MoleculeModelProtocol, FormFieldProtocol {
|
||||
|
||||
public class RadioButtonModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "radioButton"
|
||||
public var backgroundColor: Color?
|
||||
public var state: Bool = false
|
||||
public var enabled: Bool = true
|
||||
|
||||
public var baseValue: AnyHashable?
|
||||
public var groupName: String?
|
||||
public var fieldKey: String?
|
||||
public var fieldValue: String?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case state
|
||||
case enabled
|
||||
case fieldKey
|
||||
case fieldValue
|
||||
case groupName
|
||||
}
|
||||
|
||||
public init(_ state: Bool) {
|
||||
self.state = state
|
||||
}
|
||||
|
||||
public func formFieldValue() -> AnyHashable? {
|
||||
return 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
|
||||
}
|
||||
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
|
||||
self.enabled = enabled
|
||||
}
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||
groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName)
|
||||
fieldValue = try typeContainer.decodeIfPresent(String.self, forKey: .fieldValue)
|
||||
}
|
||||
|
||||
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.encode(state, forKey: .state)
|
||||
try container.encode(enabled, forKey: .enabled)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||
try container.encodeIfPresent(fieldValue, forKey: .fieldValue)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
//--------------------------------------------------
|
||||
@ -100,8 +100,9 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
knobView.backgroundColor = isOn ? knobTintColor?.on : knobTintColor?.off
|
||||
self.constrainKnob()
|
||||
}
|
||||
|
||||
FormValidator.enableByValidationWith(delegate: delegateObject?.formValidationProtocol)
|
||||
|
||||
(model as? ToggleModel)?.state = isOn
|
||||
FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||
accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff")
|
||||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
@ -339,82 +340,61 @@ public typealias ActionBlockConfirmation = () -> (Bool)
|
||||
return
|
||||
}
|
||||
|
||||
self.model = model
|
||||
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()
|
||||
|
||||
@ -8,23 +8,29 @@
|
||||
|
||||
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
|
||||
public var action: ActionModelProtocol?
|
||||
public var alternateAction: ActionModelProtocol?
|
||||
public var required: Bool?
|
||||
public var fieldKey: String?
|
||||
public var groupName: String? = FormValidator.defaultGroupName
|
||||
public var baseValue: AnyHashable?
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case state
|
||||
case action
|
||||
case backgroundColor
|
||||
case required
|
||||
case fieldKey
|
||||
case alternateAction
|
||||
case groupName
|
||||
}
|
||||
|
||||
public func formFieldValue() -> AnyHashable? {
|
||||
return state
|
||||
}
|
||||
|
||||
public init(_ state: Bool) {
|
||||
@ -39,8 +45,10 @@ public class ToggleModel: MoleculeModelProtocol {
|
||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||
alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction)
|
||||
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 {
|
||||
@ -49,8 +57,8 @@ public class ToggleModel: MoleculeModelProtocol {
|
||||
try container.encodeModelIfPresent(action, forKey: .action)
|
||||
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.encode(state, forKey: .state)
|
||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ import UIKit
|
||||
}
|
||||
|
||||
// MARK: - MFViewProtocol
|
||||
public func updateView(_ size: CGFloat) {
|
||||
open func updateView(_ size: CGFloat) {
|
||||
containerHelper.updateViewMargins(self, model: listItemModel, size: size)
|
||||
|
||||
if accessoryView != nil {
|
||||
@ -151,7 +151,7 @@ import UIKit
|
||||
}
|
||||
|
||||
//TODO: ModelProtocol, Change to model
|
||||
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
guard let model = model as? ListItemModelProtocol else { return }
|
||||
|
||||
self.listItemModel = model
|
||||
@ -176,6 +176,9 @@ import UIKit
|
||||
let backgroundColor = moleculeModel.backgroundColor {
|
||||
self.backgroundColor = backgroundColor.uiColor
|
||||
}
|
||||
|
||||
// align if needed.
|
||||
containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol)
|
||||
}
|
||||
|
||||
open func reset() {
|
||||
@ -183,11 +186,11 @@ import UIKit
|
||||
backgroundColor = .white
|
||||
}
|
||||
|
||||
public class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
open class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
return model.moleculeName
|
||||
}
|
||||
|
||||
public class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
open class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
22
MVMCoreUI/BaseControllers/MFViewController+Form.swift
Normal file
22
MVMCoreUI/BaseControllers/MFViewController+Form.swift
Normal file
@ -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)
|
||||
}
|
||||
}
|
||||
@ -31,9 +31,10 @@ extension MFViewController: MoleculeDelegateProtocol {
|
||||
return nil
|
||||
}
|
||||
|
||||
@objc public func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) { }
|
||||
// These are required because swift will call the extension function otherwise.
|
||||
@objc public func moleculeLayoutUpdated(_ molecule: UIView & MVMCoreUIMoleculeViewProtocol) {}
|
||||
|
||||
@objc public func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { }
|
||||
|
||||
@objc public func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) { }
|
||||
@objc public func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {}
|
||||
@objc public func addMolecules(_ molecules: [[AnyHashable : Any]], indexPath: IndexPath, animation: UITableView.RowAnimation) {}
|
||||
@objc public func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {}
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
#import <MVMCoreUI/MVMCoreUI-Swift.h>
|
||||
@import MVMAnimationFramework;
|
||||
|
||||
@interface MFViewController() <FormValidationProtocol>
|
||||
@interface MFViewController()
|
||||
|
||||
// A flag for if this view controller is observing for cache updates or not.
|
||||
@property (nonatomic) BOOL observingForResponseJSONUpdates;
|
||||
@ -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) {
|
||||
@ -477,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()) {
|
||||
@ -487,12 +478,13 @@
|
||||
if (!self.disableAnimations) {
|
||||
[self setupIntroAnimations];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (void)newDataBuildAndUpdate {
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
[self newDataBuildScreen];
|
||||
[self.formValidator enableByValidation];
|
||||
[self startValidation];
|
||||
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]];
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ open class ThreeLayerTableViewController: MFProgrammaticTableViewController {
|
||||
private var footerView: UIView?
|
||||
private var safeAreaView: UIView?
|
||||
var useMargins: Bool = true
|
||||
var bottomViewOutsideOfScrollArea: Bool = false
|
||||
public var bottomViewOutsideOfScrollArea: Bool = false
|
||||
private var topViewBottomConstraint: NSLayoutConstraint?
|
||||
private var bottomViewTopConstraint: NSLayoutConstraint?
|
||||
|
||||
|
||||
23
MVMCoreUI/Categories/UIStackView+Extension.swift
Normal file
23
MVMCoreUI/Categories/UIStackView+Extension.swift
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// UIStackView+Extension.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 3/16/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension UIStackView: MVMCoreUIMoleculeViewProtocol {
|
||||
public func updateView(_ size: CGFloat) {
|
||||
for view in arrangedSubviews {
|
||||
(view as? MVMCoreViewProtocol)?.updateView(size)
|
||||
}
|
||||
}
|
||||
|
||||
public func reset() {
|
||||
for view in arrangedSubviews {
|
||||
(view as? MVMCoreUIMoleculeViewProtocol)?.reset?()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -23,15 +23,15 @@ open class Container: View, ContainerProtocol {
|
||||
}
|
||||
|
||||
// MARK:- ContainerProtocol
|
||||
public func alignHorizontal(_ alignment: UIStackView.Alignment) {
|
||||
open func alignHorizontal(_ alignment: UIStackView.Alignment) {
|
||||
containerHelper.alignHorizontal(alignment)
|
||||
}
|
||||
|
||||
public func alignVertical(_ alignment: UIStackView.Alignment) {
|
||||
open func alignVertical(_ alignment: UIStackView.Alignment) {
|
||||
containerHelper.alignVertical(alignment)
|
||||
}
|
||||
|
||||
public func constrainView(_ view: UIView) {
|
||||
open func constrainView(_ view: UIView) {
|
||||
containerHelper.constrainView(view)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ContainerHelper: NSObject {
|
||||
open class ContainerHelper: NSObject {
|
||||
var leftConstraint: NSLayoutConstraint?
|
||||
var topConstraint: NSLayoutConstraint?
|
||||
var bottomConstraint: NSLayoutConstraint?
|
||||
@ -28,7 +28,7 @@ public class ContainerHelper: NSObject {
|
||||
var bottomLowConstraint: NSLayoutConstraint?
|
||||
var rightLowConstraint: NSLayoutConstraint?
|
||||
|
||||
func constrainView(_ view: UIView) {
|
||||
open func constrainView(_ view: UIView) {
|
||||
guard let margins = view.superview?.layoutMarginsGuide else { return }
|
||||
leftConstraint = view.leftAnchor.constraint(equalTo: margins.leftAnchor)
|
||||
leftConstraint?.isActive = true
|
||||
@ -69,7 +69,7 @@ public class ContainerHelper: NSObject {
|
||||
setAccessibility(view)
|
||||
}
|
||||
|
||||
func setAccessibility(_ view: UIView) {
|
||||
open func setAccessibility(_ view: UIView) {
|
||||
guard let superView = view.superview else { return }
|
||||
superView.isAccessibilityElement = false
|
||||
if let elements = view.accessibilityElements {
|
||||
@ -79,7 +79,7 @@ public class ContainerHelper: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
func alignHorizontal(_ alignment: UIStackView.Alignment) {
|
||||
open func alignHorizontal(_ alignment: UIStackView.Alignment) {
|
||||
switch alignment {
|
||||
case .center:
|
||||
alignCenterHorizontalConstraint?.isActive = true
|
||||
@ -109,7 +109,7 @@ public class ContainerHelper: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
func alignVertical(_ alignment: UIStackView.Alignment) {
|
||||
open func alignVertical(_ alignment: UIStackView.Alignment) {
|
||||
switch alignment {
|
||||
case .center:
|
||||
alignCenterVerticalConstraint?.isActive = true
|
||||
@ -139,7 +139,7 @@ public class ContainerHelper: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
static func getAlignment(for string: String) -> UIStackView.Alignment? {
|
||||
public static func getAlignment(for string: String) -> UIStackView.Alignment? {
|
||||
switch string {
|
||||
case "leading":
|
||||
return .leading
|
||||
@ -154,7 +154,7 @@ public class ContainerHelper: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
static func getAlignmentString(for alignment: UIStackView.Alignment?) -> String? {
|
||||
public static func getAlignmentString(for alignment: UIStackView.Alignment?) -> String? {
|
||||
switch alignment {
|
||||
case .leading:
|
||||
return "leading"
|
||||
@ -169,11 +169,11 @@ public class ContainerHelper: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
func updateViewMargins(_ view: UIView, model: ContainerModelProtocol?, size: CGFloat) {
|
||||
open func updateViewMargins(_ view: UIView, model: ContainerModelProtocol?, size: CGFloat) {
|
||||
MFStyler.setMarginsFor(view, size: size, defaultHorizontal: model?.useHorizontalMargins ?? false, top: (model?.useVerticalMargins ?? false) ? (model?.topMarginPadding ?? 0) : 0, bottom: (model?.useVerticalMargins ?? false) ? (model?.bottomMarginPadding ?? 0) : 0)
|
||||
}
|
||||
|
||||
func set(with model: ContainerModelProtocol, for contained: MVMCoreUIViewConstrainingProtocol?) {
|
||||
open func set(with model: ContainerModelProtocol, for contained: MVMCoreUIViewConstrainingProtocol?) {
|
||||
if let horizontalAlignment = model.horizontalAlignment ?? contained?.horizontalAlignment?() {
|
||||
alignHorizontal(horizontalAlignment)
|
||||
}
|
||||
@ -182,7 +182,7 @@ public class ContainerHelper: NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
func set(with JSON: [AnyHashable: Any]?, for contained: UIView) {
|
||||
open func set(with JSON: [AnyHashable: Any]?, for contained: UIView) {
|
||||
if let horizontalAlignmentString = JSON?.optionalStringForKey("horizontalAlignment"), let alignment = ContainerHelper.getAlignment(for: horizontalAlignmentString) ?? (contained as? MVMCoreUIViewConstrainingProtocol)?.horizontalAlignment?() {
|
||||
alignHorizontal(alignment)
|
||||
} else if let alignment = (contained as? MVMCoreUIViewConstrainingProtocol)?.horizontalAlignment?() {
|
||||
|
||||
14
MVMCoreUI/FormUIHelpers/FormActionFieldProtocol.swift
Normal file
14
MVMCoreUI/FormUIHelpers/FormActionFieldProtocol.swift
Normal file
@ -0,0 +1,14 @@
|
||||
//
|
||||
// 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 {
|
||||
func updateEnable(_ enabled: Bool)
|
||||
var updateUI: (() -> Void)? { get set }
|
||||
}
|
||||
22
MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift
Normal file
22
MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift
Normal file
@ -0,0 +1,22 @@
|
||||
//
|
||||
// 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 }
|
||||
var baseValue: AnyHashable? { get set }
|
||||
func formFieldValue() -> AnyHashable?
|
||||
}
|
||||
|
||||
extension FormFieldProtocol {
|
||||
var baseValue: AnyHashable? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
17
MVMCoreUI/FormUIHelpers/FormHolderProtocol.swift
Normal file
17
MVMCoreUI/FormUIHelpers/FormHolderProtocol.swift
Normal file
@ -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()
|
||||
}
|
||||
19
MVMCoreUI/FormUIHelpers/FormItemProtocol.swift
Normal file
19
MVMCoreUI/FormUIHelpers/FormItemProtocol.swift
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// FormItemProtocol.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 2/25/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public protocol FormItemProtocol {
|
||||
static var defaultGroupName: String? { get }
|
||||
var groupName: String? { get set }
|
||||
}
|
||||
extension FormItemProtocol{
|
||||
public static var defaultGroupName: String? {
|
||||
return "default"
|
||||
}
|
||||
}
|
||||
15
MVMCoreUI/FormUIHelpers/FormProtocol.swift
Normal file
15
MVMCoreUI/FormUIHelpers/FormProtocol.swift
Normal file
@ -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 }
|
||||
}
|
||||
@ -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]?
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
//
|
||||
// MVMCoreUIFormValidator+FormParams.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 3/21/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -1,70 +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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -11,75 +11,107 @@ import MVMCore
|
||||
|
||||
@objcMembers public class FormValidator: NSObject {
|
||||
|
||||
static var defaultGroupName: String = "default"
|
||||
var extraValidationBlock: (() -> Bool)?
|
||||
var dummyGroupName = "dummyGroupName"
|
||||
weak var delegate: FormValidationProtocol?
|
||||
var fieldMolecules: [FormValidationFormFieldProtocol] = []
|
||||
var enableDisableMolecules: [FormValidationEnableDisableProtocol] = []
|
||||
var formRules: [FormGroupRule]?
|
||||
var delegate: FormHolderProtocol?
|
||||
var fieldMolecules: [String: 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 var molecule = molecule as? FormFieldProtocol,
|
||||
let fieldKey = molecule.fieldKey {
|
||||
if molecule.baseValue == nil {
|
||||
molecule.baseValue = molecule.formFieldValue()
|
||||
}
|
||||
fieldMolecules[fieldKey] = 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() {
|
||||
guard let formRules = formRules else {
|
||||
return
|
||||
}
|
||||
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(fieldMolecules)
|
||||
if !valid {
|
||||
break
|
||||
}
|
||||
}
|
||||
let enableField = valid && (extraValidationBlock?() ?? true)
|
||||
enableDisableMolecules.enableField?(enableField)
|
||||
actionModel.updateEnable(valid)
|
||||
}
|
||||
|
||||
public func formField(for fieldKey: String) -> FormFieldProtocol? {
|
||||
return fieldMolecules[fieldKey]
|
||||
}
|
||||
}
|
||||
|
||||
// mark Form params
|
||||
@objc public extension FormValidator {
|
||||
@objc func addFormParams(requestParameters: MVMCoreRequestParameters) {
|
||||
let formButton = getFormButton(forPageType: requestParameters.pageType)
|
||||
let groupName = formButton?.groupName ?? FormValidator.defaultGroupName
|
||||
let formParams = self.getFormParams(forGroup: groupName)
|
||||
requestParameters.add(formParams)
|
||||
}
|
||||
|
||||
@objc func getFormParams( forGroup groupName: String) -> [String: Any] {
|
||||
var extraParam: [String: Any] = [:]
|
||||
MVMCoreDispatchUtility.performSyncBlock(onMainThread: {
|
||||
for (fieldKey, molecule) in self.fieldMolecules {
|
||||
if let formFieldValue = molecule.formFieldValue(),
|
||||
groupName == molecule.groupName {
|
||||
extraParam[fieldKey] = formFieldValue
|
||||
}
|
||||
}
|
||||
})
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
38
MVMCoreUI/FormUIHelpers/Rules/Rules/FormGroupRule.swift
Normal file
38
MVMCoreUI/FormUIHelpers/Rules/Rules/FormGroupRule.swift
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// FormRule.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Suresh, Kamlesh on 2/24/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
open class FormGroupRule: Codable {
|
||||
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.decodeModels(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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 RuleAllValueChangedModel: RulesProtocol {
|
||||
|
||||
public static var identifier: String = "allValueChanged"
|
||||
public var type: String = RuleAllValueChangedModel.identifier
|
||||
public var fields: [String]
|
||||
|
||||
public func isValid(_ formField: FormFieldProtocol) -> Bool {
|
||||
return formField.baseValue != formField.formFieldValue()
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
//
|
||||
// RuleAnyRequiredModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kevin Christiano on 3/13/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
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 }
|
||||
|
||||
if let valueString = value as? String {
|
||||
return valueString.count > 0
|
||||
|
||||
} else if let valueBool = value as? Bool {
|
||||
return valueBool
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
public func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
|
||||
|
||||
for formKey in fields {
|
||||
guard let formField = fieldMolecules[formKey] else { continue }
|
||||
|
||||
if isValid(formField) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -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 type: String = RuleAnyValueChangedModel.identifier
|
||||
public var fields: [String]
|
||||
|
||||
public func isValid(_ formField: FormFieldProtocol) -> Bool {
|
||||
return formField.baseValue != formField.formFieldValue()
|
||||
}
|
||||
|
||||
public func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
|
||||
for formKey in fields {
|
||||
guard let formField = fieldMolecules[formKey] else {
|
||||
continue
|
||||
}
|
||||
if isValid(formField) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
40
MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift
Normal file
40
MVMCoreUI/FormUIHelpers/Rules/Rules/RuleEqualsModel.swift
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// 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 type: String = RuleEqualsModel.identifier
|
||||
public var fields: [String]
|
||||
|
||||
public func isValid(_ formField: FormFieldProtocol) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
public func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
|
||||
var valid = true
|
||||
var compareValue: AnyHashable?
|
||||
for formKey in fields {
|
||||
guard let formField = fieldMolecules[formKey] else {
|
||||
continue
|
||||
}
|
||||
|
||||
if compareValue == nil {
|
||||
compareValue = formField.formFieldValue()
|
||||
continue
|
||||
}
|
||||
if compareValue != formField.formFieldValue(){
|
||||
valid = false
|
||||
break
|
||||
}
|
||||
}
|
||||
return valid
|
||||
}
|
||||
}
|
||||
23
MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRegexModel.swift
Normal file
23
MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRegexModel.swift
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// 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 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
|
||||
}
|
||||
}
|
||||
30
MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRequiredModel.swift
Normal file
30
MVMCoreUI/FormUIHelpers/Rules/Rules/RuleRequiredModel.swift
Normal file
@ -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 type: 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 > 0
|
||||
} else if let valueBool = value as? Bool {
|
||||
valid = valueBool
|
||||
}
|
||||
return valid
|
||||
}
|
||||
}
|
||||
56
MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift
Normal file
56
MVMCoreUI/FormUIHelpers/Rules/Rules/RulesProtocol.swift
Normal file
@ -0,0 +1,56 @@
|
||||
//
|
||||
// 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 type: String { get set }
|
||||
var fields: [String] { get set }
|
||||
func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> 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 "type"
|
||||
}
|
||||
|
||||
static var categoryName: String {
|
||||
return "\(RulesProtocol.self)"
|
||||
}
|
||||
|
||||
func isValid(_ fieldMolecules: [String: FormFieldProtocol]) -> Bool {
|
||||
var valid = true
|
||||
|
||||
for formKey in fields {
|
||||
guard let formField = fieldMolecules[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 }
|
||||
|
||||
formFieldValid.setValidity(isValid)
|
||||
}
|
||||
}
|
||||
15
MVMCoreUI/FormUIHelpers/ValidProtocol.swift
Normal file
15
MVMCoreUI/FormUIHelpers/ValidProtocol.swift
Normal file
@ -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 }
|
||||
}
|
||||
@ -18,7 +18,7 @@
|
||||
@import MVMCore.NSDictionary_MFConvenience;
|
||||
@import MVMCore.MVMCoreJSONConstants;
|
||||
|
||||
@interface MFTextField() <FormValidationFormFieldProtocol>
|
||||
@interface MFTextField()
|
||||
|
||||
@property (strong, nonatomic) UIColor *customPlaceHolderColor;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *separatorHeightConstraint;
|
||||
@ -560,11 +560,7 @@
|
||||
- (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 setWithMap:json];
|
||||
self.uiTextFieldDelegate = delegateObject.uiTextFieldDelegate;
|
||||
[MVMCoreUICommonViewsUtility addDismissToolbar:self.textField delegate:self.uiTextFieldDelegate];
|
||||
}
|
||||
@ -574,24 +570,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
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
static const CGFloat FaultTolerance = 20.f;
|
||||
static const CGFloat CheckBoxHeightWidth = 18.0;
|
||||
|
||||
@interface MVMCoreUICheckBox () <FormValidationFormFieldProtocol, MVMCoreUIMoleculeViewProtocol>
|
||||
@interface MVMCoreUICheckBox () <MVMCoreUIMoleculeViewProtocol>
|
||||
|
||||
@property (nonatomic, readwrite) BOOL isSelected;
|
||||
@property (weak, nonatomic) UIView *checkedSquare;
|
||||
@ -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];
|
||||
@ -109,23 +107,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 {
|
||||
@ -350,7 +331,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 {
|
||||
|
||||
@ -311,7 +311,7 @@ static CGFloat const IndicatorRectangleHeight = 4;
|
||||
self.currentPage = page;
|
||||
}
|
||||
|
||||
#pragma mark - MoleculeViewProtocol
|
||||
#pragma mark - MVMCoreUIMoleculeViewProtocol
|
||||
|
||||
- (void)setWithJSON:(NSDictionary *)json delegateObject:(MVMCoreUIDelegateObject *)delegateObject additionalData:(NSDictionary *)additionalData {
|
||||
NSString *colorString = [json string:KeyBackgroundColor];
|
||||
|
||||
@ -22,7 +22,7 @@ const CGFloat SwitchKnobWidth = 20;
|
||||
const CGFloat SwitchKnobHeight = 20;
|
||||
const CGFloat SwitchShakeIntensity = 2;
|
||||
|
||||
@interface MVMCoreUISwitch () <FormValidationFormFieldProtocol, MVMCoreUIViewConstrainingProtocol>
|
||||
@interface MVMCoreUISwitch () <MVMCoreUIViewConstrainingProtocol>
|
||||
|
||||
@property (weak, nonatomic) UIView *baseView;
|
||||
@property (weak, nonatomic) UIView *knobView;
|
||||
@ -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];
|
||||
@ -339,12 +337,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 {
|
||||
@ -427,22 +424,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
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
@import MVMCore.MVMCoreGetterUtility;
|
||||
@import MVMCore.NSDictionary_MFConvenience;
|
||||
|
||||
@interface PrimaryButton() <FormValidationEnableDisableProtocol>
|
||||
@interface PrimaryButton()
|
||||
|
||||
@property (nonatomic) BOOL smallButton;
|
||||
@property (assign, nonatomic) BOOL tinyButton;
|
||||
@ -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"];
|
||||
@ -781,22 +780,4 @@
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - FormValidationEnableDisableProtocol
|
||||
|
||||
- (BOOL)isValidationRequired {
|
||||
return self.validationRequired;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)requiredGroups {
|
||||
return self.requiredGroupsList;
|
||||
}
|
||||
|
||||
- (void)enableField:(BOOL)enable {
|
||||
if (!self.validationRequired) {
|
||||
self.enabled = YES;
|
||||
} else {
|
||||
self.enabled = enable;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -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 }
|
||||
}
|
||||
@ -9,7 +9,7 @@
|
||||
import Foundation
|
||||
|
||||
|
||||
public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol {
|
||||
public protocol TemplateModelProtocol: PageModelProtocol, ModelProtocol, FormProtocol {
|
||||
var template: String { get }
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
//
|
||||
// ListOneColumnFullWidthTextBodyText.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kruthika KP on 05/03/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class ListOneColumnFullWidthTextBodyText: TableViewCell {
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//-----------------------------------------------------
|
||||
public var headlineBody = HeadlineBody(frame: .zero)
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - View Lifecycle
|
||||
//-----------------------------------------------------
|
||||
override open func setupView() {
|
||||
super.setupView()
|
||||
addMolecule(headlineBody)
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?){
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListOneColumnFullWidthTextBodyTextModel else { return }
|
||||
headlineBody.set(with: model.headlineBody, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return 90
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
//
|
||||
// ListOneColumnFullWidthTextBodyTextModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kruthika KP on 05/03/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ListOneColumnFullWidthTextBodyTextModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "list1CFWBdy"
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
|
||||
public init(headlineBody: HeadlineBodyModel) {
|
||||
self.headlineBody = headlineBody
|
||||
super.init()
|
||||
}
|
||||
|
||||
// Defaults to set
|
||||
override public func setDefaults() {
|
||||
super.setDefaults()
|
||||
headlineBody.style = "item"
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case headlineBody
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
headlineBody = try typeContainer.decode(HeadlineBodyModel.self, forKey: .headlineBody)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(headlineBody, forKey: .headlineBody)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
//
|
||||
// ListTwoColumnCompareChanges.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 24/02/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class ListTwoColumnCompareChanges: TableViewCell {
|
||||
|
||||
//-------------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//-------------------------------------------------------
|
||||
let leftHeadline1 = Label.commonLabelB1(true)
|
||||
let leftHeadline2 = Label.commonLabelB1(true)
|
||||
let leftHeadline3 = Label.commonLabelB1(true)
|
||||
let leftBody = Label.commonLabelB2(true)
|
||||
let leftLink = Link()
|
||||
let rightHeadline1 = Label.commonLabelB1(true)
|
||||
let rightHeadline2 = Label.commonLabelB1(true)
|
||||
let rightHeadline3 = Label.commonLabelB1(true)
|
||||
let rightBody = Label.commonLabelB2(true)
|
||||
let rightLink = Link()
|
||||
let containingStack: Stack<StackModel>
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//------------------------------------------------------
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
let stackHeadline1 = Stack<StackModel>.createStack(with: [(view: leftHeadline1, model: StackItemModel(percent: 50, verticalAlignment: .leading)),
|
||||
(view: rightHeadline1, model: StackItemModel(percent: 50, verticalAlignment: .leading))],
|
||||
axis: .horizontal)
|
||||
let stackHeadline2 = Stack<StackModel>.createStack(with: [(view: leftHeadline2, model: StackItemModel(percent: 50, verticalAlignment: .leading)),
|
||||
(view: rightHeadline2, model: StackItemModel(percent: 50, verticalAlignment: .leading))],
|
||||
axis: .horizontal)
|
||||
let stackHeadline3 = Stack<StackModel>.createStack(with: [(view: leftHeadline3, model: StackItemModel(percent: 50, verticalAlignment: .leading)),
|
||||
(view: rightHeadline3, model: StackItemModel(percent: 50, verticalAlignment: .leading))],
|
||||
axis: .horizontal)
|
||||
let stackBody = Stack<StackModel>.createStack(with: [(view: leftBody, model: StackItemModel(percent: 50, verticalAlignment: .leading)),
|
||||
(view: rightBody, model: StackItemModel(percent: 50, verticalAlignment: .leading))],
|
||||
axis: .horizontal)
|
||||
let stackLink = Stack<StackModel>.createStack(with: [(view: leftLink, model: StackItemModel(percent: 50, verticalAlignment: .leading)),
|
||||
(view: rightLink, model: StackItemModel(percent: 50, verticalAlignment: .leading))],
|
||||
axis: .horizontal)
|
||||
containingStack = Stack<StackModel>.createStack(with: [stackHeadline1,
|
||||
stackHeadline2,
|
||||
stackHeadline3,
|
||||
stackBody,
|
||||
stackLink],
|
||||
spacing: 0)
|
||||
containingStack.stackModel?.molecules[1].spacing = 5
|
||||
containingStack.stackModel?.molecules[2].spacing = 5
|
||||
containingStack.stackModel?.molecules[4].spacing = 5
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//------------------------------------------------------
|
||||
let stackSpacing: CGFloat = 5.0
|
||||
|
||||
//-------------------------------------------------------
|
||||
// MARK: - View Lifecycle
|
||||
//-------------------------------------------------------
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
addMolecule(containingStack)
|
||||
for molecule in containingStack.stackItems {
|
||||
((molecule as? StackItem)?.view as? Stack<StackModel>)?.restack()
|
||||
}
|
||||
containingStack.restack()
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Molecule
|
||||
//------------------------------------------------------
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListTwoColumnCompareChangesModel else { return }
|
||||
leftHeadline1.set(with: model.leftHeadline1, delegateObject, additionalData)
|
||||
leftHeadline2.set(with: model.leftHeadline2, delegateObject, additionalData)
|
||||
leftHeadline3.set(with: model.leftHeadline3, delegateObject, additionalData)
|
||||
leftBody.set(with: model.leftBody, delegateObject, additionalData)
|
||||
leftLink.set(with: model.leftLink, delegateObject, additionalData)
|
||||
rightHeadline1.set(with: model.rightHeadline1, delegateObject, additionalData)
|
||||
rightHeadline2.set(with: model.rightHeadline2, delegateObject, additionalData)
|
||||
rightHeadline3.set(with: model.rightHeadline3, delegateObject, additionalData)
|
||||
rightBody.set(with: model.rightBody, delegateObject, additionalData)
|
||||
rightLink.set(with: model.rightLink, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
leftHeadline1.styleB1(true)
|
||||
leftHeadline2.styleB1(true)
|
||||
leftHeadline3.styleB1(true)
|
||||
leftBody.styleB2(true)
|
||||
rightHeadline1.styleB1(true)
|
||||
rightHeadline2.styleB1(true)
|
||||
rightHeadline3.styleB1(true)
|
||||
rightBody.styleB2(true)
|
||||
}
|
||||
|
||||
public override class func estimatedHeight(with molecule: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 121
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,83 @@
|
||||
//
|
||||
// ListTwoColumnCompareChangesModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 24/02/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ListTwoColumnCompareChangesModel: ListItemModel, MoleculeModelProtocol {
|
||||
|
||||
public static var identifier: String = "list2CCmpr1"
|
||||
public var leftHeadline1: LabelModel
|
||||
public var leftHeadline2: LabelModel
|
||||
public var leftHeadline3: LabelModel
|
||||
public var leftBody: LabelModel
|
||||
public var leftLink: LinkModel
|
||||
public var rightHeadline1: LabelModel
|
||||
public var rightHeadline2: LabelModel
|
||||
public var rightHeadline3: LabelModel
|
||||
public var rightBody: LabelModel
|
||||
public var rightLink: LinkModel
|
||||
|
||||
public init(leftHeadline1: LabelModel, leftHeadline2: LabelModel, leftHeadline3: LabelModel, leftBody: LabelModel, leftLink: LinkModel, rightHeadline1: LabelModel, rightHeadline2: LabelModel, rightHeadline3: LabelModel, rightBody: LabelModel, rightLink: LinkModel) {
|
||||
self.leftHeadline1 = leftHeadline1
|
||||
self.leftHeadline2 = leftHeadline2
|
||||
self.leftHeadline3 = leftHeadline3
|
||||
self.leftBody = leftBody
|
||||
self.leftLink = leftLink
|
||||
self.rightHeadline1 = rightHeadline1
|
||||
self.rightHeadline2 = rightHeadline2
|
||||
self.rightHeadline3 = rightHeadline3
|
||||
self.rightBody = rightBody
|
||||
self.rightLink = rightLink
|
||||
super.init()
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case leftHeadline1
|
||||
case leftHeadline2
|
||||
case leftHeadline3
|
||||
case leftBody
|
||||
case leftLink
|
||||
case rightHeadline1
|
||||
case rightHeadline2
|
||||
case rightHeadline3
|
||||
case rightBody
|
||||
case rightLink
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
leftHeadline1 = try typeContainer.decode(LabelModel.self, forKey: .leftHeadline1)
|
||||
leftHeadline2 = try typeContainer.decode(LabelModel.self, forKey: .leftHeadline2)
|
||||
leftHeadline3 = try typeContainer.decode(LabelModel.self, forKey: .leftHeadline3)
|
||||
leftBody = try typeContainer.decode(LabelModel.self, forKey: .leftBody)
|
||||
leftLink = try typeContainer.decode(LinkModel.self, forKey: .leftLink)
|
||||
rightHeadline1 = try typeContainer.decode(LabelModel.self, forKey: .rightHeadline1)
|
||||
rightHeadline2 = try typeContainer.decode(LabelModel.self, forKey: .rightHeadline2)
|
||||
rightHeadline3 = try typeContainer.decode(LabelModel.self, forKey: .rightHeadline3)
|
||||
rightBody = try typeContainer.decode(LabelModel.self, forKey: .rightBody)
|
||||
rightLink = try typeContainer.decode(LinkModel.self, forKey: .rightLink)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(leftHeadline1, forKey: .leftHeadline1)
|
||||
try container.encode(leftHeadline2, forKey: .leftHeadline2)
|
||||
try container.encode(leftHeadline3, forKey: .leftHeadline3)
|
||||
try container.encode(leftBody, forKey: .leftBody)
|
||||
try container.encode(leftLink, forKey: .leftLink)
|
||||
try container.encode(rightHeadline1, forKey: .rightHeadline1)
|
||||
try container.encode(rightHeadline2, forKey: .rightHeadline2)
|
||||
try container.encode(rightHeadline3, forKey: .rightHeadline3)
|
||||
try container.encode(rightBody, forKey: .rightBody)
|
||||
try container.encode(rightLink, forKey: .rightLink)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
//
|
||||
// ListTwoColumnPriceDescription.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kruthika KP on 24/02/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers open class ListTwoColumnPriceDescription: TableViewCell {
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - Outlets
|
||||
//-------------------------------------------------------
|
||||
public let leftHeadline = Label.commonLabelB1(true)
|
||||
public let leftBody = Label.commonLabelB2(true)
|
||||
public let rightLabel = Label.commonLabelB2(true)
|
||||
public let rightSubLabel = Label.commonLabelB2(true)
|
||||
|
||||
public let view = MVMCoreUICommonViewsUtility.commonView()
|
||||
public let leftVerticalStack: UIStackView
|
||||
public let rightVerticalStack: UIStackView
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - Initializers
|
||||
//------------------------------------------------------
|
||||
public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
leftVerticalStack = UIStackView(arrangedSubviews: [leftHeadline, leftBody])
|
||||
leftVerticalStack.axis = .vertical
|
||||
leftVerticalStack.alignment = .leading
|
||||
rightVerticalStack = UIStackView(arrangedSubviews: [rightLabel, rightSubLabel])
|
||||
rightVerticalStack.axis = .vertical
|
||||
rightVerticalStack.alignment = .trailing
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
public required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
//-----------------------------------------------------
|
||||
// MARK: - View Lifecycle
|
||||
//-------------------------------------------------------
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
leftVerticalStack.updateView(size)
|
||||
rightVerticalStack.updateView(size)
|
||||
}
|
||||
|
||||
override open func setupView() {
|
||||
super.setupView()
|
||||
contentView.addSubview(view)
|
||||
containerHelper.constrainView(view)
|
||||
|
||||
leftVerticalStack.translatesAutoresizingMaskIntoConstraints = false
|
||||
rightVerticalStack.translatesAutoresizingMaskIntoConstraints = false
|
||||
rightLabel.setContentHuggingPriority(.defaultHigh, for: .vertical)
|
||||
rightSubLabel.setContentHuggingPriority(.defaultHigh, for: .vertical)
|
||||
view.addSubview(leftVerticalStack)
|
||||
view.addSubview(rightVerticalStack)
|
||||
NSLayoutConstraint.pinViews(leftView: leftVerticalStack, rightView: rightVerticalStack, alignTop: true)
|
||||
|
||||
leftHeadline.numberOfLines = 1
|
||||
rightLabel.numberOfLines = 1
|
||||
rightSubLabel.numberOfLines = 1
|
||||
}
|
||||
//----------------------------------------------------
|
||||
// MARK: - Molecule
|
||||
//------------------------------------------------------
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListTwoColumnPriceDescriptionModel else { return }
|
||||
leftHeadline.set(with: model.leftHeadline, delegateObject, additionalData)
|
||||
leftBody.set(with: model.leftBody, delegateObject, additionalData)
|
||||
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
|
||||
rightSubLabel.set(with: model.rightSubLabel, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with molecule: MoleculeModelProtocol?, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
return 80
|
||||
}
|
||||
|
||||
override open func reset() {
|
||||
super.reset()
|
||||
leftVerticalStack.reset()
|
||||
rightVerticalStack.reset()
|
||||
leftHeadline.styleB1(true)
|
||||
leftBody.styleB2(true)
|
||||
rightLabel.styleB2(true)
|
||||
rightSubLabel.styleB2(true)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
//
|
||||
// ListTwoColumnPriceDescriptionModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Kruthika KP on 26/02/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ListTwoColumnPriceDescriptionModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "list2CTxtPrc1"
|
||||
public var leftHeadline: LabelModel
|
||||
public var leftBody: LabelModel
|
||||
public var rightLabel: LabelModel
|
||||
public var rightSubLabel: LabelModel
|
||||
|
||||
override public func setDefaults() {
|
||||
super.setDefaults()
|
||||
rightLabel.hero = 0
|
||||
if rightSubLabel.textColor == nil {
|
||||
rightSubLabel.textColor = Color(uiColor: .mvmCoolGray6)
|
||||
}
|
||||
if rightSubLabel.attributes == nil {
|
||||
rightSubLabel.attributes = [LabelAttributeStrikeThroughModel(0, rightSubLabel.text.count)]
|
||||
}
|
||||
}
|
||||
|
||||
public init(leftHeadline: LabelModel,leftBody: LabelModel, rightLabel: LabelModel, rightSubLabel: LabelModel) {
|
||||
self.leftHeadline = leftHeadline
|
||||
self.leftBody = leftBody
|
||||
self.rightLabel = rightLabel
|
||||
self.rightSubLabel = rightSubLabel
|
||||
super.init()
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case leftHeadline
|
||||
case leftBody
|
||||
case rightLabel
|
||||
case rightSubLabel
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
leftHeadline = try typeContainer.decode(LabelModel.self, forKey: .leftHeadline)
|
||||
leftBody = try typeContainer.decode(LabelModel.self, forKey: .leftBody)
|
||||
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
|
||||
rightSubLabel = try typeContainer.decode(LabelModel.self, forKey: .rightSubLabel)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(leftHeadline, forKey: .leftHeadline)
|
||||
try container.encode(leftBody, forKey: .leftBody)
|
||||
try container.encode(rightLabel, forKey: .rightLabel)
|
||||
try container.encode(rightSubLabel, forKey: .rightSubLabel)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
//
|
||||
// ListTwoColumnPriceDetails.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 19/02/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class ListTwoColumnPriceDetails: TableViewCell {
|
||||
|
||||
let leftLabel = Label.commonLabelB2(true)
|
||||
let rightLabel = Label.commonLabelB2(true)
|
||||
let view = MVMCoreUICommonViewsUtility.commonView()
|
||||
|
||||
// MARK: - MFViewProtocol
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
view.addSubview(leftLabel)
|
||||
view.addSubview(rightLabel)
|
||||
NSLayoutConstraint.pinViews(leftView: leftLabel, rightView: rightLabel, alignTop: true)
|
||||
contentView.addSubview(view)
|
||||
containerHelper.constrainView(view)
|
||||
rightLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 900), for: .horizontal)
|
||||
rightLabel.setContentHuggingPriority(.defaultHigh, for: .vertical)
|
||||
}
|
||||
|
||||
open override func updateView(_ size: CGFloat) {
|
||||
super.updateView(size)
|
||||
leftLabel.updateView(size)
|
||||
rightLabel.updateView(size)
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
guard let model = model as? ListTwoColumnPriceDetailsModel else { return }
|
||||
leftLabel.set(with: model.leftLabel, delegateObject, additionalData)
|
||||
rightLabel.set(with: model.rightLabel, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
open override func reset() {
|
||||
super.reset()
|
||||
leftLabel.reset()
|
||||
rightLabel.reset()
|
||||
leftLabel.styleB2(true)
|
||||
rightLabel.styleB2(true)
|
||||
}
|
||||
|
||||
open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat {
|
||||
return 15
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
//
|
||||
// ListTwoColumnPriceDetailsModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 19/02/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public class ListTwoColumnPriceDetailsModel: ListItemModel, MoleculeModelProtocol {
|
||||
public static var identifier: String = "list2CTxtPrc2"
|
||||
public var leftLabel: LabelModel
|
||||
public var rightLabel: LabelModel
|
||||
|
||||
public init(leftLabel: LabelModel, rightLabel:LabelModel) {
|
||||
self.leftLabel = leftLabel
|
||||
self.rightLabel = rightLabel
|
||||
super.init()
|
||||
}
|
||||
|
||||
/// Defaults to set
|
||||
override public func setDefaults() {
|
||||
super.setDefaults()
|
||||
style = "none"
|
||||
if leftLabel.textColor == nil {
|
||||
leftLabel.textColor = Color(uiColor: .mvmCoolGray6)
|
||||
}
|
||||
if rightLabel.textColor == nil {
|
||||
rightLabel.textColor = Color(uiColor: .mvmCoolGray6)
|
||||
}
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case leftLabel
|
||||
case rightLabel
|
||||
}
|
||||
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
leftLabel = try typeContainer.decode(LabelModel.self, forKey: .leftLabel)
|
||||
rightLabel = try typeContainer.decode(LabelModel.self, forKey: .rightLabel)
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
||||
public override func encode(to encoder: Encoder) throws {
|
||||
try super.encode(to: encoder)
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(leftLabel, forKey: .leftLabel)
|
||||
try container.encode(rightLabel, forKey: .rightLabel)
|
||||
}
|
||||
}
|
||||
@ -14,4 +14,9 @@ public struct ImageHeadlineBodyModel: MoleculeModelProtocol {
|
||||
public var backgroundColor: Color?
|
||||
public var image: ImageViewModel
|
||||
public var headlineBody: HeadlineBodyModel
|
||||
|
||||
public init(image: ImageViewModel, headlineBody: HeadlineBodyModel) {
|
||||
self.image = image
|
||||
self.headlineBody = headlineBody
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +109,9 @@ import UIKit
|
||||
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
|
||||
guard let model = model as? TwoButtonViewModel else { return }
|
||||
|
||||
if let secondaryModel = model.secondaryButton {
|
||||
showSecondaryButton()
|
||||
secondaryButton.set(with: secondaryModel, delegateObject, additionalData)
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -14,18 +14,18 @@ import UIKit
|
||||
// MARK: - MVMCoreUIMoleculeViewProtocol
|
||||
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
|
||||
guard let model = model as? MoleculeListItemModel else { return }
|
||||
|
||||
if molecule != nil {
|
||||
(molecule as? ModelMoleculeViewProtocol)?.set(with: model.molecule, delegateObject, additionalData)
|
||||
|
||||
} else if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(model.molecule, delegateObject, false) {
|
||||
addMolecule(moleculeView)
|
||||
guard let castModel = model as? MoleculeListItemModel else {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
return
|
||||
}
|
||||
|
||||
containerHelper.set(with: model, for: molecule as? MVMCoreUIViewConstrainingProtocol)
|
||||
if molecule != nil {
|
||||
(molecule as? ModelMoleculeViewProtocol)?.set(with: castModel.molecule, delegateObject, additionalData)
|
||||
} else if let moleculeView = MVMCoreUIMoleculeMappingObject.shared()?.createMolecule(castModel.molecule, delegateObject, false) {
|
||||
addMolecule(moleculeView)
|
||||
}
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
public override class func nameForReuse(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> String? {
|
||||
|
||||
@ -152,7 +152,7 @@ import UIKit
|
||||
styleDefault()
|
||||
spaceAboveMolecule = 6.0
|
||||
spaceBelowMolecule = 6.0
|
||||
(middleView as? MoleculeViewProtocol)?.reset?()
|
||||
(middleView as? MVMCoreUIMoleculeViewProtocol)?.reset?()
|
||||
}
|
||||
|
||||
func styleDefault() {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
17
MVMCoreUI/Molecules/RadioButtonLabelModel.swift
Normal file
17
MVMCoreUI/Molecules/RadioButtonLabelModel.swift
Normal file
@ -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
|
||||
}
|
||||
@ -9,21 +9,29 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
@objcMembers public class RadioButtonSelectionHelper: NSObject {
|
||||
|
||||
@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: AnyHashable?
|
||||
|
||||
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.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.fieldKey
|
||||
formValidator.radioButtonsModelByGroup[groupName] = radioButtonSelectionHelper
|
||||
return radioButtonSelectionHelper
|
||||
}
|
||||
|
||||
public func selected(_ radioButton: RadioButton) {
|
||||
@ -34,21 +42,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() -> AnyHashable? {
|
||||
return selectedRadioButton?.formFieldValue()
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
@objcMembers public class HeadlineBodyModel: MoleculeModelProtocol {
|
||||
@objcMembers open class HeadlineBodyModel: MoleculeModelProtocol {
|
||||
public static var identifier: String = "headlineBody"
|
||||
public var moleculeName: String? = HeadlineBodyModel.identifier
|
||||
public var headline: LabelModel?
|
||||
@ -19,4 +19,8 @@ import Foundation
|
||||
public init(headline: LabelModel) {
|
||||
self.headline = headline
|
||||
}
|
||||
|
||||
public init(body: LabelModel) {
|
||||
self.body = body
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ open class StringAndMoleculeView: View {
|
||||
override open func reset() {
|
||||
super.reset()
|
||||
label.reset()
|
||||
(molecule as? MoleculeViewProtocol)?.reset?()
|
||||
(molecule as? MVMCoreUIMoleculeViewProtocol)?.reset?()
|
||||
}
|
||||
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
|
||||
@ -10,13 +10,13 @@ import UIKit
|
||||
|
||||
open class Carousel: View {
|
||||
|
||||
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
|
||||
public let collectionView = UICollectionView(frame: .zero, 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.
|
||||
var pageIndex: Int {
|
||||
public var pageIndex: Int {
|
||||
get {
|
||||
return loop ? currentIndex - 2 : currentIndex
|
||||
}
|
||||
@ -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,20 +35,20 @@ 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)?
|
||||
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() {
|
||||
@ -230,7 +230,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,22 +252,22 @@ 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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
@ -336,7 +336,7 @@ 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)
|
||||
|
||||
@ -135,7 +135,7 @@ open class Stack<T>: Container where T: (StackModelProtocol & MoleculeModelProto
|
||||
super.reset()
|
||||
backgroundColor = .clear
|
||||
for item in stackItems {
|
||||
(item as? MoleculeViewProtocol)?.reset?()
|
||||
(item as? MVMCoreUIMoleculeViewProtocol)?.reset?()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -23,8 +23,8 @@
|
||||
@"centerMoleculeStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeStackCenteredTemplate class]],
|
||||
@"list" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[MoleculeListTemplate class]],
|
||||
@"threeLayer" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ThreeLayerTemplate class]],
|
||||
@"stackModal" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ModalMoleculeStackTemplate class]],
|
||||
@"listModal" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ModalMoleculeListTemplate class]]
|
||||
@"modalStack" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ModalMoleculeStackTemplate class]],
|
||||
@"modalList" : [[MVMCoreViewControllerProgrammaticMappingObject alloc] initWithClass:[ModalMoleculeListTemplate class]]
|
||||
} mutableCopy];
|
||||
});
|
||||
return viewControllerMapping;
|
||||
|
||||
@ -20,6 +20,8 @@ public protocol MoleculeDelegateProtocol {
|
||||
/// Asks the delegate to add or remove molecules.
|
||||
//optional
|
||||
func addMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation)
|
||||
func addMolecules(_ molecules: [[AnyHashable : Any]], indexPath: IndexPath, animation: UITableView.RowAnimation)
|
||||
|
||||
func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation)
|
||||
|
||||
//optional
|
||||
@ -36,6 +38,10 @@ extension MoleculeDelegateProtocol {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public func addMolecules(_ molecules: [[AnyHashable : Any]], indexPath: IndexPath, animation: UITableView.RowAnimation) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public func removeMolecules(_ molecules: [[AnyHashable : Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@ -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)
|
||||
@ -105,23 +106,34 @@ import Foundation
|
||||
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListLeftVariableRadioButtonAndPaymentMethod.self, viewModelClass: ListLeftVariableRadioButtonAndPaymentMethodModel.self)
|
||||
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListRVWheel.self, viewModelClass: ListRVWheelModel.self)
|
||||
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListOneColumnFullWidthTextAllTextAndLinks.self, viewModelClass: ListOneColumnFullWidthTextAllTextAndLinksModel.self)
|
||||
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListOneColumnFullWidthTextBodyText.self, viewModelClass: ListOneColumnFullWidthTextBodyTextModel.self)
|
||||
|
||||
// Designed Section Dividers
|
||||
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListFourColumnDataUsageDivider.self, viewModelClass: ListFourColumnDataUsageDividerModel.self)
|
||||
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListThreeColumnPlanDataDivider.self, viewModelClass: ListThreeColumnPlanDataDividerModel.self)
|
||||
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListTwoColumnCompareChanges.self, viewModelClass: ListTwoColumnCompareChangesModel.self)
|
||||
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListTwoColumnPriceDetails.self, viewModelClass: ListTwoColumnPriceDetailsModel.self)
|
||||
|
||||
// Designed Headers
|
||||
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: HeadersH2NoButtonsBodyText.self, viewModelClass: HeadersH2NoButtonsBodyTextModel.self)
|
||||
|
||||
MVMCoreUIMoleculeMappingObject.shared()?.register(viewClass: ListTwoColumnPriceDescription.self, viewModelClass: ListTwoColumnPriceDescriptionModel.self)
|
||||
// TODO: Need model
|
||||
MVMCoreUIMoleculeMappingObject.shared()?.moleculeMapping.setObject(DigitEntryField.self, forKey: "digitTextField" as NSString)
|
||||
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(RuleAnyRequiredModel.self)
|
||||
try? ModelRegistry.register(RuleAnyValueChangedModel.self)
|
||||
try? ModelRegistry.register(RuleAllValueChangedModel.self)
|
||||
try? ModelRegistry.register(RuleEqualsModel.self)
|
||||
try? ModelRegistry.register(RuleRegexModel.self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.decodeModelIfPresent(codingKey: .header)
|
||||
footer = try typeContainer.decodeModelIfPresent(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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,12 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
//--------------------------------------------------
|
||||
// MARK: - Stored Properties
|
||||
//--------------------------------------------------
|
||||
|
||||
|
||||
public var formValidator: FormValidator?
|
||||
public func validate() {
|
||||
// Can override
|
||||
}
|
||||
|
||||
public var moleculesInfo: [(identifier: String, class: AnyClass, molecule: (ListItemModelProtocol & MoleculeModelProtocol))]?
|
||||
|
||||
var observer: NSKeyValueObservation?
|
||||
@ -132,12 +137,12 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
|
||||
(moleculeCell as? ModelMoleculeViewProtocol)?.set(with: moleculeInfo.molecule, delegate, nil)
|
||||
moleculeCell?.updateView(tableView.bounds.width)
|
||||
|
||||
// Neded to fix an apple defect where the cell is not the correct size on certain devices for certain cells
|
||||
cell.layoutIfNeeded()
|
||||
return cell
|
||||
}
|
||||
|
||||
open override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
||||
|
||||
if let protocolCell = cell as? MoleculeListCellProtocol {
|
||||
protocolCell.willDisplay()
|
||||
}
|
||||
@ -178,8 +183,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
}
|
||||
}
|
||||
|
||||
public override func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
|
||||
open override func addMolecules(_ molecules: [[AnyHashable : Any]], indexPath: IndexPath, animation: UITableView.RowAnimation) {
|
||||
var tmpMolecules = [ListItemModelProtocol & MoleculeModelProtocol]()
|
||||
|
||||
molecules.forEach { molecule in
|
||||
@ -189,7 +193,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
guard let indexPath = self.tableView?.indexPath(for: sender) else { return }
|
||||
var indexPaths: [IndexPath] = []
|
||||
|
||||
for molecule in tmpMolecules {
|
||||
@ -207,7 +210,17 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
}
|
||||
}
|
||||
|
||||
public override func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
open override func addMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let indexPath = self?.tableView?.indexPath(for: sender) else { return }
|
||||
DispatchQueue.global().async {
|
||||
self?.addMolecules(molecules, indexPath: indexPath, animation: animation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open override func removeMolecules(_ molecules: [[AnyHashable: Any]], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
|
||||
var tmpMolecules = [ListItemModelProtocol & MoleculeModelProtocol]()
|
||||
|
||||
@ -235,7 +248,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
view.layoutIfNeeded()
|
||||
}
|
||||
|
||||
public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
open func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
|
||||
// This dispatch is needed to fix a race condition that can occur if this function is called during the table setup.
|
||||
DispatchQueue.main.async {
|
||||
@ -257,7 +270,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
|
||||
}
|
||||
}
|
||||
|
||||
public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
open func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], sender: UITableViewCell, animation: UITableView.RowAnimation) {
|
||||
|
||||
var indexPaths: [IndexPath] = []
|
||||
//TODO: cehck for molecule protocola eqality
|
||||
|
||||
@ -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?
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.decodeModelIfPresent(codingKey: .header)
|
||||
footer = try typeContainer.decodeModelIfPresent(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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,18 +8,23 @@
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -9,6 +9,11 @@
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class ThreeLayerTemplate: ThreeLayerViewController, TemplateProtocol {
|
||||
public func validate() {
|
||||
|
||||
}
|
||||
|
||||
public var formValidator: FormValidator?
|
||||
|
||||
public var templateModel: ThreeLayerPageTemplateModel?
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user