Signed-off-by: Matt Bruce <matt.bruce@verizon.com>
This commit is contained in:
parent
cc5c68094c
commit
d8cda0f3dc
@ -77,6 +77,7 @@
|
|||||||
EA5B696F2866BC1000B17D2E /* MVMCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EA5B696C2866BC1000B17D2E /* MVMCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
EA5B696F2866BC1000B17D2E /* MVMCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EA5B696C2866BC1000B17D2E /* MVMCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
EA5B69702866BC1000B17D2E /* MVMCoreUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA5B696D2866BC1000B17D2E /* MVMCoreUI.framework */; };
|
EA5B69702866BC1000B17D2E /* MVMCoreUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA5B696D2866BC1000B17D2E /* MVMCoreUI.framework */; };
|
||||||
EA5B69712866BC1000B17D2E /* MVMCoreUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EA5B696D2866BC1000B17D2E /* MVMCoreUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
EA5B69712866BC1000B17D2E /* MVMCoreUI.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EA5B696D2866BC1000B17D2E /* MVMCoreUI.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
|
EA797B2C2902D4BB00DBAFE6 /* TestToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA797B2B2902D4BB00DBAFE6 /* TestToggle.swift */; };
|
||||||
EAA658152875FA5E00484A7D /* VDSFormControlsTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAA658142875FA5E00484A7D /* VDSFormControlsTokens.xcframework */; };
|
EAA658152875FA5E00484A7D /* VDSFormControlsTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAA658142875FA5E00484A7D /* VDSFormControlsTokens.xcframework */; };
|
||||||
EAA658162875FA5E00484A7D /* VDSFormControlsTokens.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EAA658142875FA5E00484A7D /* VDSFormControlsTokens.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
EAA658162875FA5E00484A7D /* VDSFormControlsTokens.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = EAA658142875FA5E00484A7D /* VDSFormControlsTokens.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
EACA5E5E2853DBC900CBA65B /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EACA5E5D2853DBC900CBA65B /* VDSColorTokens.xcframework */; };
|
EACA5E5E2853DBC900CBA65B /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EACA5E5D2853DBC900CBA65B /* VDSColorTokens.xcframework */; };
|
||||||
@ -164,6 +165,7 @@
|
|||||||
EA3361FA2891D54A0071C351 /* VDSTypographyTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSTypographyTokens.xcframework; path = ../SharedFrameworks/VDSTypographyTokens.xcframework; sourceTree = "<group>"; };
|
EA3361FA2891D54A0071C351 /* VDSTypographyTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSTypographyTokens.xcframework; path = ../SharedFrameworks/VDSTypographyTokens.xcframework; sourceTree = "<group>"; };
|
||||||
EA5B696C2866BC1000B17D2E /* MVMCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MVMCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA5B696C2866BC1000B17D2E /* MVMCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MVMCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EA5B696D2866BC1000B17D2E /* MVMCoreUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MVMCoreUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA5B696D2866BC1000B17D2E /* MVMCoreUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MVMCoreUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
EA797B2B2902D4BB00DBAFE6 /* TestToggle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestToggle.swift; sourceTree = "<group>"; };
|
||||||
EA7E676927582F2200ABF773 /* MVMCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MVMCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA7E676927582F2200ABF773 /* MVMCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MVMCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EA7E676A27582F2200ABF773 /* MVMCoreUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MVMCoreUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
EA7E676A27582F2200ABF773 /* MVMCoreUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MVMCoreUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
EAA658142875FA5E00484A7D /* VDSFormControlsTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSFormControlsTokens.xcframework; path = ../SharedFrameworks/VDSFormControlsTokens.xcframework; sourceTree = "<group>"; };
|
EAA658142875FA5E00484A7D /* VDSFormControlsTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSFormControlsTokens.xcframework; path = ../SharedFrameworks/VDSFormControlsTokens.xcframework; sourceTree = "<group>"; };
|
||||||
@ -228,6 +230,7 @@
|
|||||||
D2B1E3FB22F4A6930065F95C /* Assets.xcassets */,
|
D2B1E3FB22F4A6930065F95C /* Assets.xcassets */,
|
||||||
D2B1E3FD22F4A6930065F95C /* LaunchScreen.storyboard */,
|
D2B1E3FD22F4A6930065F95C /* LaunchScreen.storyboard */,
|
||||||
D2B1E40022F4A6930065F95C /* Info.plist */,
|
D2B1E40022F4A6930065F95C /* Info.plist */,
|
||||||
|
EA797B2B2902D4BB00DBAFE6 /* TestToggle.swift */,
|
||||||
);
|
);
|
||||||
path = JSONCreator;
|
path = JSONCreator;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -479,6 +482,7 @@
|
|||||||
D2FC4FB025897ACB00061EA4 /* OrderTracker.swift in Sources */,
|
D2FC4FB025897ACB00061EA4 /* OrderTracker.swift in Sources */,
|
||||||
EA09CDD8282C40CC00A7835F /* GMFGBLEHandlerProtocol.swift in Sources */,
|
EA09CDD8282C40CC00A7835F /* GMFGBLEHandlerProtocol.swift in Sources */,
|
||||||
EA09CDDC282C40CC00A7835F /* GMFGFotaHandler.swift in Sources */,
|
EA09CDDC282C40CC00A7835F /* GMFGFotaHandler.swift in Sources */,
|
||||||
|
EA797B2C2902D4BB00DBAFE6 /* TestToggle.swift in Sources */,
|
||||||
EA09CDD6282C40CC00A7835F /* GMFGConstant.swift in Sources */,
|
EA09CDD6282C40CC00A7835F /* GMFGConstant.swift in Sources */,
|
||||||
D27564C925939E91003CA713 /* Links.swift in Sources */,
|
D27564C925939E91003CA713 /* Links.swift in Sources */,
|
||||||
EA09CDE6282C416C00A7835F /* BluetoothDebuggableProtocol.swift in Sources */,
|
EA09CDE6282C416C00A7835F /* BluetoothDebuggableProtocol.swift in Sources */,
|
||||||
|
|||||||
@ -130,149 +130,6 @@ extension AppDelegate: MVMCoreGlobalTopAlertDelegateProtocol {
|
|||||||
|
|
||||||
extension AppDelegate {
|
extension AppDelegate {
|
||||||
func register(){
|
func register(){
|
||||||
ModelRegistry.register(handler: TextEntryField.self, for: TextEntryField64Model.self)
|
ModelRegistry.register(handler: TestToggle.self, for: TestToggleModel.self)
|
||||||
ModelRegistry.register(handler: EmailVerifyField.self, for: EmailVerifyModel.self)
|
|
||||||
ModelRegistry.register(handler: ToggleWifiActionHandler.self, for: ToggleWifiActionModel.self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objcMembers open class EmailVerifyModel: MoleculeModelProtocol {
|
|
||||||
|
|
||||||
public static var identifier: String = "emailVerifyField"
|
|
||||||
public var moleculeName: String = EmailVerifyModel.identifier
|
|
||||||
public var emailField: TextEntryFieldModel
|
|
||||||
public var bottomMolecule: MoleculeModelProtocol
|
|
||||||
public var email: String
|
|
||||||
public var backgroundColor: MVMCoreUI.Color?
|
|
||||||
|
|
||||||
public init(emailField: TextEntryFieldModel, email: String, bottomMolecule: MoleculeModelProtocol) {
|
|
||||||
self.emailField = emailField
|
|
||||||
self.email = email
|
|
||||||
self.bottomMolecule = bottomMolecule
|
|
||||||
}
|
|
||||||
|
|
||||||
public required init(from decoder: Decoder) throws {
|
|
||||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
|
||||||
emailField = try typeContainer.decode(TextEntryFieldModel.self, forKey: .emailField)
|
|
||||||
email = try typeContainer.decode(String.self, forKey: .email)
|
|
||||||
bottomMolecule = try typeContainer.decodeModel(codingKey: .bottomMolecule)
|
|
||||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
|
||||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
|
||||||
try container.encode(emailField, forKey: .emailField)
|
|
||||||
try container.encode(email, forKey: .email)
|
|
||||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
|
||||||
try container.encodeModel(bottomMolecule, forKey: .bottomMolecule)
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
|
||||||
case moleculeName
|
|
||||||
case emailField
|
|
||||||
case bottomMolecule
|
|
||||||
case backgroundColor
|
|
||||||
case email
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@objcMembers open class EmailVerifyField: View {
|
|
||||||
|
|
||||||
private let emailField = TextEntryField()
|
|
||||||
|
|
||||||
private var bottomView: MoleculeViewProtocol?
|
|
||||||
|
|
||||||
private var emailVerifyFieldModel: EmailVerifyModel? {
|
|
||||||
return model as? EmailVerifyModel
|
|
||||||
}
|
|
||||||
|
|
||||||
private var isBottomViewHidden: Bool {
|
|
||||||
guard let emailVerifyFieldModel = emailVerifyFieldModel, let text = emailField.text else { return true }
|
|
||||||
return !(emailVerifyFieldModel.email.caseInsensitiveCompare(text) == .orderedSame)
|
|
||||||
}
|
|
||||||
|
|
||||||
private let containerView = MVMCoreUICommonViewsUtility.commonView()
|
|
||||||
|
|
||||||
open override func setupView() {
|
|
||||||
super.setupView()
|
|
||||||
backgroundColor = .clear
|
|
||||||
clipsToBounds = true
|
|
||||||
addSubview(containerView)
|
|
||||||
NSLayoutConstraint.constraintPinSubview(toSuperview: containerView)
|
|
||||||
containerView.addSubview(emailField)
|
|
||||||
NSLayoutConstraint.constraintPinSubview(emailField, pinTop: true, pinBottom: false, pinLeft: true, pinRight: true)
|
|
||||||
addEmailFieldObserver()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func addEmailFieldObserver() {
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(onEmailValueChange), name: UITextField.textDidChangeNotification, object: emailField.textField)
|
|
||||||
}
|
|
||||||
|
|
||||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
|
||||||
super.set(with: model, delegateObject, additionalData)
|
|
||||||
|
|
||||||
guard let model = model as? EmailVerifyModel else { return }
|
|
||||||
|
|
||||||
emailField.set(with: model.emailField, delegateObject, additionalData)
|
|
||||||
|
|
||||||
if let bottomView = self.bottomView ?? ModelRegistry.createMolecule(model.bottomMolecule, delegateObject: delegateObject, additionalData: additionalData) {
|
|
||||||
bottomView.set(with: model.bottomMolecule, delegateObject, additionalData)
|
|
||||||
self.bottomView = bottomView
|
|
||||||
addBottomView(bottomView: bottomView)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func onEmailValueChange() {
|
|
||||||
bottomView?.isHidden = isBottomViewHidden
|
|
||||||
}
|
|
||||||
|
|
||||||
private func addBottomView(bottomView: MoleculeViewProtocol) {
|
|
||||||
|
|
||||||
containerView.addSubview(bottomView)
|
|
||||||
|
|
||||||
bottomView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true
|
|
||||||
containerView.trailingAnchor.constraint(equalTo: bottomView.trailingAnchor).isActive = true
|
|
||||||
bottomView.topAnchor.constraint(equalTo: emailField.bottomAnchor).isActive = true
|
|
||||||
containerView.bottomAnchor.constraint(equalTo: bottomView.bottomAnchor).isActive = true
|
|
||||||
bottomView.isHidden = isBottomViewHidden
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ToggleWifiActionModel: ActionModelProtocol {
|
|
||||||
static var identifier: String = "toggleWifi"
|
|
||||||
var extraParameters: JSONValueDictionary?
|
|
||||||
var analyticsData: JSONValueDictionary?
|
|
||||||
var wifiId: String
|
|
||||||
var actionType: String = ToggleWifiActionModel.identifier
|
|
||||||
|
|
||||||
init(wifiId: String) {
|
|
||||||
self.wifiId = wifiId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TextEntryField64Model: TextEntryFieldModel {
|
|
||||||
open override class var identifier: String { "textFieldBase64" }
|
|
||||||
|
|
||||||
open override func formFieldServerValue() -> AnyHashable? {
|
|
||||||
guard let value = super.formFieldServerValue() as? String else { return nil }
|
|
||||||
return value.base64Encoded()
|
|
||||||
}
|
|
||||||
|
|
||||||
required init(from decoder: Decoder) throws {
|
|
||||||
try super.init(from: decoder)
|
|
||||||
text = text?.base64Decoded()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension String {
|
|
||||||
|
|
||||||
func base64Encoded() -> String? {
|
|
||||||
data(using: .utf8)?.base64EncodedString()
|
|
||||||
}
|
|
||||||
|
|
||||||
func base64Decoded() -> String? {
|
|
||||||
guard let data = Data(base64Encoded: self) else { return nil }
|
|
||||||
return String(data: data, encoding: .utf8)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,72 +22,43 @@
|
|||||||
{
|
{
|
||||||
"moleculeName": "stackItem",
|
"moleculeName": "stackItem",
|
||||||
"molecule": {
|
"molecule": {
|
||||||
"moleculeName": "testToggle",
|
"moleculeName": "toggle",
|
||||||
"fieldKey": "isActive"
|
"fieldKey": "isActive"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moleculeName": "stackItem",
|
"moleculeName": "stackItem",
|
||||||
"molecule": {
|
"molecule": {
|
||||||
"moleculeName": "textField",
|
"moleculeName":"labelToggle",
|
||||||
"fieldKey": "firstName",
|
"label":{
|
||||||
"type": "text",
|
"moleculeName": "label",
|
||||||
"errorMessage": "Please enter a valid first name.",
|
"text":"Label Text Goes Here"
|
||||||
"placeholder": "John A",
|
},
|
||||||
"titleLabel": {
|
"toggle":{
|
||||||
"moleculeName": "label",
|
"moleculeName": "toggle"
|
||||||
"text": "First Name"
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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": "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": "textFieldBase64",
|
|
||||||
"fieldKey": "zipcode",
|
|
||||||
"type": "number",
|
|
||||||
"placeholder": "90210",
|
|
||||||
"title": "Zip Code",
|
|
||||||
"text": "NzUwMzQ=",
|
|
||||||
"errorMessage": "Please enter a valid zip code."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
@ -113,36 +84,7 @@
|
|||||||
{
|
{
|
||||||
"groupName": "default",
|
"groupName": "default",
|
||||||
"rules": [
|
"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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
60
JSONCreator_iOS/JSONCreator/JSON/Samples/ToggleSample.json
Normal file
60
JSONCreator_iOS/JSONCreator/JSON/Samples/ToggleSample.json
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"Page": {
|
||||||
|
"template": "stack",
|
||||||
|
"pageType": "moleculeStack",
|
||||||
|
"screenHeading": "Manage Profile",
|
||||||
|
"hideFabOverlay": true,
|
||||||
|
"suppressPostLaunchRequests": false,
|
||||||
|
"tabBarHidden": true,
|
||||||
|
"header": {
|
||||||
|
"moleculeName": "header",
|
||||||
|
"molecule": {
|
||||||
|
"moleculeName": "headlineBody",
|
||||||
|
"headline": {
|
||||||
|
"moleculeName": "label",
|
||||||
|
"text": "Zenkey"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"stack": {
|
||||||
|
"moleculeName": "stack",
|
||||||
|
"molecules": [
|
||||||
|
{
|
||||||
|
"moleculeName": "stackItem",
|
||||||
|
"molecule": {
|
||||||
|
"moleculeName": "toggle",
|
||||||
|
"fieldKey": "isActive"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"footer": {
|
||||||
|
"moleculeName": "footer",
|
||||||
|
"molecule": {
|
||||||
|
"moleculeName": "twoButtonView",
|
||||||
|
"primaryButton": {
|
||||||
|
"moleculeName": "button",
|
||||||
|
"title": "Edit",
|
||||||
|
"groupName": "default",
|
||||||
|
"action": {
|
||||||
|
"actionType": "openPage",
|
||||||
|
"pageType": "updateProfile",
|
||||||
|
"extraParameters": {
|
||||||
|
"from": "none"
|
||||||
|
},
|
||||||
|
"presentationStyle": "push"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"formRules": [
|
||||||
|
{
|
||||||
|
"groupName": "default",
|
||||||
|
"rules": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -22,17 +22,7 @@ import MVMCoreUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class JSONCreatorActionHandler: MVMCoreUIActionHandler {
|
public class JSONCreatorActionHandler: MVMCoreUIActionHandler {
|
||||||
public override func handleOtherActions(_ actionType: String?, actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?, delegateObject: DelegateObject?) -> Bool {
|
|
||||||
if actionType == "print" {
|
|
||||||
if actionInformation?.boolForKey("delay") ?? false {
|
|
||||||
sleep(2)
|
|
||||||
}
|
|
||||||
print(actionInformation?.stringForkey("text") ?? "fail")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return super.handleOtherActions(actionType, actionInformation: actionInformation, additionalData: additionalData, delegateObject: delegateObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
public static func doStuff() {
|
public static func doStuff() {
|
||||||
MVMCoreObject.sharedInstance()?.actionHandler = JSONCreatorActionHandler()
|
MVMCoreObject.sharedInstance()?.actionHandler = JSONCreatorActionHandler()
|
||||||
ModelRegistry.register(ActionPrintModel.self)
|
ModelRegistry.register(ActionPrintModel.self)
|
||||||
|
|||||||
211
JSONCreator_iOS/JSONCreator/TestToggle.swift
Normal file
211
JSONCreator_iOS/JSONCreator/TestToggle.swift
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
//
|
||||||
|
// 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: ToggleBase, 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: .touchUpInside)
|
||||||
|
.sink {[weak self] toggle in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.toggle()
|
||||||
|
}.store(in: &subscribers)
|
||||||
|
|
||||||
|
publisher(for: .valueChanged)
|
||||||
|
.sink {[weak self] toggle in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.valueChanged(isOn: toggle.isOn)
|
||||||
|
}.store(in: &subscribers)
|
||||||
|
|
||||||
|
accessibilityLabelEnabled = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
|
||||||
|
accessibilityLabelDisabled = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
|
||||||
|
accessibilityHintEnabled = MVMCoreUIUtility.hardcodedString(withKey: "AccToggleHint")
|
||||||
|
accessibilityHintDisabled = MVMCoreUIUtility.hardcodedString(withKey: "AccDisabled")
|
||||||
|
accessibilityValueEnabled = MVMCoreUIUtility.hardcodedString(withKey: "AccOn")
|
||||||
|
accessibilityValueDisabled = MVMCoreUIUtility.hardcodedString(withKey: "AccOff")
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK:- MVMCoreViewProtocol
|
||||||
|
open func updateView(_ size: CGFloat) {}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user