From db424ce04a45d2d6bcf499d360536e8270cea920 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 22 Dec 2020 16:35:21 -0500 Subject: [PATCH 01/18] field errors start --- .../Templates/MoleculeListTemplate.swift | 46 +++++++--- .../BaseControllers/ViewController.swift | 92 +++++++++---------- .../FormUIHelpers/FormFieldProtocol.swift | 5 +- 3 files changed, 79 insertions(+), 64 deletions(-) diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index 4b6b565e..e23d2ccd 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -19,7 +19,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol var observer: NSKeyValueObservation? public var templateModel: ListPageTemplateModel? - + //-------------------------------------------------- // MARK: - Computed Properties //-------------------------------------------------- @@ -41,7 +41,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol //-------------------------------------------------- // MARK: - Methods //-------------------------------------------------- - + open override func parsePageJSON() throws { try parseTemplate(json: loadObject?.pageJSON) try super.parsePageJSON() @@ -54,8 +54,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol open override func viewForTop() -> UIView { guard let headerModel = templateModel?.header, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(headerModel, delegateObject: delegateObjectIVar) - else { return super.viewForTop() } + let molecule = MoleculeObjectMapping.shared()?.createMolecule(headerModel, delegateObject: delegateObjectIVar) + else { return super.viewForTop() } // Temporary, Default the horizontal padding if var container = templateModel?.header as? ContainerModelProtocol, container.useHorizontalMargins == nil { @@ -67,8 +67,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol override open func viewForBottom() -> UIView { guard let footerModel = templateModel?.footer, - let molecule = MoleculeObjectMapping.shared()?.createMolecule(footerModel, delegateObject: delegateObjectIVar) - else { return super.viewForBottom() } + let molecule = MoleculeObjectMapping.shared()?.createMolecule(footerModel, delegateObject: delegateObjectIVar) + else { return super.viewForBottom() } return molecule } @@ -86,7 +86,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol //Handle scroll handleScrollToSpecificRow() } - + //-------------------------------------------------- // MARK: - Handle scroll to spefic row @@ -117,12 +117,12 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol open func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { guard let moleculeInfo = getMoleculeInfo(for: indexPath), - let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject) - else { return 0 } + let estimatedHeight = (moleculeInfo.class as? MoleculeViewProtocol.Type)?.estimatedHeight(with: moleculeInfo.molecule, delegateObject() as? MVMCoreUIDelegateObject) + else { return 0 } return estimatedHeight } - + open override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return moleculesInfo?.count ?? 0 } @@ -130,8 +130,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol open override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let moleculeInfo = getMoleculeInfo(for: indexPath), - let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier) - else { return UITableViewCell() } + let cell = tableView.dequeueReusableCell(withIdentifier: moleculeInfo.identifier) + else { return UITableViewCell() } (cell as? MoleculeViewProtocol)?.reset() (cell as? MoleculeListCellProtocol)?.setLines(with: templateModel?.line, delegateObject: delegateObjectIVar, additionalData: nil, indexPath: indexPath) @@ -156,6 +156,24 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol // MARK: - MoleculeDelegateProtocol //-------------------------------------------------- + public override func handleFieldErrors(_ fieldErrors: [Any]?, loadObject: MVMCoreLoadObject) { + super.handleFieldErrors(fieldErrors, loadObject: loadObject) + + for case let fieldError as [AnyHashable: Any] in fieldErrors ?? [] { + + guard let fieldKey = fieldError["fieldKey"] as? String, + let userError = fieldError["userMessage"] as? String, + let entryFieldModel = formValidator?.fields[fieldKey] as? EntryFieldModel + else { continue } + + entryFieldModel.errorMessage = userError + + DispatchQueue.main.async { + let c = self.tableView.cellForRow(at: IndexPath(row: 0, section: 0))?.layoutSubviews() + } + } + } + open override func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { if let tableView = tableView { @@ -222,8 +240,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol func createMoleculeInfo(with listItem: MoleculeModelProtocol?) -> (identifier: String, class: AnyClass, molecule: MoleculeModelProtocol)? { guard let listItem = listItem, - let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(listItem) - else { return nil } + let moleculeClass = MoleculeObjectMapping.shared()?.getMoleculeClass(listItem) + else { return nil } let moleculeName = moleculeClass.nameForReuse(with: listItem, delegateObject() as? MVMCoreUIDelegateObject) ?? listItem.moleculeName diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 33c47344..5fc57de7 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -18,12 +18,8 @@ import UIKit @objc public var loadObject: MVMCoreLoadObject? public var model: MVMControllerModelProtocol? public var pageModel: PageModelProtocol? { - get { - return model - } - set { - model = newValue as? MVMControllerModelProtocol - } + get { model } + set { model = newValue as? MVMControllerModelProtocol } } /// Set if this page is containted in a manager. @@ -31,12 +27,10 @@ import UIKit /// A temporary iVar backer for delegateObject() until we change the protocol public lazy var delegateObjectIVar: MVMCoreUIDelegateObject = { - return MVMCoreUIDelegateObject.create(withDelegateForAll: self) + MVMCoreUIDelegateObject.create(withDelegateForAll: self) }() - public func delegateObject() -> DelegateObject? { - return delegateObjectIVar - } + public func delegateObject() -> DelegateObject? { delegateObjectIVar } public var formValidator: FormValidator? @@ -52,7 +46,7 @@ import UIKit /// Checks if the screen width has changed open func screenSizeChanged() -> Bool { - return !MVMCoreGetterUtility.cgfequalwiththreshold(previousScreenSize.width, view.bounds.size.width, 0.1) + !MVMCoreGetterUtility.cgfequalwiththreshold(previousScreenSize.width, view.bounds.size.width, 0.1) } //-------------------------------------------------- @@ -61,8 +55,8 @@ import UIKit open func observeForResponseJSONUpdates() { guard !observingForResponses, - (pagesToListenFor()?.count ?? 0 > 0 || modulesToListenFor()?.count ?? 0 > 0) - else { return } + (pagesToListenFor()?.count ?? 0 > 0 || modulesToListenFor()?.count ?? 0 > 0) + else { return } observingForResponses = true NotificationCenter.default.addObserver(self, selector: #selector(responseJSONUpdated(notification:)), name: NSNotification.Name(rawValue: NotificationResponseLoaded), object: nil) @@ -80,28 +74,28 @@ import UIKit } open func modulesToListenFor() -> [String]? { - return loadObject?.requestParameters?.modules as? [String] + loadObject?.requestParameters?.modules as? [String] } @objc open func responseJSONUpdated(notification: Notification) { // Checks for a page we are listening for. var newData = false if let pagesLoaded = notification.userInfo?.optionalDictionaryForKey(KeyPageMap), - let pageType = pagesToListenFor()?.first(where: { (pageTypeListened) -> Bool in - guard let page = pagesLoaded.optionalDictionaryForKey(pageTypeListened), - let pageType = page.optionalStringForKey(KeyPageType), - pageType == pageTypeListened - else { return false } - - return true - }) { + let pageType = pagesToListenFor()?.first(where: { (pageTypeListened) -> Bool in + guard let page = pagesLoaded.optionalDictionaryForKey(pageTypeListened), + let pageType = page.optionalStringForKey(KeyPageType), + pageType == pageTypeListened + else { return false } + + return true + }) { newData = true loadObject?.pageJSON = pagesLoaded.optionalDictionaryForKey(pageType) } // Checks for modules we are listening for. if let modulesLoaded = notification.userInfo?.optionalDictionaryForKey(KeyModuleMap), - let modulesListened = modulesToListenFor() { + let modulesListened = modulesToListenFor() { for moduleName in modulesListened { if let module = modulesLoaded.optionalDictionaryForKey(moduleName) { newData = true @@ -196,9 +190,9 @@ import UIKit open class func verifyRequiredModulesLoaded(for loadObject: MVMCoreLoadObject?, error: AutoreleasingUnsafeMutablePointer) -> Bool { guard let pageType = loadObject?.pageType, - var modulesRequired = MVMCoreUIViewControllerMappingObject.shared()?.modulesRequired(forPageType: pageType), - !modulesRequired.isEmpty - else { return true } + var modulesRequired = MVMCoreUIViewControllerMappingObject.shared()?.modulesRequired(forPageType: pageType), + !modulesRequired.isEmpty + else { return true } guard let loadedModules = loadObject?.modulesJSON else { return false } @@ -263,8 +257,8 @@ import UIKit /// Sets the navigation item for this view controller. open func setNavigationItem() { guard let navigationItemModel = getNavigationModel(), - let navigationController = navigationController - else { return } + let navigationController = navigationController + else { return } // Utilize helper function to set the navigation item state. NavigationController.setNavigationItem(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: self) @@ -273,9 +267,9 @@ import UIKit /// Sets the appearance of the navigation bar based on the model. open func setNavigationBar() { guard let navigationItemModel = getNavigationModel(), - let navigationController = navigationController else { - MVMCoreUISession.sharedGlobal()?.splitViewController?.parent?.setNeedsStatusBarAppearanceUpdate() - return + let navigationController = navigationController else { + MVMCoreUISession.sharedGlobal()?.splitViewController?.parent?.setNeedsStatusBarAppearanceUpdate() + return } // Utilize helper function to set the split view and navigation item state. @@ -405,7 +399,7 @@ import UIKit } open override var supportedInterfaceOrientations: UIInterfaceOrientationMask { - return MVMCoreGetterUtility.isOnIPad() ? UIInterfaceOrientationMask.all : UIInterfaceOrientationMask.portrait + MVMCoreGetterUtility.isOnIPad() ? UIInterfaceOrientationMask.all : UIInterfaceOrientationMask.portrait } open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { @@ -424,6 +418,7 @@ import UIKit open func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) { pageShown() } + //-------------------------------------------------- // MARK: - MVMCoreLoadDelegateProtocol //-------------------------------------------------- @@ -435,15 +430,18 @@ import UIKit // Open the support panel if error == nil, - loadObject?.requestParameters?.openSupportPanel ?? (loadObject?.systemParametersJSON?.boolForKey(KeyOpenSupport) ?? false) == true { + loadObject?.requestParameters?.openSupportPanel ?? (loadObject?.systemParametersJSON?.boolForKey(KeyOpenSupport) ?? false) == true { MVMCoreUISession.sharedGlobal()?.splitViewController?.showRightPanel(animated: true) } } - + /// Override this method to avoid adding form params. open func addFormParams(_ requestParameters: MVMCoreRequestParameters) { formValidator?.addFormParams(requestParameters: requestParameters) } + + public func handleFieldErrors(_ fieldErrors: [Any]?, loadObject: MVMCoreLoadObject) { } + //-------------------------------------------------- // MARK: - MVMCoreActionDelegateProtocol //-------------------------------------------------- @@ -469,9 +467,9 @@ import UIKit open func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol? { guard let moduleJSON = loadObject?.modulesJSON?.optionalDictionaryForKey(moleculeName), - let moleculeName = moduleJSON.optionalStringForKey("moleculeName"), - let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self) - else { return nil } + let moleculeName = moduleJSON.optionalStringForKey("moleculeName"), + let modelType = ModelRegistry.getType(for: moleculeName, with: MoleculeModelProtocol.self) + else { return nil } do { return try modelType.decode(jsonDict: moduleJSON) as? MoleculeModelProtocol @@ -483,8 +481,8 @@ import UIKit } // Needed otherwise when subclassed, the extension gets called. - open func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) {} - open func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? { return nil } + open func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { } + open func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? { nil } open func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) { } open func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) { } @@ -514,13 +512,13 @@ import UIKit } open func showRightPanelForScreenBeforeLaunchApp() -> Bool { - return loadObject?.pageJSON?.lenientBoolForKey("showRightPanel") ?? false + loadObject?.pageJSON?.lenientBoolForKey("showRightPanel") ?? false } // TODO: make molecular open func isOverridingRightButton() -> Bool { guard let rightPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("rightPanelButtonLink") - else { return false } + else { return false } MVMCoreActionHandler.shared()?.handleAction(with: rightPanelLink, additionalData: nil, delegateObject: delegateObject()) return true } @@ -528,7 +526,7 @@ import UIKit // TODO: make molecular open func isOverridingLeftButton() -> Bool { guard let leftPanelLink = loadObject?.pageJSON?.optionalDictionaryForKey("leftPanelButtonLink") - else { return false } + else { return false } MVMCoreActionHandler.shared()?.handleAction(with: leftPanelLink, additionalData: nil, delegateObject: delegateObject()) return true } @@ -536,8 +534,8 @@ import UIKit // Eventually will be moved to Model open func bottomProgress() -> Float? { guard let progressString = loadObject?.pageJSON?.optionalStringForKey(KeyProgressPercent), - let progress = Float(progressString) - else { return nil } + let progress = Float(progressString) + else { return nil } return progress / Float(100) } @@ -558,8 +556,8 @@ import UIKit // TODO: Make this into a protocol if UIAccessibility.isVoiceOverRunning { if let toolBar = textField.inputAccessoryView as? UIToolbar, - let _ = toolBar.items?.last, - let pickerView = textField.inputView as? UIPickerView { + let _ = toolBar.items?.last, + let pickerView = textField.inputView as? UIPickerView { view.accessibilityElements = [pickerView, toolBar] } @@ -610,6 +608,6 @@ import UIKit //-------------------------------------------------- func executeBehaviors(_ behaviorBlock:(_ behavior:T)->Void) { - model?.behaviors?.compactMap({ $0 as? T }).forEach { behaviorBlock($0) } + model?.behaviors?.compactMap { $0 as? T }.forEach { behaviorBlock($0) } } } diff --git a/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift b/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift index b9d2defe..f769e040 100644 --- a/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift +++ b/MVMCoreUI/FormUIHelpers/FormFieldProtocol.swift @@ -22,7 +22,6 @@ public protocol FormFieldProtocol: FormItemProtocol { } extension FormFieldProtocol { - var baseValue: AnyHashable? { - return nil - } + + var baseValue: AnyHashable? { nil } } From f040331b2c08a6d75b5d7138504c4d7ffa0ea107 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Tue, 22 Dec 2020 16:56:02 -0500 Subject: [PATCH 02/18] kind of working --- .../Atomic/Atoms/FormFields/TextFields/EntryField.swift | 2 ++ MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index 65b13861..3efae2ac 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -325,6 +325,8 @@ import UIKit model.wasInitiallySelected = true self.isSelected = true } + + showError = model.isValid! } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index e23d2ccd..d5fa9100 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -167,9 +167,11 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol else { continue } entryFieldModel.errorMessage = userError + entryFieldModel.isValid = true + entryFieldModel.text = "" - DispatchQueue.main.async { - let c = self.tableView.cellForRow(at: IndexPath(row: 0, section: 0))?.layoutSubviews() + DispatchQueue.main.async { [self] in + tableView.reloadData() } } } From 57a3b92bb57e1dcb197fa3a49056aabee8a996a7 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 23 Dec 2020 09:59:38 -0500 Subject: [PATCH 03/18] dynamic --- .../Atoms/FormFields/TextFields/EntryField.swift | 10 ++++++++-- .../Atoms/FormFields/TextFields/EntryFieldModel.swift | 2 ++ MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index 3efae2ac..195fa0b9 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -71,13 +71,17 @@ import UIKit public var showError: Bool { get { return entryFieldContainer.showError } set (error) { - self.feedback = error ? entryFieldModel?.errorMessage : entryFieldModel?.feedback + self.feedback = error ? errorMessage : entryFieldModel?.feedback self.feedbackLabel.textColor = error ? entryFieldModel?.errorTextColor?.uiColor ?? .mvmBlack : .mvmBlack self.entryFieldContainer.showError = error self.entryFieldModel?.showError = error } } + var errorMessage: String { + (entryFieldModel?.dynamicErrorMessage != nil ? entryFieldModel?.dynamicErrorMessage : entryFieldModel?.errorMessage) ?? "" + } + /// Toggles original or locked UI. public var isLocked: Bool { get { return entryFieldContainer.isLocked } @@ -326,7 +330,9 @@ import UIKit self.isSelected = true } - showError = model.isValid! + if model.dynamicErrorMessage != nil { + showError = model.isValid! + } } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index d64f70ae..e5b58733 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -21,6 +21,7 @@ import Foundation public var backgroundColor: Color? public var title: String? public var feedback: String? + public var dynamicErrorMessage: String? public var errorMessage: String? public var errorTextColor: Color? public var enabled: Bool = true @@ -67,6 +68,7 @@ import Foundation //-------------------------------------------------- public func formFieldValue() -> AnyHashable? { + dynamicErrorMessage = nil return text } diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index d5fa9100..5884c763 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -166,7 +166,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol let entryFieldModel = formValidator?.fields[fieldKey] as? EntryFieldModel else { continue } - entryFieldModel.errorMessage = userError + entryFieldModel.dynamicErrorMessage = userError entryFieldModel.isValid = true entryFieldModel.text = "" From b84aeac3c1353d3d86b4e0f03ebe5b72fd18e492 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 23 Dec 2020 10:29:26 -0500 Subject: [PATCH 04/18] moved up a level --- .../Atomic/Templates/MoleculeListTemplate.swift | 16 ++-------------- MVMCoreUI/BaseControllers/ViewController.swift | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index 5884c763..41117af4 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -159,20 +159,8 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol public override func handleFieldErrors(_ fieldErrors: [Any]?, loadObject: MVMCoreLoadObject) { super.handleFieldErrors(fieldErrors, loadObject: loadObject) - for case let fieldError as [AnyHashable: Any] in fieldErrors ?? [] { - - guard let fieldKey = fieldError["fieldKey"] as? String, - let userError = fieldError["userMessage"] as? String, - let entryFieldModel = formValidator?.fields[fieldKey] as? EntryFieldModel - else { continue } - - entryFieldModel.dynamicErrorMessage = userError - entryFieldModel.isValid = true - entryFieldModel.text = "" - - DispatchQueue.main.async { [self] in - tableView.reloadData() - } + DispatchQueue.main.async { [self] in + tableView.reloadData() } } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 5fc57de7..b309e370 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -440,7 +440,20 @@ import UIKit formValidator?.addFormParams(requestParameters: requestParameters) } - public func handleFieldErrors(_ fieldErrors: [Any]?, loadObject: MVMCoreLoadObject) { } + public func handleFieldErrors(_ fieldErrors: [Any]?, loadObject: MVMCoreLoadObject) { + + for case let fieldError as [AnyHashable: Any] in fieldErrors ?? [] { + + guard let fieldKey = fieldError["fieldKey"] as? String, + let userError = fieldError["userMessage"] as? String, + let entryFieldModel = formValidator?.fields[fieldKey] as? EntryFieldModel + else { continue } + + entryFieldModel.dynamicErrorMessage = userError + entryFieldModel.isValid = true + entryFieldModel.text = "" + } + } //-------------------------------------------------- // MARK: - MVMCoreActionDelegateProtocol From 1e4963f58e1f6c1cf2d15e6b52f37a1ad44675ce Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 23 Dec 2020 12:20:38 -0500 Subject: [PATCH 05/18] updates --- MVMCoreUI.xcodeproj/project.pbxproj | 4 +++ .../FormFields/TextFields/EntryField.swift | 5 +-- .../TextFields/EntryFieldModel.swift | 4 +++ .../Atomic/Extensions/UIView+Extension.swift | 35 +++++++++++++++++++ .../Templates/MoleculeListTemplate.swift | 8 ----- .../BaseControllers/ViewController.swift | 6 ++++ 6 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 MVMCoreUI/Atomic/Extensions/UIView+Extension.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 3fce1455..a9c1a769 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -98,6 +98,7 @@ 0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */; }; 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */; }; 0A849EFE246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */; }; + 0A9394892593AC9D00D2791F /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9394882593AC9D00D2791F /* UIView+Extension.swift */; }; 0A9D091D2433796500D2E6C0 /* BarsCarouselIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D09172433796500D2E6C0 /* BarsCarouselIndicatorModel.swift */; }; 0A9D091E2433796500D2E6C0 /* NumericCarouselIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D09182433796500D2E6C0 /* NumericCarouselIndicatorModel.swift */; }; 0A9D091F2433796500D2E6C0 /* NumericIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D09192433796500D2E6C0 /* NumericIndicatorView.swift */; }; @@ -641,6 +642,7 @@ 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryFieldModel.swift; sourceTree = ""; }; 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = ""; }; 0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleEqualsIgnoreCaseModel.swift; sourceTree = ""; }; + 0A9394882593AC9D00D2791F /* UIView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Extension.swift"; sourceTree = ""; }; 0A9D09172433796500D2E6C0 /* BarsCarouselIndicatorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarsCarouselIndicatorModel.swift; sourceTree = ""; }; 0A9D09182433796500D2E6C0 /* NumericCarouselIndicatorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumericCarouselIndicatorModel.swift; sourceTree = ""; }; 0A9D09192433796500D2E6C0 /* NumericIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumericIndicatorView.swift; sourceTree = ""; }; @@ -1386,6 +1388,7 @@ 0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */, D2ED27E6254B0CE600A1C293 /* UIAlertActionStyle+Codable.swift */, D2ED27E7254B0CE600A1C293 /* UIAlertControllerStyle+Extension.swift */, + 0A9394882593AC9D00D2791F /* UIView+Extension.swift */, ); path = Extensions; sourceTree = ""; @@ -2798,6 +2801,7 @@ 0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */, 0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */, D28A837D23CCA86A00DFE4FC /* TabsListItemModel.swift in Sources */, + 0A9394892593AC9D00D2791F /* UIView+Extension.swift in Sources */, 0A51F3E32475CB73002E08B6 /* LoadingSpinner.swift in Sources */, BB2FB3BB247E7EBC00DF73CD /* TagCollectionViewCell.swift in Sources */, 012A88C6238DA34000FE3DA1 /* ModuleMoleculeModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index 195fa0b9..3c990eef 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -78,8 +78,8 @@ import UIKit } } - var errorMessage: String { - (entryFieldModel?.dynamicErrorMessage != nil ? entryFieldModel?.dynamicErrorMessage : entryFieldModel?.errorMessage) ?? "" + var errorMessage: String? { + entryFieldModel?.dynamicErrorMessage ?? entryFieldModel?.errorMessage } /// Toggles original or locked UI. @@ -320,6 +320,7 @@ import UIKit feedback = model.feedback isEnabled = model.enabled entryFieldContainer.disableAllBorders = model.hideBorders + accessibilityIdentifier = model.accessibilityIdentifier ?? model.fieldKey if let isLocked = model.locked { self.isLocked = isLocked diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index e5b58733..02affc3d 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -19,6 +19,7 @@ import Foundation } public var backgroundColor: Color? + public var accessibilityIdentifier: String? public var title: String? public var feedback: String? public var dynamicErrorMessage: String? @@ -49,6 +50,7 @@ import Foundation private enum CodingKeys: String, CodingKey { case moleculeName case backgroundColor + case accessibilityIdentifier case title case enabled case feedback @@ -98,6 +100,7 @@ import Foundation required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier) title = try typeContainer.decodeIfPresent(String.self, forKey: .title) feedback = try typeContainer.decodeIfPresent(String.self, forKey: .feedback) errorMessage = try typeContainer.decodeIfPresent(String.self, forKey: .errorMessage) @@ -119,6 +122,7 @@ import Foundation var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) try container.encodeIfPresent(title, forKey: .title) try container.encodeIfPresent(feedback, forKey: .feedback) try container.encodeIfPresent(text, forKey: .text) diff --git a/MVMCoreUI/Atomic/Extensions/UIView+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIView+Extension.swift new file mode 100644 index 00000000..3878b64a --- /dev/null +++ b/MVMCoreUI/Atomic/Extensions/UIView+Extension.swift @@ -0,0 +1,35 @@ +// +// UIView+Extension.swift +// MVMCoreUI +// +// Created by Kevin Christiano on 12/23/20. +// Copyright © 2020 Verizon Wireless. All rights reserved. +// + +import UIKit + + +extension UIView { + + public class func findByAccessibility(identifier: String) -> UIView? { + + guard let window = UIApplication.shared.keyWindow else { return nil } + + func findByID(view: UIView, _ id: String) -> UIView? { + + if view.accessibilityIdentifier == id { + return view + } + + for v in view.subviews { + if let a = findByID(view: v, id) { + return a + } + } + + return nil + } + + return findByID(view: window, identifier) + } +} diff --git a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift index 41117af4..ba057444 100644 --- a/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift +++ b/MVMCoreUI/Atomic/Templates/MoleculeListTemplate.swift @@ -156,14 +156,6 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol // MARK: - MoleculeDelegateProtocol //-------------------------------------------------- - public override func handleFieldErrors(_ fieldErrors: [Any]?, loadObject: MVMCoreLoadObject) { - super.handleFieldErrors(fieldErrors, loadObject: loadObject) - - DispatchQueue.main.async { [self] in - tableView.reloadData() - } - } - open override func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { if let tableView = tableView { diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index b309e370..fa9a1232 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -452,6 +452,12 @@ import UIKit entryFieldModel.dynamicErrorMessage = userError entryFieldModel.isValid = true entryFieldModel.text = "" + + if let view = UIView.findByAccessibility(identifier: fieldKey), let moleculeView = view as? MoleculeViewProtocol { + DispatchQueue.main.async { [self] in + moleculeView.set(with: entryFieldModel, delegateObjectIVar, nil) + } + } } } From 5b42466c7c130588c153101cebf73ed212a54de3 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 23 Dec 2020 12:40:21 -0500 Subject: [PATCH 06/18] adjustments --- MVMCoreUI/Atomic/Extensions/UIView+Extension.swift | 12 ++++-------- MVMCoreUI/BaseControllers/ViewController.swift | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Atomic/Extensions/UIView+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIView+Extension.swift index 3878b64a..5f4a9aa2 100644 --- a/MVMCoreUI/Atomic/Extensions/UIView+Extension.swift +++ b/MVMCoreUI/Atomic/Extensions/UIView+Extension.swift @@ -15,21 +15,17 @@ extension UIView { guard let window = UIApplication.shared.keyWindow else { return nil } - func findByID(view: UIView, _ id: String) -> UIView? { + func find(view: UIView, by id: String) -> UIView? { - if view.accessibilityIdentifier == id { - return view - } + if view.accessibilityIdentifier == id { return view } for v in view.subviews { - if let a = findByID(view: v, id) { - return a - } + if let aView = find(view: v, by: id) { return aView } } return nil } - return findByID(view: window, identifier) + return find(view: window, by: identifier) } } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index fa9a1232..fadc02a3 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -453,8 +453,8 @@ import UIKit entryFieldModel.isValid = true entryFieldModel.text = "" - if let view = UIView.findByAccessibility(identifier: fieldKey), let moleculeView = view as? MoleculeViewProtocol { - DispatchQueue.main.async { [self] in + DispatchQueue.main.async { [self] in + if let view = UIView.findByAccessibility(identifier: fieldKey), let moleculeView = view as? MoleculeViewProtocol { moleculeView.set(with: entryFieldModel, delegateObjectIVar, nil) } } From ea49af01d645c177f3757f16d8dde7eaec8649cf Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 23 Dec 2020 15:58:43 -0500 Subject: [PATCH 07/18] alterations --- MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift | 3 ++- MVMCoreUI/BaseControllers/ViewController.swift | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index 3c990eef..6bbef151 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -310,6 +310,7 @@ import UIKit if self.isSelected { self.updateValidation(model.isValid ?? true) + } else if model.isValid ?? true && self.showError { self.showError = false } @@ -332,7 +333,7 @@ import UIKit } if model.dynamicErrorMessage != nil { - showError = model.isValid! + showError = !(model.isValid ?? true) } } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index fadc02a3..700746b7 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -450,7 +450,7 @@ import UIKit else { continue } entryFieldModel.dynamicErrorMessage = userError - entryFieldModel.isValid = true + entryFieldModel.isValid = false entryFieldModel.text = "" DispatchQueue.main.async { [self] in From d75e423b0639a7afbef6ae146432f1eee1de0030 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 30 Dec 2020 21:29:11 -0500 Subject: [PATCH 08/18] fieldName --- MVMCoreUI/BaseControllers/ViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 700746b7..2071673d 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -444,7 +444,7 @@ import UIKit for case let fieldError as [AnyHashable: Any] in fieldErrors ?? [] { - guard let fieldKey = fieldError["fieldKey"] as? String, + guard let fieldKey = fieldError["fieldName"] as? String, let userError = fieldError["userMessage"] as? String, let entryFieldModel = formValidator?.fields[fieldKey] as? EntryFieldModel else { continue } From d4aa9ce48ad30816c83151cb6f98b0695f7177f1 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Mon, 4 Jan 2021 10:40:05 -0500 Subject: [PATCH 09/18] updates for field name and cleartext. --- MVMCoreUI/BaseControllers/ViewController.swift | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 2071673d..93e7ceb0 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -444,17 +444,20 @@ import UIKit for case let fieldError as [AnyHashable: Any] in fieldErrors ?? [] { - guard let fieldKey = fieldError["fieldName"] as? String, + guard let fieldName = fieldError["fieldName"] as? String, let userError = fieldError["userMessage"] as? String, - let entryFieldModel = formValidator?.fields[fieldKey] as? EntryFieldModel + let entryFieldModel = formValidator?.fields[fieldName] as? EntryFieldModel else { continue } entryFieldModel.dynamicErrorMessage = userError entryFieldModel.isValid = false - entryFieldModel.text = "" + + if fieldError["clearText"] as? Bool ?? true { + entryFieldModel.text = "" + } DispatchQueue.main.async { [self] in - if let view = UIView.findByAccessibility(identifier: fieldKey), let moleculeView = view as? MoleculeViewProtocol { + if let view = UIView.findByAccessibility(identifier: fieldName), let moleculeView = view as? MoleculeViewProtocol { moleculeView.set(with: entryFieldModel, delegateObjectIVar, nil) } } From 0f9e6d4dae0bdd6e39d8863633f3f737d92b290a Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 6 Jan 2021 16:58:51 -0500 Subject: [PATCH 10/18] revised for validatiod --- .../Atomic/Atoms/FormFields/TextFields/EntryField.swift | 7 +++++++ .../Atoms/FormFields/TextFields/EntryFieldModel.swift | 9 ++++++++- MVMCoreUI/BaseControllers/ViewController.swift | 9 +-------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index 6bbef151..e29081ea 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -317,6 +317,13 @@ import UIKit }) } + model.updateUIDynamicError = { [weak self] in + MVMCoreDispatchUtility.performBlock(onMainThread: { + guard let self = self else { return } + self.updateValidation(model.isValid ?? false) + }) + } + title = model.title feedback = model.feedback isEnabled = model.enabled diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index 02affc3d..f70110ec 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -22,7 +22,12 @@ import Foundation public var accessibilityIdentifier: String? public var title: String? public var feedback: String? - public var dynamicErrorMessage: String? + public var dynamicErrorMessage: String? { + didSet { + isValid = false + updateUIDynamicError?() + } + } public var errorMessage: String? public var errorTextColor: Color? public var enabled: Bool = true @@ -43,6 +48,8 @@ import Foundation /// Temporary binding mechanism for the view to update on enable changes. public var updateUI: ActionBlock? + public var updateUIDynamicError: ActionBlock? + //-------------------------------------------------- // MARK: - Keys //-------------------------------------------------- diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 93e7ceb0..fc24d69f 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -449,18 +449,11 @@ import UIKit let entryFieldModel = formValidator?.fields[fieldName] as? EntryFieldModel else { continue } - entryFieldModel.dynamicErrorMessage = userError - entryFieldModel.isValid = false - if fieldError["clearText"] as? Bool ?? true { entryFieldModel.text = "" } - DispatchQueue.main.async { [self] in - if let view = UIView.findByAccessibility(identifier: fieldName), let moleculeView = view as? MoleculeViewProtocol { - moleculeView.set(with: entryFieldModel, delegateObjectIVar, nil) - } - } + entryFieldModel.dynamicErrorMessage = userError } } From 9495e3f69c99604509f29983d45c5e4b14ac2e2b Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Wed, 6 Jan 2021 17:32:51 -0500 Subject: [PATCH 11/18] deleted extension --- MVMCoreUI.xcodeproj/project.pbxproj | 4 --- .../Atomic/Extensions/UIView+Extension.swift | 31 ------------------- 2 files changed, 35 deletions(-) delete mode 100644 MVMCoreUI/Atomic/Extensions/UIView+Extension.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index e01de725..2dc86525 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -98,7 +98,6 @@ 0A7EF86523D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86423D8AFFF00B2AAD1 /* ItemDropdownEntryFieldModel.swift */; }; 0A7EF86723D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */; }; 0A849EFE246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */; }; - 0A9394892593AC9D00D2791F /* UIView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9394882593AC9D00D2791F /* UIView+Extension.swift */; }; 0A9D091D2433796500D2E6C0 /* BarsCarouselIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D09172433796500D2E6C0 /* BarsCarouselIndicatorModel.swift */; }; 0A9D091E2433796500D2E6C0 /* NumericCarouselIndicatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D09182433796500D2E6C0 /* NumericCarouselIndicatorModel.swift */; }; 0A9D091F2433796500D2E6C0 /* NumericIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A9D09192433796500D2E6C0 /* NumericIndicatorView.swift */; }; @@ -643,7 +642,6 @@ 0A7EF86623D8B0AE00B2AAD1 /* DateDropdownEntryFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateDropdownEntryFieldModel.swift; sourceTree = ""; }; 0A8321AE2355FE9500CB7F00 /* DigitBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitBox.swift; sourceTree = ""; }; 0A849EFD246F1775009F277F /* RuleEqualsIgnoreCaseModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleEqualsIgnoreCaseModel.swift; sourceTree = ""; }; - 0A9394882593AC9D00D2791F /* UIView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Extension.swift"; sourceTree = ""; }; 0A9D09172433796500D2E6C0 /* BarsCarouselIndicatorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BarsCarouselIndicatorModel.swift; sourceTree = ""; }; 0A9D09182433796500D2E6C0 /* NumericCarouselIndicatorModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumericCarouselIndicatorModel.swift; sourceTree = ""; }; 0A9D09192433796500D2E6C0 /* NumericIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NumericIndicatorView.swift; sourceTree = ""; }; @@ -1391,7 +1389,6 @@ 0AB764D224460FA400E7FE72 /* UIPickerView+Extension.swift */, D2ED27E6254B0CE600A1C293 /* UIAlertActionStyle+Codable.swift */, D2ED27E7254B0CE600A1C293 /* UIAlertControllerStyle+Extension.swift */, - 0A9394882593AC9D00D2791F /* UIView+Extension.swift */, ); path = Extensions; sourceTree = ""; @@ -2805,7 +2802,6 @@ 0A21DB83235DFBC500C160A2 /* MdnEntryField.swift in Sources */, 0AE98BB723FF18E9004C5109 /* ArrowModel.swift in Sources */, D28A837D23CCA86A00DFE4FC /* TabsListItemModel.swift in Sources */, - 0A9394892593AC9D00D2791F /* UIView+Extension.swift in Sources */, 0A51F3E32475CB73002E08B6 /* LoadingSpinner.swift in Sources */, BB2FB3BB247E7EBC00DF73CD /* TagCollectionViewCell.swift in Sources */, 012A88C6238DA34000FE3DA1 /* ModuleMoleculeModel.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Extensions/UIView+Extension.swift b/MVMCoreUI/Atomic/Extensions/UIView+Extension.swift deleted file mode 100644 index 5f4a9aa2..00000000 --- a/MVMCoreUI/Atomic/Extensions/UIView+Extension.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// UIView+Extension.swift -// MVMCoreUI -// -// Created by Kevin Christiano on 12/23/20. -// Copyright © 2020 Verizon Wireless. All rights reserved. -// - -import UIKit - - -extension UIView { - - public class func findByAccessibility(identifier: String) -> UIView? { - - guard let window = UIApplication.shared.keyWindow else { return nil } - - func find(view: UIView, by id: String) -> UIView? { - - if view.accessibilityIdentifier == id { return view } - - for v in view.subviews { - if let aView = find(view: v, by: id) { return aView } - } - - return nil - } - - return find(view: window, by: identifier) - } -} From dabad14ed5009368214e7b9ffd27d3ff512061c7 Mon Sep 17 00:00:00 2001 From: "Suresh, Kamlesh" Date: Wed, 6 Jan 2021 18:51:03 -0500 Subject: [PATCH 12/18] code review fiixes --- .../Atomic/Atoms/FormFields/TextFields/EntryField.swift | 3 ++- .../Atoms/FormFields/TextFields/EntryFieldModel.swift | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index e29081ea..23b9710f 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -319,7 +319,8 @@ import UIKit model.updateUIDynamicError = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { - guard let self = self else { return } + guard let self = self, model.dynamicErrorMessage != nil else { return } + model.isValid = false self.updateValidation(model.isValid ?? false) }) } diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index f70110ec..08d3ee39 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -23,8 +23,7 @@ import Foundation public var title: String? public var feedback: String? public var dynamicErrorMessage: String? { - didSet { - isValid = false + didSet { updateUIDynamicError?() } } @@ -47,7 +46,8 @@ import Foundation /// Temporary binding mechanism for the view to update on enable changes. public var updateUI: ActionBlock? - + + // TODO: Remove once updateUI is fixed with isSelected public var updateUIDynamicError: ActionBlock? //-------------------------------------------------- From df5678f6961b86b04d9c1ad732b2045f7990844c Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 7 Jan 2021 09:14:07 -0500 Subject: [PATCH 13/18] adjusted --- .../Atomic/Atoms/FormFields/TextFields/EntryField.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index 23b9710f..3c579317 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -319,7 +319,10 @@ import UIKit model.updateUIDynamicError = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { - guard let self = self, model.dynamicErrorMessage != nil else { return } + guard let self = self, + model.dynamicErrorMessage != nil + else { return } + model.isValid = false self.updateValidation(model.isValid ?? false) }) From 62b02b251690471628bcf3ab705dbbe312fec149 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 7 Jan 2021 09:29:11 -0500 Subject: [PATCH 14/18] altered --- .../Atomic/Atoms/FormFields/TextFields/EntryField.swift | 4 +--- .../Atoms/FormFields/TextFields/EntryFieldModel.swift | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index 3c579317..2d011898 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -319,9 +319,7 @@ import UIKit model.updateUIDynamicError = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { - guard let self = self, - model.dynamicErrorMessage != nil - else { return } + guard let self = self else { return } model.isValid = false self.updateValidation(model.isValid ?? false) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index 08d3ee39..cdcb97f6 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -23,8 +23,10 @@ import Foundation public var title: String? public var feedback: String? public var dynamicErrorMessage: String? { - didSet { - updateUIDynamicError?() + didSet { + if dynamicErrorMessage != nil { + updateUIDynamicError?() + } } } public var errorMessage: String? From 789442f13d885410a4c2fe3b92524ee1a4c59d91 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 7 Jan 2021 10:37:46 -0500 Subject: [PATCH 15/18] changes --- .../Atomic/Atoms/FormFields/TextFields/EntryField.swift | 4 ---- .../Atoms/FormFields/TextFields/EntryFieldModel.swift | 6 +----- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index 2d011898..9e8b531e 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -340,10 +340,6 @@ import UIKit model.wasInitiallySelected = true self.isSelected = true } - - if model.dynamicErrorMessage != nil { - showError = !(model.isValid ?? true) - } } open override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? { diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index cdcb97f6..63d1164e 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -23,11 +23,7 @@ import Foundation public var title: String? public var feedback: String? public var dynamicErrorMessage: String? { - didSet { - if dynamicErrorMessage != nil { - updateUIDynamicError?() - } - } + didSet { updateUIDynamicError?() } } public var errorMessage: String? public var errorTextColor: Color? From 5c0e43319335ddd0f03bd2a8bf01f74545822ea1 Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 7 Jan 2021 10:48:27 -0500 Subject: [PATCH 16/18] changes --- .../Atomic/Atoms/FormFields/TextFields/EntryField.swift | 2 -- .../Atoms/FormFields/TextFields/EntryFieldModel.swift | 9 +++++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index 9e8b531e..16d36bc7 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -320,8 +320,6 @@ import UIKit model.updateUIDynamicError = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { guard let self = self else { return } - - model.isValid = false self.updateValidation(model.isValid ?? false) }) } diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index 63d1164e..c9d60bfe 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -23,7 +23,10 @@ import Foundation public var title: String? public var feedback: String? public var dynamicErrorMessage: String? { - didSet { updateUIDynamicError?() } + didSet { + isValid = dynamicErrorMessage?.isEmpty ?? true + updateUIDynamicError?() + } } public var errorMessage: String? public var errorTextColor: Color? @@ -75,7 +78,9 @@ import Foundation //-------------------------------------------------- public func formFieldValue() -> AnyHashable? { - dynamicErrorMessage = nil + if dynamicErrorMessage != nil { + dynamicErrorMessage = nil + } return text } From c8d628da3151c9d5326098e8fac47f34809ecdaf Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 7 Jan 2021 10:59:09 -0500 Subject: [PATCH 17/18] changes --- .../Atomic/Atoms/FormFields/TextFields/EntryField.swift | 6 +++++- .../Atoms/FormFields/TextFields/EntryFieldModel.swift | 1 + MVMCoreUI/BaseControllers/ViewController.swift | 5 +---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index 16d36bc7..8ecfc04d 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -320,7 +320,11 @@ import UIKit model.updateUIDynamicError = { [weak self] in MVMCoreDispatchUtility.performBlock(onMainThread: { guard let self = self else { return } - self.updateValidation(model.isValid ?? false) + let validState = model.isValid ?? false + self.updateValidation(validState) + if !validState && model.shouldClearText { + self.text = "" + } }) } diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift index c9d60bfe..ef5c57e9 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryFieldModel.swift @@ -22,6 +22,7 @@ import Foundation public var accessibilityIdentifier: String? public var title: String? public var feedback: String? + public var shouldClearText: Bool = false public var dynamicErrorMessage: String? { didSet { isValid = dynamicErrorMessage?.isEmpty ?? true diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index fc24d69f..dcaf611e 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -449,10 +449,7 @@ import UIKit let entryFieldModel = formValidator?.fields[fieldName] as? EntryFieldModel else { continue } - if fieldError["clearText"] as? Bool ?? true { - entryFieldModel.text = "" - } - + entryFieldModel.shouldClearText = fieldError["clearText"] as? Bool ?? true entryFieldModel.dynamicErrorMessage = userError } } From 49c97466d6e58d84bdb3c62faca2e6f05249cced Mon Sep 17 00:00:00 2001 From: Kevin G Christiano Date: Thu, 7 Jan 2021 11:00:15 -0500 Subject: [PATCH 18/18] changes --- MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift index 8ecfc04d..811b2e2a 100644 --- a/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift +++ b/MVMCoreUI/Atomic/Atoms/FormFields/TextFields/EntryField.swift @@ -324,6 +324,7 @@ import UIKit self.updateValidation(validState) if !validState && model.shouldClearText { self.text = "" + model.shouldClearText = false } }) }