Merge branch 'feature/ONEAPP-2811-Tilet' into develop

# Conflicts:
#	JSONCreator_iOS/JSONCreator/TestToggle.swift

Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
Matt Bruce 2023-04-06 15:29:25 -05:00
commit fcfd21400f
5 changed files with 470 additions and 40 deletions

View File

@ -19,46 +19,67 @@
"stack": {
"moleculeName": "stack",
"molecules": [
{
"moleculeName": "stackItem",
"molecule": {
"moleculeName": "toggle",
"fieldKey": "isActive"
}
},
{
"moleculeName": "stackItem",
"molecule": {
"moleculeName":"labelToggle",
"label":{
"moleculeName": "label",
"text":"Label Text Goes Here"
},
"toggle":{
"moleculeName": "toggle"
}
}
},
{
"moleculeName": "stackItem",
"molecule": {
"moleculeName":"headlineBodyToggle",
"headlineBody":{
"moleculeName": "headlineBody",
"headline":{
"moleculeName": "label",
"text": "Headline Text Goes Here"
},
"body":{
"moleculeName": "label",
"text": "Body Text Goes Here"
}
},
"toggle":{
"moleculeName": "toggle"
}
{
"moleculeName": "stackItem",
"molecule": {
"moleculeName": "textView",
"fieldKey": "firstName",
"type": "text",
"errorMessage": "Please enter a valid first name.",
"placeholder": "John A",
"titleLabel": {
"moleculeName": "label",
"text": "First Name"
}
}
},
{
"moleculeName": "stackItem",
"molecule": {
"moleculeName": "textField",
"fieldKey": "lastName",
"type": "text",
"placeholder": "Smith",
"errorMessage": "Please enter a valid last name.",
"titleLabel": {
"moleculeName": "label",
"text": "Last Name"
}
}
},
{
"moleculeName": "stackItem",
"molecule": {
"moleculeName": "textField",
"fieldKey": "phoneNumber",
"type": "phone",
"placeholder": "212-555-1234",
"title": "Contact Phone Number",
"errorMessage": "Please enter a valid phone number."
}
},
{
"moleculeName": "stackItem",
"molecule": {
"moleculeName": "textField",
"fieldKey": "emailID",
"type": "text",
"placeholder": "JSMith123@gmail.com",
"title": "Email",
"errorMessage": "Please enter a valid greeting name."
}
},
{
"moleculeName": "stackItem",
"molecule": {
"moleculeName": "textField",
"fieldKey": "zipcode",
"type": "number",
"placeholder": "90210",
"title": "Zip Code",
"errorMessage": "Please enter a valid zip code."
}
}
]
},
"footer": {
@ -84,7 +105,36 @@
{
"groupName": "default",
"rules": [
{
"type": "regex",
"fields": [
"emailID"
],
"regex": "^[a-zA-Z0-9](\\.?\\_?\\-?[a-zA-Z0-9]){0,}@[a-zA-Z0-9-_]+\\.([a-zA-Z0-9-_]{1,}\\.){0,}[a-zA-Z]{2,}$"
},
{
"type": "regex",
"fields": [
"zipcode"
],
"regex": "^\\d{5}(?:[-\\s]\\d{4})?$"
},
{
"regex": "^(\\d{3})[\\s.-]{0,1}(\\d{3})[\\s.-]{0,1}(\\d{4})$",
"type": "regex",
"fields": [
"phoneNumber"
]
},
{
"type": "allRequired",
"ruleId": "requiredRule",
"fields": [
"emailID",
"firstName",
"lastName"
]
}
]
}
]

View File

@ -0,0 +1,110 @@
{
"ResponseInfo": {},
"Page": {
"pageType": "contactUs",
"screenHeading": "Select an international plan",
"template": "list",
"molecules": [
{
"moleculeName": "listItem",
"molecule": {
"directionalIcon": {
"size": "medium"
},
"moleculeName": "tilelet",
"subTitle": {
"text": "You are enrolled in Auto Pay & paper-free billing."
},
"title": {
"text": "Youre getting $50 off on your monthly bill."
},
"action": {
"actionType": "openPage",
"analyticsData": {
"vzdl.page.displayChannel": "mva",
"vzwi.mvmapp.pageTypeLink": "settingsLanding|Auto Pay discount",
"vzdl.page.id": "settingslanding",
"vzdl.page.linkName": "Auto Pay discount",
"vzdl.page.sourceChannel": "mva",
"vzdl.page.name": "settings landing"
},
"pageType": "managePmts",
"presentationStyle": "push",
"requestURL": "https://mobile-exp-qa2.vzw.com/mobile/nsa/nos/gw/launchapp/l2/webview",
"extraParameters": {
"pageTitle": "Auto Pay discount",
"screenHeading": "Auto Pay discount",
"browserUrl": "https://vzwqa2.verizonwireless.com/digital/nsa/secure/ui/payment/settings#/enrollAandP",
"locale": "EN",
"flowName": "accountsettings"
},
"title": "Auto Pay discount"
}
}
},
{
"moleculeName":"listItem",
"molecule": {
"moleculeName": "twoButtonView",
"primaryButton": {
"moleculeName": "button",
"title": "Edit",
"groupName": "default",
"action": {
"actionType": "openPage",
"pageType": "updateProfile",
"extraParameters": {
"from": "none"
},
"presentationStyle": "push"
}
}
}
},{
"moleculeName":"listItem",
"molecule": {
"moleculeName": "label",
"text": "afa\ndasfdsa\nadfadfda\nasadfsafa\nafsafsa\nafsadfas\nadffafaf"
}
},{
"moleculeName":"listItem",
"molecule": {
"moleculeName": "label",
"text": "afa\ndasfdsa\nadfadfda\nasadfsafa\nafsafsa\nafsadfas\nadffafaf"
}
},{
"moleculeName":"listItem",
"molecule": {
"moleculeName": "label",
"text": "afa\ndasfdsa\nadfadfda\nasadfsafa\nafsafsa\nafsadfas\nadffafaf\ndafsdssfafs"
}
},{
"moleculeName":"listItem",
"molecule": {
"moleculeName": "label",
"text": "afa\ndasfdsa\nadfadfda\nasadfsafa\nafsafsa\nafsadfas\nadffafaf\n\nadsfa\nadfs"
}
},{
"moleculeName":"listItem",
"molecule": {
"moleculeName": "label",
"text": "afa\ndasfdsa\nadfadfda\nasadfsafa\nafsafsa\nafsadfas\nadffafafttttt"
}
},{
"moleculeName":"listItem",
"molecule": {
"moleculeName": "label",
"text": "afa\ndasfdsa\nadfadfda\nasadfsafa\nafsafsa\nafsadfas\nadffafaf\n\nadsfa\nadfs"
}
},{
"moleculeName":"listItem",
"molecule": {
"moleculeName": "label",
"text": "afa\ndasfdsa\nadfadfda\nasadfsafa\nafsafsa\nafsadfas\nadffafafttttt"
}
}
],
"middle": {
}
}
}

View File

@ -0,0 +1,64 @@
{
"Page": {
"template": "stack",
"pageType": "moleculeStack",
"screenHeading": "Tilet Sample",
"hideFabOverlay": true,
"suppressPostLaunchRequests": false,
"tabBarHidden": true,
"header": {
"moleculeName": "header",
"molecule": {
"moleculeName": "headlineBody",
"headline": {
"moleculeName": "label",
"text": "Tilet Variations"
}
}
},
"stack": {
"moleculeName": "stack",
"molecules": [
{
"moleculeName": "stackItem",
"molecule":
{
"directionalIcon": {
"size": "medium"
},
"moleculeName": "tilelet",
"subTitle": {
"text": "You are enrolled in Auto Pay & paper-free billing."
},
"title": {
"text": "Youre getting $50 off on your monthly bill."
},
"action": {
"actionType": "openPage",
"analyticsData": {
"vzdl.page.displayChannel": "mva",
"vzwi.mvmapp.pageTypeLink": "settingsLanding|Auto Pay discount",
"vzdl.page.id": "settingslanding",
"vzdl.page.linkName": "Auto Pay discount",
"vzdl.page.sourceChannel": "mva",
"vzdl.page.name": "settings landing"
},
"pageType": "managePmts",
"presentationStyle": "push",
"requestURL": "https://mobile-exp-qa2.vzw.com/mobile/nsa/nos/gw/launchapp/l2/webview",
"extraParameters": {
"pageTitle": "Auto Pay discount",
"screenHeading": "Auto Pay discount",
"browserUrl": "https://vzwqa2.verizonwireless.com/digital/nsa/secure/ui/payment/settings#/enrollAandP",
"locale": "EN",
"flowName": "accountsettings"
},
"title": "Auto Pay discount"
}
}
}
]
},
"footer": {}
}
}

View File

@ -0,0 +1,206 @@
//
// TestToggle.swift
// JSONCreator
//
// Created by Matt Bruce on 10/21/22.
// Copyright © 2022 Verizon Wireless. All rights reserved.
//
import Foundation
import MVMCore
import MVMCoreUI
import UIKit
import VDS
/**
A custom implementation of Apple's UISwitch.
By default this class begins in the off state.
Container: The background of the toggle control.
Knob: The circular indicator that slides on the container.
*/
open class TestToggle: VDS.Toggle, VDSMoleculeViewProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public var viewModel: TestToggleModel!
public var delegateObject: MVMCoreUIDelegateObject?
public var additionalData: [AnyHashable: Any]?
//--------------------------------------------------
// MARK: - Initializers
//--------------------------------------------------
public override func initialSetup() {
super.initialSetup()
publisher(for: .valueChanged)
.sink {[weak self] toggle in
guard let self = self else { return }
self.valueChanged(isOn: toggle.isOn)
}.store(in: &subscribers)
}
// MARK:- MVMCoreViewProtocol
open func updateView(_ size: CGFloat) {}
override open func updateView() {
super.updateView()
//accessibility
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
accessibilityHint = isEnabled ? MVMCoreUIUtility.hardcodedString(withKey: "AccToggleHint") : MVMCoreUIUtility.hardcodedString(withKey: "AccDisabled")
accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff")
}
open func viewModelDidUpdate() {
guard let viewModel else { return }
additionalData = additionalData.dictionaryAdding(key: KeySourceModel, value: viewModel)
}
private func valueChanged(isOn: Bool){
guard let viewModel else { return }
//sync the value on the viewModel
viewModel.selected = isOn
//tell the form you changed
_ = FormValidator.validate(delegate: self.delegateObject?.formHolderDelegate)
if viewModel.action != nil || viewModel.alternateAction != nil {
var action: ActionModelProtocol?
if isOn {
action = viewModel.action
} else {
action = viewModel.alternateAction ?? viewModel.action
}
if let action {
MVMCoreUIActionHandler.performActionUnstructured(with: action,
sourceModel: viewModel,
additionalData: additionalData,
delegateObject: delegateObject)
}
}
print("toggle value changed to: \(isOn)")
print("viewModel server value: \(viewModel.formFieldServerValue()!)")
}
public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
return 44
}
private typealias ActionDefinition = (model: ActionModelProtocol,
sourceModel: MoleculeModelProtocol?)
private func performActionUnstructured(definition: ActionDefinition) {
MVMCoreUIActionHandler.performActionUnstructured(with: definition.model,
sourceModel: definition.sourceModel,
additionalData: additionalData,
delegateObject: delegateObject)
}
}
// MARK: - MVMCoreUIViewConstrainingProtocol
extension TestToggle {
public func needsToBeConstrained() -> Bool { true }
public func horizontalAlignment() -> UIStackView.Alignment { .trailing }
}
public class TestToggleModel: MoleculeModelProtocol, FormFieldProtocol {
//--------------------------------------------------
// MARK: - Properties
//--------------------------------------------------
public static var identifier: String = "testToggle"
public var backgroundColor: Color? //not used
public var selected: Bool = false
public var enabled: Bool = true
public var readOnly: Bool = false
public var action: ActionModelProtocol?
public var alternateAction: ActionModelProtocol?
public var accessibilityText: String?
public var fieldKey: String?
public var groupName: String = FormValidator.defaultGroupName
public var baseValue: AnyHashable?
//--------------------------------------------------
// MARK: - Keys
//--------------------------------------------------
private enum CodingKeys: String, CodingKey {
case moleculeName
case state
case enabled
case readOnly
case action
case accessibilityIdentifier
case alternateAction
case accessibilityText
case fieldKey
case groupName
}
//--------------------------------------------------
// MARK: - Form Valdiation
//--------------------------------------------------
public func formFieldValue() -> AnyHashable? {
guard enabled else { return nil }
return selected
}
//--------------------------------------------------
// MARK: - Server Value
//--------------------------------------------------
open func formFieldServerValue() -> AnyHashable? {
return formFieldValue()
}
//--------------------------------------------------
// MARK: - Initializer
//--------------------------------------------------
public init(_ state: Bool) {
selected = state
baseValue = state
}
//--------------------------------------------------
// MARK: - Codec
//--------------------------------------------------
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) {
selected = state
}
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction)
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
baseValue = selected
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let gName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
groupName = gName
}
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeModelIfPresent(action, forKey: .action)
try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction)
try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(selected, forKey: .state)
try container.encode(enabled, forKey: .enabled)
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(groupName, forKey: .groupName)
try container.encode(readOnly, forKey: .readOnly)
}
}

View File

@ -1,6 +1,6 @@
mvm_core https://gitlab.verizon.com/BPHV_MIPS/mvm_core.git develop
mvm_core_ui https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui.git develop
mvm_core_ui https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui.git feature/ONEAPP-2811-Tilet
vds_ios https://gitlab.verizon.com/BPHV_MIPS/vds_ios.git develop