diff --git a/samples/v1.3/Elements/Action.Submit.IgnoreInputValidation.json b/samples/v1.3/Elements/Action.Submit.IgnoreInputValidation.json new file mode 100644 index 0000000000..f97bf67cb1 --- /dev/null +++ b/samples/v1.3/Elements/Action.Submit.IgnoreInputValidation.json @@ -0,0 +1,33 @@ +{ + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "version": "1.3", + "body": [ + { + "type": "TextBlock", + "text": "Here are some required inputs" + }, + { + "type": "Input.Text", + "id": "input1", + "isRequired": true + }, + { + "type": "Input.Text", + "id": "input2", + "isRequired": true + } + ], + "actions": [ + { + "type": "Action.Submit", + "title": "OK", + "ignoreInputValidation": false + }, + { + "type": "Action.Submit", + "title": "Cancel", + "ignoreInputValidation": true + } + ] +} diff --git a/samples/v1.3/Elements/AdaptiveCard.InputNecessityIndicators.json b/samples/v1.3/Elements/AdaptiveCard.InputNecessityIndicators.json new file mode 100644 index 0000000000..23454aa61c --- /dev/null +++ b/samples/v1.3/Elements/AdaptiveCard.InputNecessityIndicators.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "inputNecessityIndicators": "optionalInputs", + "version": "1.3", + "body": [ + { + "type": "TextBlock", + "text": "This one is optional" + }, + { + "type": "Input.Text", + "id": "input1", + "isRequired": false + }, + { + "type": "TextBlock", + "text": "This one too" + }, + { + "type": "Input.Text", + "id": "input2" + }, + { + "type": "TextBlock", + "text": "This is required" + }, + { + "type": "Input.Text", + "id": "input3", + "isRequired": true + } + ], + "actions": [ + { + "type": "Action.Submit", + "title": "OK" + } + ] +} diff --git a/samples/v1.3/Elements/Input.Text.Regex.json b/samples/v1.3/Elements/Input.Text.Regex.json new file mode 100644 index 0000000000..93f66297a5 --- /dev/null +++ b/samples/v1.3/Elements/Input.Text.Regex.json @@ -0,0 +1,34 @@ +{ + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "inputNecessityIndicators": "none", + "version": "1.3", + "body": [ + { + "type": "TextBlock", + "text": "This input is required and has a regex" + }, + { + "type": "Input.Text", + "id": "input1", + "isRequired": true, + "regEx": "([A-Z])\\w+" + }, + { + "type": "TextBlock", + "text": "This input is optional and has a regex" + }, + { + "type": "Input.Text", + "id": "input2", + "isRequired": false, + "regEx": "([A-Z])\\w+" + } + ], + "actions": [ + { + "type": "Action.Submit", + "title": "OK" + } + ] +} diff --git a/samples/v1.3/Elements/Input.Text.isRequired.json b/samples/v1.3/Elements/Input.Text.isRequired.json new file mode 100644 index 0000000000..cc1cffbcc5 --- /dev/null +++ b/samples/v1.3/Elements/Input.Text.isRequired.json @@ -0,0 +1,33 @@ +{ + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "inputNecessityIndicators": "requiredInputs", + "version": "1.3", + "body": [ + { + "type": "TextBlock", + "text": "Two required inputs and one optional" + }, + { + "type": "Input.Text", + "id": "input1", + "isRequired": true + }, + { + "type": "Input.Text", + "id": "input2", + "isRequired": true + }, + { + "type": "Input.Text", + "id": "input3", + "isRequired": false + } + ], + "actions": [ + { + "type": "Action.Submit", + "title": "OK" + } + ] +} diff --git a/source/android/adaptivecards/src/main/cpp/objectmodel_wrap.cpp b/source/android/adaptivecards/src/main/cpp/objectmodel_wrap.cpp index 6ef6a98dd0..bc488f23af 100644 --- a/source/android/adaptivecards/src/main/cpp/objectmodel_wrap.cpp +++ b/source/android/adaptivecards/src/main/cpp/objectmodel_wrap.cpp @@ -8812,6 +8812,54 @@ SWIGEXPORT jint JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectMode } +SWIGEXPORT jlong JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_getInputNecessityIndicatorsEnum(JNIEnv *jenv, jclass jcls) { + jlong jresult = 0 ; + AdaptiveCards::EnumHelpers::EnumMapping< AdaptiveCards::InputNecessityIndicators > *result = 0 ; + + (void)jenv; + (void)jcls; + result = (AdaptiveCards::EnumHelpers::EnumMapping< AdaptiveCards::InputNecessityIndicators > *) &AdaptiveCards::EnumHelpers::getInputNecessityIndicatorsEnum(); + *(AdaptiveCards::EnumHelpers::EnumMapping< AdaptiveCards::InputNecessityIndicators > **)&jresult = result; + return jresult; +} + + +SWIGEXPORT jstring JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_InputNecessityIndicatorsToString(JNIEnv *jenv, jclass jcls, jint jarg1) { + jstring jresult = 0 ; + AdaptiveCards::InputNecessityIndicators arg1 ; + std::string result; + + (void)jenv; + (void)jcls; + arg1 = (AdaptiveCards::InputNecessityIndicators)jarg1; + result = AdaptiveCards::InputNecessityIndicatorsToString(arg1); + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT jint JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_InputNecessityIndicatorsFromString(JNIEnv *jenv, jclass jcls, jstring jarg1) { + jint jresult = 0 ; + std::string *arg1 = 0 ; + AdaptiveCards::InputNecessityIndicators result; + + (void)jenv; + (void)jcls; + if(!jarg1) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return 0; + } + const char *arg1_pstr = (const char *)jenv->GetStringUTFChars(jarg1, 0); + if (!arg1_pstr) return 0; + std::string arg1_str(arg1_pstr); + arg1 = &arg1_str; + jenv->ReleaseStringUTFChars(jarg1, arg1_pstr); + result = (AdaptiveCards::InputNecessityIndicators)AdaptiveCards::InputNecessityIndicatorsFromString((std::string const &)*arg1); + jresult = (jint)result; + return jresult; +} + + SWIGEXPORT jlong JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_AdaptiveBase64Util_1Decode(JNIEnv *jenv, jclass jcls, jstring jarg1) { jlong jresult = 0 ; std::string *arg1 = 0 ; @@ -10810,6 +10858,47 @@ SWIGEXPORT void JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectMode } +SWIGEXPORT jstring JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_BaseInputElement_1GetErrorMessage(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jstring jresult = 0 ; + AdaptiveCards::BaseInputElement *arg1 = (AdaptiveCards::BaseInputElement *) 0 ; + std::shared_ptr< AdaptiveCards::BaseInputElement const > *smartarg1 = 0 ; + std::string result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + + smartarg1 = *(std::shared_ptr< const AdaptiveCards::BaseInputElement > **)&jarg1; + arg1 = (AdaptiveCards::BaseInputElement *)(smartarg1 ? smartarg1->get() : 0); + result = ((AdaptiveCards::BaseInputElement const *)arg1)->GetErrorMessage(); + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT void JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_BaseInputElement_1SetErrorMessage(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + AdaptiveCards::BaseInputElement *arg1 = (AdaptiveCards::BaseInputElement *) 0 ; + std::string arg2 ; + std::shared_ptr< AdaptiveCards::BaseInputElement > *smartarg1 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + + smartarg1 = *(std::shared_ptr< AdaptiveCards::BaseInputElement > **)&jarg1; + arg1 = (AdaptiveCards::BaseInputElement *)(smartarg1 ? smartarg1->get() : 0); + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + (&arg2)->assign(arg2_pstr); + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + (arg1)->SetErrorMessage(arg2); +} + + SWIGEXPORT jlong JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_BaseInputElement_1SerializeToJsonValue(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { jlong jresult = 0 ; AdaptiveCards::BaseInputElement *arg1 = (AdaptiveCards::BaseInputElement *) 0 ; @@ -15986,6 +16075,48 @@ SWIGEXPORT void JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectMode } +SWIGEXPORT jstring JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_TextInput_1GetRegex(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jstring jresult = 0 ; + AdaptiveCards::TextInput *arg1 = (AdaptiveCards::TextInput *) 0 ; + std::shared_ptr< AdaptiveCards::TextInput const > *smartarg1 = 0 ; + std::string result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + + smartarg1 = *(std::shared_ptr< const AdaptiveCards::TextInput > **)&jarg1; + arg1 = (AdaptiveCards::TextInput *)(smartarg1 ? smartarg1->get() : 0); + result = ((AdaptiveCards::TextInput const *)arg1)->GetRegex(); + jresult = jenv->NewStringUTF((&result)->c_str()); + return jresult; +} + + +SWIGEXPORT void JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_TextInput_1SetRegex(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + AdaptiveCards::TextInput *arg1 = (AdaptiveCards::TextInput *) 0 ; + std::string *arg2 = 0 ; + std::shared_ptr< AdaptiveCards::TextInput > *smartarg1 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + + smartarg1 = *(std::shared_ptr< AdaptiveCards::TextInput > **)&jarg1; + arg1 = (AdaptiveCards::TextInput *)(smartarg1 ? smartarg1->get() : 0); + if(!jarg2) { + SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null string"); + return ; + } + const char *arg2_pstr = (const char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2_pstr) return ; + std::string arg2_str(arg2_pstr); + arg2 = &arg2_str; + jenv->ReleaseStringUTFChars(jarg2, arg2_pstr); + (arg1)->SetRegex((std::string const &)*arg2); +} + + SWIGEXPORT jlong JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_TextInput_1dynamic_1cast(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { jlong jresult = 0 ; AdaptiveCards::BaseCardElement *arg1 = (AdaptiveCards::BaseCardElement *) 0 ; @@ -17607,6 +17738,40 @@ SWIGEXPORT void JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectMode } +SWIGEXPORT jboolean JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_SubmitAction_1GetIgnoreInputValidation(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jboolean jresult = 0 ; + AdaptiveCards::SubmitAction *arg1 = (AdaptiveCards::SubmitAction *) 0 ; + std::shared_ptr< AdaptiveCards::SubmitAction const > *smartarg1 = 0 ; + bool result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + + smartarg1 = *(std::shared_ptr< const AdaptiveCards::SubmitAction > **)&jarg1; + arg1 = (AdaptiveCards::SubmitAction *)(smartarg1 ? smartarg1->get() : 0); + result = (bool)((AdaptiveCards::SubmitAction const *)arg1)->GetIgnoreInputValidation(); + jresult = (jboolean)result; + return jresult; +} + + +SWIGEXPORT void JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_SubmitAction_1SetIgnoreInputValidation(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jboolean jarg2) { + AdaptiveCards::SubmitAction *arg1 = (AdaptiveCards::SubmitAction *) 0 ; + bool arg2 ; + std::shared_ptr< AdaptiveCards::SubmitAction > *smartarg1 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + + smartarg1 = *(std::shared_ptr< AdaptiveCards::SubmitAction > **)&jarg1; + arg1 = (AdaptiveCards::SubmitAction *)(smartarg1 ? smartarg1->get() : 0); + arg2 = jarg2 ? true : false; + (arg1)->SetIgnoreInputValidation(arg2); +} + + SWIGEXPORT jlong JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_SubmitAction_1SerializeToJsonValue(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { jlong jresult = 0 ; AdaptiveCards::SubmitAction *arg1 = (AdaptiveCards::SubmitAction *) 0 ; @@ -18965,6 +19130,40 @@ SWIGEXPORT void JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectMode } +SWIGEXPORT jint JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_AdaptiveCard_1GetInputNecessityIndicators(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { + jint jresult = 0 ; + AdaptiveCards::AdaptiveCard *arg1 = (AdaptiveCards::AdaptiveCard *) 0 ; + std::shared_ptr< AdaptiveCards::AdaptiveCard const > *smartarg1 = 0 ; + AdaptiveCards::InputNecessityIndicators result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + + smartarg1 = *(std::shared_ptr< const AdaptiveCards::AdaptiveCard > **)&jarg1; + arg1 = (AdaptiveCards::AdaptiveCard *)(smartarg1 ? smartarg1->get() : 0); + result = (AdaptiveCards::InputNecessityIndicators)((AdaptiveCards::AdaptiveCard const *)arg1)->GetInputNecessityIndicators(); + jresult = (jint)result; + return jresult; +} + + +SWIGEXPORT void JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_AdaptiveCard_1SetInputNecessityIndicators(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jint jarg2) { + AdaptiveCards::AdaptiveCard *arg1 = (AdaptiveCards::AdaptiveCard *) 0 ; + AdaptiveCards::InputNecessityIndicators arg2 ; + std::shared_ptr< AdaptiveCards::AdaptiveCard > *smartarg1 = 0 ; + + (void)jenv; + (void)jcls; + (void)jarg1_; + + smartarg1 = *(std::shared_ptr< AdaptiveCards::AdaptiveCard > **)&jarg1; + arg1 = (AdaptiveCards::AdaptiveCard *)(smartarg1 ? smartarg1->get() : 0); + arg2 = (AdaptiveCards::InputNecessityIndicators)jarg2; + (arg1)->SetInputNecessityIndicators(arg2); +} + + SWIGEXPORT jlong JNICALL Java_io_adaptivecards_objectmodel_AdaptiveCardObjectModelJNI_AdaptiveCard_1GetSelectAction(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { jlong jresult = 0 ; AdaptiveCards::AdaptiveCard *arg1 = (AdaptiveCards::AdaptiveCard *) 0 ; diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCard.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCard.java index 81c66ec901..f6838ea2c1 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCard.java +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCard.java @@ -132,6 +132,14 @@ public void SetMinHeight(long value) { AdaptiveCardObjectModelJNI.AdaptiveCard_SetMinHeight(swigCPtr, this, value); } + public InputNecessityIndicators GetInputNecessityIndicators() { + return InputNecessityIndicators.swigToEnum(AdaptiveCardObjectModelJNI.AdaptiveCard_GetInputNecessityIndicators(swigCPtr, this)); + } + + public void SetInputNecessityIndicators(InputNecessityIndicators value) { + AdaptiveCardObjectModelJNI.AdaptiveCard_SetInputNecessityIndicators(swigCPtr, this, value.swigValue()); + } + public BaseActionElement GetSelectAction() { long cPtr = AdaptiveCardObjectModelJNI.AdaptiveCard_GetSelectAction(swigCPtr, this); return (cPtr == 0) ? null : new BaseActionElement(cPtr, true); diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCardObjectModel.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCardObjectModel.java index 0c4c458c9d..46dff4a9c0 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCardObjectModel.java +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCardObjectModel.java @@ -301,6 +301,18 @@ public static HeightType HeightTypeFromString(String t) { return HeightType.swigToEnum(AdaptiveCardObjectModelJNI.HeightTypeFromString(t)); } + public static SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__InputNecessityIndicators_t getInputNecessityIndicatorsEnum() { + return new SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__InputNecessityIndicators_t(AdaptiveCardObjectModelJNI.getInputNecessityIndicatorsEnum(), false); + } + + public static String InputNecessityIndicatorsToString(InputNecessityIndicators t) { + return AdaptiveCardObjectModelJNI.InputNecessityIndicatorsToString(t.swigValue()); + } + + public static InputNecessityIndicators InputNecessityIndicatorsFromString(String t) { + return InputNecessityIndicators.swigToEnum(AdaptiveCardObjectModelJNI.InputNecessityIndicatorsFromString(t)); + } + public static void HandleUnknownProperties(JsonValue json, SWIGTYPE_p_std__unordered_setT_std__string_t knownProperties, JsonValue unknownProperties) { AdaptiveCardObjectModelJNI.HandleUnknownProperties(JsonValue.getCPtr(json), json, SWIGTYPE_p_std__unordered_setT_std__string_t.getCPtr(knownProperties), JsonValue.getCPtr(unknownProperties), unknownProperties); } diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCardObjectModelJNI.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCardObjectModelJNI.java index 6a90218c51..fbc4aa5e40 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCardObjectModelJNI.java +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCardObjectModelJNI.java @@ -346,6 +346,9 @@ public class AdaptiveCardObjectModelJNI { public final static native long getHeightTypeEnum(); public final static native String HeightTypeToString(int jarg1); public final static native int HeightTypeFromString(String jarg1); + public final static native long getInputNecessityIndicatorsEnum(); + public final static native String InputNecessityIndicatorsToString(int jarg1); + public final static native int InputNecessityIndicatorsFromString(String jarg1); public final static native long AdaptiveBase64Util_Decode(String jarg1); public final static native String AdaptiveBase64Util_Encode(long jarg1, CharVector jarg1_); public final static native String AdaptiveBase64Util_ExtractDataFromUri(String jarg1); @@ -457,6 +460,8 @@ public class AdaptiveCardObjectModelJNI { public final static native long new_BaseInputElement__SWIG_1(int jarg1, int jarg2, boolean jarg3, int jarg4); public final static native boolean BaseInputElement_GetIsRequired(long jarg1, BaseInputElement jarg1_); public final static native void BaseInputElement_SetIsRequired(long jarg1, BaseInputElement jarg1_, boolean jarg2); + public final static native String BaseInputElement_GetErrorMessage(long jarg1, BaseInputElement jarg1_); + public final static native void BaseInputElement_SetErrorMessage(long jarg1, BaseInputElement jarg1_, String jarg2); public final static native long BaseInputElement_SerializeToJsonValue(long jarg1, BaseInputElement jarg1_); public final static native void delete_BaseInputElement(long jarg1); public final static native long new_BackgroundImage__SWIG_0(); @@ -715,6 +720,8 @@ public class AdaptiveCardObjectModelJNI { public final static native void TextInput_SetTextInputStyle(long jarg1, TextInput jarg1_, int jarg2); public final static native long TextInput_GetInlineAction(long jarg1, TextInput jarg1_); public final static native void TextInput_SetInlineAction(long jarg1, TextInput jarg1_, long jarg2, BaseActionElement jarg2_); + public final static native String TextInput_GetRegex(long jarg1, TextInput jarg1_); + public final static native void TextInput_SetRegex(long jarg1, TextInput jarg1_, String jarg2); public final static native long TextInput_dynamic_cast(long jarg1, BaseCardElement jarg1_); public final static native long new_TextInputParser__SWIG_0(); public final static native long new_TextInputParser__SWIG_1(long jarg1, TextInputParser jarg1_); @@ -792,6 +799,8 @@ public class AdaptiveCardObjectModelJNI { public final static native long SubmitAction_GetDataJsonAsValue(long jarg1, SubmitAction jarg1_); public final static native void SubmitAction_SetDataJson__SWIG_0(long jarg1, SubmitAction jarg1_, long jarg2, JsonValue jarg2_); public final static native void SubmitAction_SetDataJson__SWIG_1(long jarg1, SubmitAction jarg1_, String jarg2); + public final static native boolean SubmitAction_GetIgnoreInputValidation(long jarg1, SubmitAction jarg1_); + public final static native void SubmitAction_SetIgnoreInputValidation(long jarg1, SubmitAction jarg1_, boolean jarg2); public final static native long SubmitAction_SerializeToJsonValue(long jarg1, SubmitAction jarg1_); public final static native long SubmitAction_dynamic_cast(long jarg1, BaseActionElement jarg1_); public final static native long new_SubmitActionParser__SWIG_0(); @@ -850,6 +859,8 @@ public class AdaptiveCardObjectModelJNI { public final static native void AdaptiveCard_SetHeight(long jarg1, AdaptiveCard jarg1_, int jarg2); public final static native long AdaptiveCard_GetMinHeight(long jarg1, AdaptiveCard jarg1_); public final static native void AdaptiveCard_SetMinHeight(long jarg1, AdaptiveCard jarg1_, long jarg2); + public final static native int AdaptiveCard_GetInputNecessityIndicators(long jarg1, AdaptiveCard jarg1_); + public final static native void AdaptiveCard_SetInputNecessityIndicators(long jarg1, AdaptiveCard jarg1_, int jarg2); public final static native long AdaptiveCard_GetSelectAction(long jarg1, AdaptiveCard jarg1_); public final static native void AdaptiveCard_SetSelectAction(long jarg1, AdaptiveCard jarg1_, long jarg2, BaseActionElement jarg2_); public final static native long AdaptiveCard_GetBody__SWIG_0(long jarg1, AdaptiveCard jarg1_); diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCardSchemaKey.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCardSchemaKey.java index ae645e7c44..394f2757b2 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCardSchemaKey.java +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/AdaptiveCardSchemaKey.java @@ -52,6 +52,7 @@ public enum AdaptiveCardSchemaKey { DefaultPoster, ElementId, Emphasis, + ErrorMessage, ExtraLarge, FactSet, Facts, @@ -75,6 +76,7 @@ public enum AdaptiveCardSchemaKey { IconSize, IconUrl, Id, + IgnoreInputValidation, Image, ImageBaseUrl, ImageSet, @@ -84,6 +86,7 @@ public enum AdaptiveCardSchemaKey { InlineAction, Inlines, InlineTopMargin, + InputNecessityIndicators, IsMultiSelect, IsMultiline, IsRequired, @@ -117,6 +120,7 @@ public enum AdaptiveCardSchemaKey { Placeholder, PlayButton, Poster, + Regex, Repeat, RepeatHorizontally, RepeatVertically, diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/BaseInputElement.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/BaseInputElement.java index 34a5ce2347..3a434d23ee 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/BaseInputElement.java +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/BaseInputElement.java @@ -58,6 +58,14 @@ public void SetIsRequired(boolean isRequired) { AdaptiveCardObjectModelJNI.BaseInputElement_SetIsRequired(swigCPtr, this, isRequired); } + public String GetErrorMessage() { + return AdaptiveCardObjectModelJNI.BaseInputElement_GetErrorMessage(swigCPtr, this); + } + + public void SetErrorMessage(String errorMessage) { + AdaptiveCardObjectModelJNI.BaseInputElement_SetErrorMessage(swigCPtr, this, errorMessage); + } + public JsonValue SerializeToJsonValue() { return new JsonValue(AdaptiveCardObjectModelJNI.BaseInputElement_SerializeToJsonValue(swigCPtr, this), true); } diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/InputNecessityIndicators.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/InputNecessityIndicators.java new file mode 100644 index 0000000000..6520ae2ba3 --- /dev/null +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/InputNecessityIndicators.java @@ -0,0 +1,53 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.0 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package io.adaptivecards.objectmodel; + +public enum InputNecessityIndicators { + None, + RequiredInputs, + OptionalInputs; + + public final int swigValue() { + return swigValue; + } + + public static InputNecessityIndicators swigToEnum(int swigValue) { + InputNecessityIndicators[] swigValues = InputNecessityIndicators.class.getEnumConstants(); + if (swigValue < swigValues.length && swigValue >= 0 && swigValues[swigValue].swigValue == swigValue) + return swigValues[swigValue]; + for (InputNecessityIndicators swigEnum : swigValues) + if (swigEnum.swigValue == swigValue) + return swigEnum; + throw new IllegalArgumentException("No enum " + InputNecessityIndicators.class + " with value " + swigValue); + } + + @SuppressWarnings("unused") + private InputNecessityIndicators() { + this.swigValue = SwigNext.next++; + } + + @SuppressWarnings("unused") + private InputNecessityIndicators(int swigValue) { + this.swigValue = swigValue; + SwigNext.next = swigValue+1; + } + + @SuppressWarnings("unused") + private InputNecessityIndicators(InputNecessityIndicators swigEnum) { + this.swigValue = swigEnum.swigValue; + SwigNext.next = this.swigValue+1; + } + + private final int swigValue; + + private static class SwigNext { + private static int next = 0; + } +} + diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__InputNecessityIndicators_t.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__InputNecessityIndicators_t.java new file mode 100644 index 0000000000..53ce9ef678 --- /dev/null +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__InputNecessityIndicators_t.java @@ -0,0 +1,26 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.0 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +package io.adaptivecards.objectmodel; + +public class SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__InputNecessityIndicators_t { + private transient long swigCPtr; + + protected SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__InputNecessityIndicators_t(long cPtr, @SuppressWarnings("unused") boolean futureUse) { + swigCPtr = cPtr; + } + + protected SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__InputNecessityIndicators_t() { + swigCPtr = 0; + } + + protected static long getCPtr(SWIGTYPE_p_AdaptiveCards__EnumHelpers__EnumMappingT_AdaptiveCards__InputNecessityIndicators_t obj) { + return (obj == null) ? 0 : obj.swigCPtr; + } +} + diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SubmitAction.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SubmitAction.java index a29d1a23cc..c16460988a 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SubmitAction.java +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/SubmitAction.java @@ -66,6 +66,14 @@ public void SetDataJson(String value) { AdaptiveCardObjectModelJNI.SubmitAction_SetDataJson__SWIG_1(swigCPtr, this, value); } + public boolean GetIgnoreInputValidation() { + return AdaptiveCardObjectModelJNI.SubmitAction_GetIgnoreInputValidation(swigCPtr, this); + } + + public void SetIgnoreInputValidation(boolean value) { + AdaptiveCardObjectModelJNI.SubmitAction_SetIgnoreInputValidation(swigCPtr, this, value); + } + public JsonValue SerializeToJsonValue() { return new JsonValue(AdaptiveCardObjectModelJNI.SubmitAction_SerializeToJsonValue(swigCPtr, this), true); } diff --git a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/TextInput.java b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/TextInput.java index 09c8746d6d..8260402cd0 100644 --- a/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/TextInput.java +++ b/source/android/adaptivecards/src/main/java/io/adaptivecards/objectmodel/TextInput.java @@ -103,6 +103,14 @@ public void SetInlineAction(BaseActionElement action) { AdaptiveCardObjectModelJNI.TextInput_SetInlineAction(swigCPtr, this, BaseActionElement.getCPtr(action), action); } + public String GetRegex() { + return AdaptiveCardObjectModelJNI.TextInput_GetRegex(swigCPtr, this); + } + + public void SetRegex(String value) { + AdaptiveCardObjectModelJNI.TextInput_SetRegex(swigCPtr, this, value); + } + public static TextInput dynamic_cast(BaseCardElement baseCardElement) { long cPtr = AdaptiveCardObjectModelJNI.TextInput_dynamic_cast(BaseCardElement.getCPtr(baseCardElement), baseCardElement); return (cPtr == 0) ? null : new TextInput(cPtr, true); diff --git a/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/EverythingBagel.cpp b/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/EverythingBagel.cpp index c4f9aec113..39beeb13a2 100644 --- a/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/EverythingBagel.cpp +++ b/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/EverythingBagel.cpp @@ -52,6 +52,7 @@ namespace AdaptiveCardsSharedModelUnitTest Assert::IsTrue(ContainerStyle::None == everythingBagel.GetStyle()); Assert::AreEqual("1.0"s, everythingBagel.GetVersion()); Assert::IsTrue(VerticalContentAlignment::Top == everythingBagel.GetVerticalContentAlignment()); + Assert::IsTrue(everythingBagel.GetInputNecessityIndicators() == InputNecessityIndicators::RequiredInputs); } void ValidateTextBlock(const TextBlock &textBlock, FontType fontType, std::string id) @@ -172,6 +173,7 @@ namespace AdaptiveCardsSharedModelUnitTest Assert::AreEqual("Container_Action.Submit"s, action->GetTitle()); auto dataString = action->GetDataJson(); Assert::AreEqual("\"Container_data\"\n"s, dataString); + Assert::IsFalse(action->GetIgnoreInputValidation()); } auto items = container.GetItems(); @@ -237,11 +239,14 @@ namespace AdaptiveCardsSharedModelUnitTest Assert::IsTrue(Spacing::Small == textInput.GetSpacing()); Assert::IsTrue(TextInputStyle::Text == textInput.GetTextInputStyle()); Assert::AreEqual("Input.Text_value"s, textInput.GetValue()); + Assert::IsTrue(textInput.GetErrorMessage().empty()); + Assert::AreEqual("([A-Z])\\w+"s, textInput.GetRegex()); auto inlineAction = std::static_pointer_cast(textInput.GetInlineAction()); Assert::IsTrue((bool)inlineAction); Assert::AreEqual("Input.Text_Action.Submit"s, inlineAction->GetTitle()); Assert::AreEqual("https://adaptivecards.io/content/cats/1.png"s, inlineAction->GetIconUrl()); + Assert::IsFalse(inlineAction->GetIgnoreInputValidation()); } void ValidateInputNumber(const NumberInput &numberInput) @@ -250,11 +255,12 @@ namespace AdaptiveCardsSharedModelUnitTest Assert::AreEqual(CardElementTypeToString(CardElementType::NumberInput), numberInput.GetElementTypeString()); Assert::AreEqual("Input.Number_id"s, numberInput.GetId()); - Assert::IsFalse(numberInput.GetIsRequired()); + Assert::IsTrue(numberInput.GetIsRequired()); Assert::AreEqual(10, numberInput.GetMax()); Assert::AreEqual(5, numberInput.GetMin()); Assert::AreEqual(7, numberInput.GetValue()); Assert::AreEqual("Input.Number_placeholder"s, numberInput.GetPlaceholder()); + Assert::IsTrue(numberInput.GetErrorMessage().empty()); } void ValidateInputDate(const DateInput &dateInput) @@ -267,6 +273,8 @@ namespace AdaptiveCardsSharedModelUnitTest Assert::AreEqual("8/1/2018"s, dateInput.GetMin()); Assert::AreEqual("8/9/2018"s, dateInput.GetValue()); Assert::AreEqual("Input.Date_placeholder"s, dateInput.GetPlaceholder()); + Assert::IsFalse(dateInput.GetIsRequired()); + Assert::IsTrue(dateInput.GetErrorMessage().empty()); } void ValidateInputTime(const TimeInput &timeInput) @@ -278,6 +286,8 @@ namespace AdaptiveCardsSharedModelUnitTest Assert::AreEqual("10:00"s, timeInput.GetMin()); Assert::AreEqual("17:00"s, timeInput.GetMax()); Assert::AreEqual("13:00"s, timeInput.GetValue()); + Assert::IsTrue(timeInput.GetIsRequired()); + Assert::AreEqual("Input.Time.ErrorMessage"s, timeInput.GetErrorMessage()); } void ValidateInputToggle(const ToggleInput &toggleInput) @@ -290,6 +300,8 @@ namespace AdaptiveCardsSharedModelUnitTest Assert::AreEqual("Input.Toggle_on"s, toggleInput.GetValue()); Assert::AreEqual("Input.Toggle_on"s, toggleInput.GetValueOn()); Assert::AreEqual("Input.Toggle_off"s, toggleInput.GetValueOff()); + Assert::IsFalse(toggleInput.GetIsRequired()); + Assert::IsTrue(toggleInput.GetErrorMessage().empty()); } void ValidateTextBlockInInput(const TextBlock &textBlock) @@ -310,6 +322,8 @@ namespace AdaptiveCardsSharedModelUnitTest Assert::IsTrue(ChoiceSetStyle::Compact == choiceSet.GetChoiceSetStyle()); Assert::AreEqual("Input.Choice2,Input.Choice4"s, choiceSet.GetValue()); Assert::IsTrue(choiceSet.GetIsMultiSelect()); + Assert::IsFalse(choiceSet.GetIsRequired()); + Assert::IsTrue(choiceSet.GetErrorMessage().empty()); auto choices = choiceSet.GetChoices(); Assert::AreEqual(size_t{ 4 }, choices.size()); @@ -361,6 +375,7 @@ namespace AdaptiveCardsSharedModelUnitTest auto submitAction = actions.at(0); Assert::AreEqual("ActionSet.Action.Submit_id", submitAction->GetId().c_str()); + Assert::IsTrue(std::static_pointer_cast(submitAction)->GetIgnoreInputValidation()); auto openUrlAction = actions.at(1); Assert::AreEqual("ActionSet.Action.OpenUrl_id", openUrlAction->GetId().c_str()); @@ -399,6 +414,7 @@ namespace AdaptiveCardsSharedModelUnitTest auto selectAction = inlineTextElement->GetSelectAction(); Assert::IsTrue(selectAction != nullptr); Assert::IsTrue(ActionType::Submit == selectAction->GetElementType()); + Assert::IsFalse(std::static_pointer_cast(selectAction)->GetIgnoreInputValidation()); Assert::IsTrue(InlineElementType::TextRun == inlines[1]->GetInlineType()); Assert::AreEqual("TextRun"s, inlines[1]->GetInlineTypeString()); @@ -467,6 +483,7 @@ namespace AdaptiveCardsSharedModelUnitTest Assert::AreEqual("Action.Submit"s, submitAction->GetTitle()); //Logger::WriteMessage("Submit Data: '"s.append(submitAction->GetDataJson()).append("'").c_str()); Assert::AreEqual("{\"submitValue\":true}\n"s, submitAction->GetDataJson()); + Assert::IsFalse(submitAction->GetIgnoreInputValidation()); auto additionalProps = submitAction->GetAdditionalProperties(); Assert::IsTrue(additionalProps.empty()); diff --git a/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/EverythingBagel.h b/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/EverythingBagel.h index 42bf7d2190..3e73281e4c 100644 --- a/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/EverythingBagel.h +++ b/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/EverythingBagel.h @@ -2,4 +2,4 @@ // Licensed under the MIT License. #pragma once -#define EVERYTHING_JSON "{\"actions\":[{\"data\":{\"submitValue\":true},\"id\":\"Action.Submit_id\",\"title\":\"Action.Submit\",\"type\":\"Action.Submit\"},{\"card\":{\"actions\":[],\"backgroundImage\":{\"fillMode\":\"repeat\",\"horizontalAlignment\":\"right\",\"url\":\"https://adaptivecards.io/content/cats/1.png\",\"verticalAlignment\":\"center\"},\"body\":[{\"isSubtle\":true,\"text\":\"Action.ShowCard text\",\"type\":\"TextBlock\"}],\"lang\":\"en\",\"type\":\"AdaptiveCard\",\"version\":\"1.0\"},\"id\":\"Action.ShowCard_id\",\"title\":\"Action.ShowCard\",\"type\":\"Action.ShowCard\"}],\"backgroundImage\":\"https://adaptivecards.io/content/cats/1.png\",\"body\":[{\"id\":\"TextBlock_id\",\"italic\":true,\"maxLines\":1,\"strikethrough\":true,\"text\":\"TextBlock_text\",\"type\":\"TextBlock\"},{\"fontType\":\"Monospace\",\"id\":\"TextBlock_id_mono\",\"italic\":true,\"maxLines\":1,\"strikethrough\":true,\"text\":\"TextBlock_text\",\"type\":\"TextBlock\"},{\"id\":\"TextBlock_id_def\",\"italic\":true,\"maxLines\":1,\"strikethrough\":true,\"text\":\"TextBlock_text\",\"type\":\"TextBlock\"},{\"altText\":\"Image_altText\",\"horizontalAlignment\":\"center\",\"id\":\"Image_id\",\"isVisible\":false,\"selectAction\":{\"title\":\"Image_Action.OpenUrl\",\"type\":\"Action.OpenUrl\",\"url\":\"https://adaptivecards.io/\"},\"separator\":true,\"size\":\"Auto\",\"spacing\":\"none\",\"style\":\"person\",\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/1.png\"},{\"id\":\"Container_id\",\"items\":[{\"columns\":[{\"id\":\"Column_id1\",\"items\":[{\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/1.png\"}],\"style\":\"Default\",\"type\":\"Column\",\"width\":\"auto\"},{\"id\":\"Column_id2\",\"items\":[{\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/2.png\"}],\"style\":\"Emphasis\",\"type\":\"Column\",\"width\":\"20px\"},{\"id\":\"Column_id3\",\"items\":[{\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/3.png\"},{\"id\":\"Column3_TextBlock_id\",\"text\":\"Column3_TextBlock_text\",\"type\":\"TextBlock\"}],\"style\":\"Default\",\"type\":\"Column\",\"width\":\"stretch\"}],\"id\":\"ColumnSet_id\",\"separator\":true,\"spacing\":\"large\",\"type\":\"ColumnSet\"}],\"selectAction\":{\"data\":\"Container_data\",\"title\":\"Container_Action.Submit\",\"type\":\"Action.Submit\"},\"spacing\":\"medium\",\"style\":\"Default\",\"type\":\"Container\"},{\"facts\":[{\"title\":\"Topping\",\"value\":\"poppyseeds\"},{\"title\":\"Topping\",\"value\":\"onion flakes\"}],\"id\":\"FactSet_id\",\"type\":\"FactSet\"},{\"id\":\"ImageSet_id\",\"imageSize\":\"Auto\",\"images\":[{\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/1.png\"},{\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/2.png\"},{\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/3.png\"}],\"separator\":true,\"type\":\"ImageSet\"},{\"id\":\"Container_id_inputs\",\"items\":[{\"id\":\"Input.Text_id\",\"inlineAction\":{\"iconUrl\":\"https://adaptivecards.io/content/cats/1.png\",\"title\":\"Input.Text_Action.Submit\",\"type\":\"Action.Submit\"},\"maxLength\":10,\"placeholder\":\"Input.Text_placeholder\",\"spacing\":\"small\",\"style\":\"text\",\"type\":\"Input.Text\",\"value\":\"Input.Text_value\"},{\"id\":\"Input.Number_id\",\"max\":10,\"min\":5,\"placeholder\":\"Input.Number_placeholder\",\"type\":\"Input.Number\",\"value\":7},{\"id\":\"Input.Date_id\",\"max\":\"1/1/2020\",\"min\":\"8/1/2018\",\"placeholder\":\"Input.Date_placeholder\",\"type\":\"Input.Date\",\"value\":\"8/9/2018\"},{\"id\":\"Input.Time_id\",\"max\":\"17:00\",\"min\":\"10:00\",\"placeholder\":\"Input.Time_placeholder\",\"type\":\"Input.Time\",\"value\":\"13:00\"},{\"id\":\"Input.Toggle_id\",\"title\":\"Input.Toggle_title\",\"type\":\"Input.Toggle\",\"value\":\"Input.Toggle_on\",\"valueOff\":\"Input.Toggle_off\",\"valueOn\":\"Input.Toggle_on\"},{\"size\":\"Large\",\"text\":\"Everybody's got choices\",\"type\":\"TextBlock\",\"weight\":\"Bolder\"},{\"choices\":[{\"title\":\"Input.Choice1_title\",\"value\":\"Input.Choice1\"},{\"title\":\"Input.Choice2_title\",\"value\":\"Input.Choice2\"},{\"title\":\"Input.Choice3_title\",\"value\":\"Input.Choice3\"},{\"title\":\"Input.Choice4_title\",\"value\":\"Input.Choice4\"}],\"id\":\"Input.ChoiceSet_id\",\"isMultiSelect\":true,\"style\":\"Compact\",\"type\":\"Input.ChoiceSet\",\"value\":\"Input.Choice2,Input.Choice4\"}],\"type\":\"Container\"},{\"actions\":[{\"id\":\"ActionSet.Action.Submit_id\",\"title\":\"ActionSet.Action.Submit\",\"type\":\"Action.Submit\"},{\"id\":\"ActionSet.Action.OpenUrl_id\",\"title\":\"ActionSet.Action.OpenUrl\",\"type\":\"Action.OpenUrl\",\"url\":\"https://adaptivecards.io/\"}],\"type\":\"ActionSet\"},{\"horizontalAlignment\":\"right\",\"id\":\"RichTextBlock_id\",\"inlines\":[{\"color\":\"Dark\",\"fontType\":\"Monospace\",\"highlight\":true,\"isSubtle\":true,\"italic\":true,\"size\":\"Large\",\"strikethrough\":true,\"text\":\"This is a text run\",\"type\":\"TextRun\",\"weight\":\"Bolder\"},{\"selectAction\":{\"type\":\"Action.Submit\"},\"text\":\"This is another text run\",\"type\":\"TextRun\"},{\"text\":\"This is a text run specified as a string\",\"type\":\"TextRun\"}],\"type\":\"RichTextBlock\"}],\"fallbackText\":\"fallbackText\",\"lang\":\"en\",\"speak\":\"speak\",\"type\":\"AdaptiveCard\",\"version\":\"1.0\"}\n" +#define EVERYTHING_JSON "{\"actions\":[{\"data\":{\"submitValue\":true},\"id\":\"Action.Submit_id\",\"title\":\"Action.Submit\",\"type\":\"Action.Submit\"},{\"card\":{\"actions\":[],\"backgroundImage\":{\"fillMode\":\"repeat\",\"horizontalAlignment\":\"right\",\"url\":\"https://adaptivecards.io/content/cats/1.png\",\"verticalAlignment\":\"center\"},\"body\":[{\"isSubtle\":true,\"text\":\"Action.ShowCard text\",\"type\":\"TextBlock\"}],\"lang\":\"en\",\"type\":\"AdaptiveCard\",\"version\":\"1.0\"},\"id\":\"Action.ShowCard_id\",\"title\":\"Action.ShowCard\",\"type\":\"Action.ShowCard\"}],\"backgroundImage\":\"https://adaptivecards.io/content/cats/1.png\",\"body\":[{\"id\":\"TextBlock_id\",\"italic\":true,\"maxLines\":1,\"strikethrough\":true,\"text\":\"TextBlock_text\",\"type\":\"TextBlock\"},{\"fontType\":\"Monospace\",\"id\":\"TextBlock_id_mono\",\"italic\":true,\"maxLines\":1,\"strikethrough\":true,\"text\":\"TextBlock_text\",\"type\":\"TextBlock\"},{\"id\":\"TextBlock_id_def\",\"italic\":true,\"maxLines\":1,\"strikethrough\":true,\"text\":\"TextBlock_text\",\"type\":\"TextBlock\"},{\"altText\":\"Image_altText\",\"horizontalAlignment\":\"center\",\"id\":\"Image_id\",\"isVisible\":false,\"selectAction\":{\"title\":\"Image_Action.OpenUrl\",\"type\":\"Action.OpenUrl\",\"url\":\"https://adaptivecards.io/\"},\"separator\":true,\"size\":\"Auto\",\"spacing\":\"none\",\"style\":\"person\",\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/1.png\"},{\"id\":\"Container_id\",\"items\":[{\"columns\":[{\"id\":\"Column_id1\",\"items\":[{\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/1.png\"}],\"style\":\"Default\",\"type\":\"Column\",\"width\":\"auto\"},{\"id\":\"Column_id2\",\"items\":[{\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/2.png\"}],\"style\":\"Emphasis\",\"type\":\"Column\",\"width\":\"20px\"},{\"id\":\"Column_id3\",\"items\":[{\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/3.png\"},{\"id\":\"Column3_TextBlock_id\",\"text\":\"Column3_TextBlock_text\",\"type\":\"TextBlock\"}],\"style\":\"Default\",\"type\":\"Column\",\"width\":\"stretch\"}],\"id\":\"ColumnSet_id\",\"separator\":true,\"spacing\":\"large\",\"type\":\"ColumnSet\"}],\"selectAction\":{\"data\":\"Container_data\",\"title\":\"Container_Action.Submit\",\"type\":\"Action.Submit\"},\"spacing\":\"medium\",\"style\":\"Default\",\"type\":\"Container\"},{\"facts\":[{\"title\":\"Topping\",\"value\":\"poppyseeds\"},{\"title\":\"Topping\",\"value\":\"onion flakes\"}],\"id\":\"FactSet_id\",\"type\":\"FactSet\"},{\"id\":\"ImageSet_id\",\"imageSize\":\"Auto\",\"images\":[{\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/1.png\"},{\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/2.png\"},{\"type\":\"Image\",\"url\":\"https://adaptivecards.io/content/cats/3.png\"}],\"separator\":true,\"type\":\"ImageSet\"},{\"id\":\"Container_id_inputs\",\"items\":[{\"id\":\"Input.Text_id\",\"inlineAction\":{\"iconUrl\":\"https://adaptivecards.io/content/cats/1.png\",\"title\":\"Input.Text_Action.Submit\",\"type\":\"Action.Submit\"},\"maxLength\":10,\"placeholder\":\"Input.Text_placeholder\",\"regex\":\"([A-Z])\\\\w+\",\"spacing\":\"small\",\"style\":\"text\",\"type\":\"Input.Text\",\"value\":\"Input.Text_value\"},{\"id\":\"Input.Number_id\",\"isRequired\":true,\"max\":10,\"min\":5,\"placeholder\":\"Input.Number_placeholder\",\"type\":\"Input.Number\",\"value\":7},{\"id\":\"Input.Date_id\",\"max\":\"1/1/2020\",\"min\":\"8/1/2018\",\"placeholder\":\"Input.Date_placeholder\",\"type\":\"Input.Date\",\"value\":\"8/9/2018\"},{\"errorMessage\":\"Input.Time.ErrorMessage\",\"id\":\"Input.Time_id\",\"isRequired\":true,\"max\":\"17:00\",\"min\":\"10:00\",\"placeholder\":\"Input.Time_placeholder\",\"type\":\"Input.Time\",\"value\":\"13:00\"},{\"id\":\"Input.Toggle_id\",\"title\":\"Input.Toggle_title\",\"type\":\"Input.Toggle\",\"value\":\"Input.Toggle_on\",\"valueOff\":\"Input.Toggle_off\",\"valueOn\":\"Input.Toggle_on\"},{\"size\":\"Large\",\"text\":\"Everybody's got choices\",\"type\":\"TextBlock\",\"weight\":\"Bolder\"},{\"choices\":[{\"title\":\"Input.Choice1_title\",\"value\":\"Input.Choice1\"},{\"title\":\"Input.Choice2_title\",\"value\":\"Input.Choice2\"},{\"title\":\"Input.Choice3_title\",\"value\":\"Input.Choice3\"},{\"title\":\"Input.Choice4_title\",\"value\":\"Input.Choice4\"}],\"id\":\"Input.ChoiceSet_id\",\"isMultiSelect\":true,\"style\":\"Compact\",\"type\":\"Input.ChoiceSet\",\"value\":\"Input.Choice2,Input.Choice4\"}],\"type\":\"Container\"},{\"actions\":[{\"id\":\"ActionSet.Action.Submit_id\",\"ignoreInputValidation\":true,\"title\":\"ActionSet.Action.Submit\",\"type\":\"Action.Submit\"},{\"id\":\"ActionSet.Action.OpenUrl_id\",\"title\":\"ActionSet.Action.OpenUrl\",\"type\":\"Action.OpenUrl\",\"url\":\"https://adaptivecards.io/\"}],\"type\":\"ActionSet\"},{\"horizontalAlignment\":\"right\",\"id\":\"RichTextBlock_id\",\"inlines\":[{\"color\":\"Dark\",\"fontType\":\"Monospace\",\"highlight\":true,\"isSubtle\":true,\"italic\":true,\"size\":\"Large\",\"strikethrough\":true,\"text\":\"This is a text run\",\"type\":\"TextRun\",\"weight\":\"Bolder\"},{\"selectAction\":{\"type\":\"Action.Submit\"},\"text\":\"This is another text run\",\"type\":\"TextRun\"},{\"text\":\"This is a text run specified as a string\",\"type\":\"TextRun\"}],\"type\":\"RichTextBlock\"}],\"fallbackText\":\"fallbackText\",\"inputNecessityIndicators\":\"RequiredInputs\",\"lang\":\"en\",\"speak\":\"speak\",\"type\":\"AdaptiveCard\",\"version\":\"1.0\"}\n" diff --git a/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/EverythingBagel.json b/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/EverythingBagel.json index ddc48de35f..c7d0c9eea8 100644 --- a/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/EverythingBagel.json +++ b/source/shared/cpp/AdaptiveCardsSharedModel/AdaptiveCardsSharedModelUnitTest/EverythingBagel.json @@ -6,6 +6,7 @@ "fallbackText": "fallbackText", "speak": "speak", "lang": "en", + "inputNecessityIndicators": "requiredInputs", "body": [ { "type": "TextBlock", @@ -187,6 +188,8 @@ "style": "text", "value": "Input.Text_value", "spacing": "small", + "isRequired": false, + "regex": "([A-Z])\\w+", "inlineAction": { "type": "Action.Submit", "iconUrl": "https://adaptivecards.io/content/cats/1.png", @@ -199,7 +202,8 @@ "max": 10, "min": 5, "placeholder": "Input.Number_placeholder", - "value": 7 + "value": 7, + "isRequired": true }, { "type": "Input.Date", @@ -215,7 +219,9 @@ "min": "10:00", "max": "17:00", "value": "13:00", - "placeholder": "Input.Time_placeholder" + "placeholder": "Input.Time_placeholder", + "isRequired": true, + "errorMessage": "Input.Time.ErrorMessage" }, { "type": "Input.Toggle", @@ -268,7 +274,8 @@ { "type": "Action.Submit", "title": "ActionSet.Action.Submit", - "id": "ActionSet.Action.Submit_id" + "id": "ActionSet.Action.Submit_id", + "ignoreInputValidation": true }, { "type": "Action.OpenUrl", diff --git a/source/shared/cpp/ObjectModel/BaseActionElement.cpp b/source/shared/cpp/ObjectModel/BaseActionElement.cpp index c882d04fa0..032bdbc616 100644 --- a/source/shared/cpp/ObjectModel/BaseActionElement.cpp +++ b/source/shared/cpp/ObjectModel/BaseActionElement.cpp @@ -9,7 +9,8 @@ using namespace AdaptiveSharedNamespace; constexpr const char* const BaseActionElement::defaultStyle; -BaseActionElement::BaseActionElement(ActionType type) : m_style(BaseActionElement::defaultStyle), m_type(type) +BaseActionElement::BaseActionElement(ActionType type) : + m_style(BaseActionElement::defaultStyle), m_type(type) { SetTypeString(ActionTypeToString(type)); PopulateKnownPropertiesSet(); @@ -90,7 +91,9 @@ void BaseActionElement::GetResourceInformation(std::vector& baseElement) +void BaseActionElement::ParseJsonObject(AdaptiveSharedNamespace::ParseContext& context, + const Json::Value& json, + std::shared_ptr& baseElement) { baseElement = ParseUtil::GetActionFromJsonValue(context, json); } diff --git a/source/shared/cpp/ObjectModel/BaseInputElement.cpp b/source/shared/cpp/ObjectModel/BaseInputElement.cpp index ac8bfa7ece..d04c83a072 100644 --- a/source/shared/cpp/ObjectModel/BaseInputElement.cpp +++ b/source/shared/cpp/ObjectModel/BaseInputElement.cpp @@ -8,11 +8,13 @@ using namespace AdaptiveSharedNamespace; BaseInputElement::BaseInputElement(CardElementType elementType) : BaseCardElement(elementType), m_isRequired(false) { + PopulateKnownPropertiesSet(); } BaseInputElement::BaseInputElement(CardElementType elementType, Spacing spacing, bool separator, HeightType height) : BaseCardElement(elementType, spacing, separator, height), m_isRequired(false) { + PopulateKnownPropertiesSet(); } bool BaseInputElement::GetIsRequired() const @@ -25,6 +27,16 @@ void BaseInputElement::SetIsRequired(const bool value) m_isRequired = value; } +std::string BaseInputElement::GetErrorMessage() const +{ + return m_errorMessage; +} + +void BaseInputElement::SetErrorMessage(const std::string errorMessage) +{ + m_errorMessage = errorMessage; +} + Json::Value BaseInputElement::SerializeToJsonValue() const { Json::Value root = BaseCardElement::SerializeToJsonValue(); @@ -34,5 +46,16 @@ Json::Value BaseInputElement::SerializeToJsonValue() const root[AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::IsRequired)] = m_isRequired; } + if (!m_errorMessage.empty()) + { + root[AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::ErrorMessage)] = m_errorMessage; + } + return root; } + +void BaseInputElement::PopulateKnownPropertiesSet() +{ + m_knownProperties.insert({AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::IsRequired), + AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::ErrorMessage)}); +} diff --git a/source/shared/cpp/ObjectModel/BaseInputElement.h b/source/shared/cpp/ObjectModel/BaseInputElement.h index 5b7f1b8f68..a4a7fe68e7 100644 --- a/source/shared/cpp/ObjectModel/BaseInputElement.h +++ b/source/shared/cpp/ObjectModel/BaseInputElement.h @@ -19,13 +19,19 @@ namespace AdaptiveSharedNamespace bool GetIsRequired() const; void SetIsRequired(const bool isRequired); + std::string GetErrorMessage() const; + void SetErrorMessage(const std::string errorMessage); + Json::Value SerializeToJsonValue() const override; private: + void PopulateKnownPropertiesSet(); bool m_isRequired; + std::string m_errorMessage; }; - template std::shared_ptr BaseInputElement::Deserialize(ParseContext &context, const Json::Value& json) + template + std::shared_ptr BaseInputElement::Deserialize(ParseContext& context, const Json::Value& json) { std::shared_ptr baseInputElement = BaseCardElement::Deserialize(context, json); @@ -33,6 +39,7 @@ namespace AdaptiveSharedNamespace baseInputElement->SetId(ParseUtil::GetString(json, AdaptiveCardSchemaKey::Id, true)); baseInputElement->SetIsRequired(ParseUtil::GetBool(json, AdaptiveCardSchemaKey::IsRequired, false)); + baseInputElement->SetErrorMessage(ParseUtil::GetString(json, AdaptiveCardSchemaKey::ErrorMessage)); return baseInputElement; } diff --git a/source/shared/cpp/ObjectModel/Enums.cpp b/source/shared/cpp/ObjectModel/Enums.cpp index 0cd14c40f9..34b41926d3 100644 --- a/source/shared/cpp/ObjectModel/Enums.cpp +++ b/source/shared/cpp/ObjectModel/Enums.cpp @@ -49,6 +49,7 @@ namespace AdaptiveSharedNamespace {AdaptiveCardSchemaKey::DefaultPoster, "defaultPoster"}, {AdaptiveCardSchemaKey::ElementId, "elementId"}, {AdaptiveCardSchemaKey::Emphasis, "emphasis"}, + {AdaptiveCardSchemaKey::ErrorMessage, "errorMessage"}, {AdaptiveCardSchemaKey::ExtraLarge, "extraLarge"}, {AdaptiveCardSchemaKey::FactSet, "factSet"}, {AdaptiveCardSchemaKey::Facts, "facts"}, @@ -72,6 +73,7 @@ namespace AdaptiveSharedNamespace {AdaptiveCardSchemaKey::IconSize, "iconSize"}, {AdaptiveCardSchemaKey::IconUrl, "iconUrl"}, {AdaptiveCardSchemaKey::Id, "id"}, + {AdaptiveCardSchemaKey::IgnoreInputValidation, "ignoreInputValidation"}, {AdaptiveCardSchemaKey::Image, "image"}, {AdaptiveCardSchemaKey::ImageBaseUrl, "imageBaseUrl"}, {AdaptiveCardSchemaKey::ImageSet, "imageSet"}, @@ -81,6 +83,7 @@ namespace AdaptiveSharedNamespace {AdaptiveCardSchemaKey::InlineAction, "inlineAction"}, {AdaptiveCardSchemaKey::Inlines, "inlines"}, {AdaptiveCardSchemaKey::InlineTopMargin, "inlineTopMargin"}, + {AdaptiveCardSchemaKey::InputNecessityIndicators, "inputNecessityIndicators"}, {AdaptiveCardSchemaKey::IsMultiSelect, "isMultiSelect"}, {AdaptiveCardSchemaKey::IsMultiline, "isMultiline"}, {AdaptiveCardSchemaKey::IsRequired, "isRequired"}, @@ -114,6 +117,7 @@ namespace AdaptiveSharedNamespace {AdaptiveCardSchemaKey::Placeholder, "placeholder"}, {AdaptiveCardSchemaKey::PlayButton, "playButton"}, {AdaptiveCardSchemaKey::Poster, "poster"}, + {AdaptiveCardSchemaKey::Regex, "regex"}, {AdaptiveCardSchemaKey::Repeat, "repeat"}, {AdaptiveCardSchemaKey::RepeatHorizontally, "repeatHorizontally"}, {AdaptiveCardSchemaKey::RepeatVertically, "repeatVertically"}, @@ -318,4 +322,9 @@ namespace AdaptiveSharedNamespace DEFINE_ADAPTIVECARD_ENUM_DEFAULT(InlineElementType, InlineElementType::TextRun, { {InlineElementType::TextRun, "TextRun"}}); + + DEFINE_ADAPTIVECARD_ENUM_DEFAULT(InputNecessityIndicators, InputNecessityIndicators::None, { + {InputNecessityIndicators::None, "None"}, + {InputNecessityIndicators::RequiredInputs, "RequiredInputs"}, + {InputNecessityIndicators::OptionalInputs, "OptionalInputs"}}); } diff --git a/source/shared/cpp/ObjectModel/Enums.h b/source/shared/cpp/ObjectModel/Enums.h index 95eeb9fc1b..43f9dc6dfb 100644 --- a/source/shared/cpp/ObjectModel/Enums.h +++ b/source/shared/cpp/ObjectModel/Enums.h @@ -51,6 +51,7 @@ namespace AdaptiveSharedNamespace DefaultPoster, ElementId, Emphasis, + ErrorMessage, ExtraLarge, FactSet, Facts, @@ -74,6 +75,7 @@ namespace AdaptiveSharedNamespace IconSize, IconUrl, Id, + IgnoreInputValidation, Image, ImageBaseUrl, ImageSet, @@ -83,6 +85,7 @@ namespace AdaptiveSharedNamespace InlineAction, Inlines, InlineTopMargin, + InputNecessityIndicators, IsMultiSelect, IsMultiline, IsRequired, @@ -116,6 +119,7 @@ namespace AdaptiveSharedNamespace Placeholder, PlayButton, Poster, + Regex, Repeat, RepeatHorizontally, RepeatVertically, @@ -404,22 +408,22 @@ namespace AdaptiveSharedNamespace // allowed unless they have been explicitly declared (i.e. 0x0101 wouldn't be valid as it was not part of the declared values) enum class ContainerBleedDirection { - BleedRestricted = 0x0000, - BleedLeft = 0x0001, - BleedRight = 0x0010, - BleedLeftRight = 0x0011, - BleedUp = 0x0100, - BleedLeftUp = 0x0101, - BleedRightUp = 0x0110, - BleedLeftRightUp = 0x0111, - BleedDown = 0x1000, - BleedLeftDown = 0x1001, - BleedRightDown = 0x1010, + BleedRestricted = 0x0000, + BleedLeft = 0x0001, + BleedRight = 0x0010, + BleedLeftRight = 0x0011, + BleedUp = 0x0100, + BleedLeftUp = 0x0101, + BleedRightUp = 0x0110, + BleedLeftRightUp = 0x0111, + BleedDown = 0x1000, + BleedLeftDown = 0x1001, + BleedRightDown = 0x1010, BleedLeftRightDown = 0x1011, - BleedUpDown = 0x1100, - BleedLeftUpDown = 0x1101, - BleedRightUpDown = 0x1110, - BleedAll = 0x1111 + BleedUpDown = 0x1100, + BleedLeftUpDown = 0x1101, + BleedRightUpDown = 0x1110, + BleedAll = 0x1111 }; // Define bit operators so we can use ContainerBleedDirection as a bitmask @@ -472,4 +476,12 @@ namespace AdaptiveSharedNamespace Drop, Content }; + + enum class InputNecessityIndicators + { + None, + RequiredInputs, + OptionalInputs + }; + DECLARE_ADAPTIVECARD_ENUM(InputNecessityIndicators); } diff --git a/source/shared/cpp/ObjectModel/SharedAdaptiveCard.cpp b/source/shared/cpp/ObjectModel/SharedAdaptiveCard.cpp index 91f8d8a7d6..97e5674043 100644 --- a/source/shared/cpp/ObjectModel/SharedAdaptiveCard.cpp +++ b/source/shared/cpp/ObjectModel/SharedAdaptiveCard.cpp @@ -14,8 +14,8 @@ using namespace AdaptiveSharedNamespace; AdaptiveCard::AdaptiveCard() : - m_style(ContainerStyle::None), m_verticalContentAlignment(VerticalContentAlignment::Top), - m_height(HeightType::Auto), m_minHeight(0) + m_style(ContainerStyle::None), m_verticalContentAlignment(VerticalContentAlignment::Top), m_height(HeightType::Auto), + m_minHeight(0), m_inputNecessityIndicators(InputNecessityIndicators::None) { } @@ -30,7 +30,8 @@ AdaptiveCard::AdaptiveCard(std::string const& version, unsigned int minHeight) : m_version(version), m_fallbackText(fallbackText), m_speak(speak), m_style(style), m_language(language), - m_verticalContentAlignment(verticalContentAlignment), m_height(height), m_minHeight(minHeight) + m_verticalContentAlignment(verticalContentAlignment), m_height(height), m_minHeight(minHeight), + m_inputNecessityIndicators(InputNecessityIndicators::None) { m_backgroundImage = std::make_shared(backgroundImageUrl); } @@ -49,7 +50,7 @@ AdaptiveCard::AdaptiveCard(std::string const& version, m_version(version), m_fallbackText(fallbackText), m_speak(speak), m_style(style), m_language(language), m_verticalContentAlignment(verticalContentAlignment), m_height(height), m_minHeight(minHeight), m_body(body), - m_actions(actions) + m_actions(actions), m_inputNecessityIndicators(InputNecessityIndicators::None) { m_backgroundImage = std::make_shared(backgroundImageUrl); } @@ -65,7 +66,8 @@ AdaptiveCard::AdaptiveCard(std::string const& version, unsigned int minHeight) : m_version(version), m_fallbackText(fallbackText), m_backgroundImage(backgroundImage), m_speak(speak), m_style(style), - m_language(language), m_verticalContentAlignment(verticalContentAlignment), m_height(height), m_minHeight(minHeight) + m_language(language), m_verticalContentAlignment(verticalContentAlignment), m_height(height), m_minHeight(minHeight), + m_inputNecessityIndicators(InputNecessityIndicators::None) { } @@ -81,9 +83,9 @@ AdaptiveCard::AdaptiveCard(std::string const& version, std::vector>& body, std::vector>& actions) : m_version(version), - m_fallbackText(fallbackText), m_backgroundImage(backgroundImage), m_speak(speak), m_style(style), - m_language(language), m_verticalContentAlignment(verticalContentAlignment), m_height(height), - m_minHeight(minHeight), m_body(body), m_actions(actions) + m_fallbackText(fallbackText), m_backgroundImage(backgroundImage), m_speak(speak), m_style(style), m_language(language), + m_verticalContentAlignment(verticalContentAlignment), m_height(height), m_minHeight(minHeight), m_body(body), + m_actions(actions), m_inputNecessityIndicators(InputNecessityIndicators::None) { } @@ -222,6 +224,9 @@ std::shared_ptr AdaptiveCard::Deserialize(const Json::Value& json, // Parse optional selectAction result->SetSelectAction(ParseUtil::GetAction(context, json, AdaptiveCardSchemaKey::SelectAction, false)); + result->SetInputNecessityIndicators(ParseUtil::GetEnumValue( + json, AdaptiveCardSchemaKey::InputNecessityIndicators, InputNecessityIndicators::None, InputNecessityIndicatorsFromString)); + return std::make_shared(result, context.warnings); } @@ -298,6 +303,12 @@ Json::Value AdaptiveCard::SerializeToJsonValue() const root[AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::Height)] = HeightTypeToString(GetHeight()); } + if (m_inputNecessityIndicators != InputNecessityIndicators::None) + { + root[AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::InputNecessityIndicators)] = + InputNecessityIndicatorsToString(m_inputNecessityIndicators); + } + std::string bodyPropertyName = AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::Body); root[bodyPropertyName] = Json::Value(Json::arrayValue); for (const auto& cardElement : GetBody()) @@ -467,6 +478,16 @@ void AdaptiveCard::SetMinHeight(const unsigned int value) m_minHeight = value; } +InputNecessityIndicators AdaptiveCard::GetInputNecessityIndicators() const +{ + return m_inputNecessityIndicators; +} + +void AdaptiveCard::SetInputNecessityIndicators(const InputNecessityIndicators value) +{ + m_inputNecessityIndicators = value; +} + std::vector AdaptiveCard::GetResourceInformation() { auto resourceVector = std::vector(); diff --git a/source/shared/cpp/ObjectModel/SharedAdaptiveCard.h b/source/shared/cpp/ObjectModel/SharedAdaptiveCard.h index 7d566778f6..7c6053d526 100644 --- a/source/shared/cpp/ObjectModel/SharedAdaptiveCard.h +++ b/source/shared/cpp/ObjectModel/SharedAdaptiveCard.h @@ -79,6 +79,8 @@ namespace AdaptiveSharedNamespace void SetHeight(const HeightType value); unsigned int GetMinHeight() const; void SetMinHeight(const unsigned int value); + InputNecessityIndicators GetInputNecessityIndicators() const; + void SetInputNecessityIndicators(const InputNecessityIndicators value); std::shared_ptr GetSelectAction() const; void SetSelectAction(const std::shared_ptr action); @@ -145,6 +147,7 @@ namespace AdaptiveSharedNamespace VerticalContentAlignment m_verticalContentAlignment; HeightType m_height; unsigned int m_minHeight; + InputNecessityIndicators m_inputNecessityIndicators; std::vector> m_body; std::vector> m_actions; diff --git a/source/shared/cpp/ObjectModel/SubmitAction.cpp b/source/shared/cpp/ObjectModel/SubmitAction.cpp index d23d5ceb4b..39c5d09622 100644 --- a/source/shared/cpp/ObjectModel/SubmitAction.cpp +++ b/source/shared/cpp/ObjectModel/SubmitAction.cpp @@ -6,7 +6,7 @@ using namespace AdaptiveSharedNamespace; -SubmitAction::SubmitAction() : BaseActionElement(ActionType::Submit) +SubmitAction::SubmitAction() : BaseActionElement(ActionType::Submit), m_ignoreInputValidation(false) { PopulateKnownPropertiesSet(); } @@ -31,6 +31,16 @@ void SubmitAction::SetDataJson(const Json::Value& value) m_dataJson = value; } +bool SubmitAction::GetIgnoreInputValidation() const +{ + return m_ignoreInputValidation; +} + +void SubmitAction::SetIgnoreInputValidation(const bool value) +{ + m_ignoreInputValidation = value; +} + Json::Value SubmitAction::SerializeToJsonValue() const { Json::Value root = BaseActionElement::SerializeToJsonValue(); @@ -40,6 +50,11 @@ Json::Value SubmitAction::SerializeToJsonValue() const root[AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::Data)] = m_dataJson; } + if (m_ignoreInputValidation) + { + root[AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::IgnoreInputValidation)] = m_ignoreInputValidation; + } + return root; } @@ -48,6 +63,7 @@ std::shared_ptr SubmitActionParser::Deserialize(ParseContext& std::shared_ptr submitAction = BaseActionElement::Deserialize(context, json); submitAction->SetDataJson(ParseUtil::ExtractJsonValue(json, AdaptiveCardSchemaKey::Data)); + submitAction->SetIgnoreInputValidation(ParseUtil::GetBool(json, AdaptiveCardSchemaKey::IgnoreInputValidation, false)); return submitAction; } @@ -59,5 +75,6 @@ std::shared_ptr SubmitActionParser::DeserializeFromString(Par void SubmitAction::PopulateKnownPropertiesSet() { - m_knownProperties.insert({AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::Data)}); + m_knownProperties.insert({AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::Data), + AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::IgnoreInputValidation)}); } diff --git a/source/shared/cpp/ObjectModel/SubmitAction.h b/source/shared/cpp/ObjectModel/SubmitAction.h index d6765c6a2e..4097bd193b 100644 --- a/source/shared/cpp/ObjectModel/SubmitAction.h +++ b/source/shared/cpp/ObjectModel/SubmitAction.h @@ -23,12 +23,16 @@ namespace AdaptiveSharedNamespace void SetDataJson(const Json::Value& value); void SetDataJson(const std::string value); + virtual bool GetIgnoreInputValidation() const; + virtual void SetIgnoreInputValidation(const bool value); + Json::Value SerializeToJsonValue() const override; private: void PopulateKnownPropertiesSet() override; Json::Value m_dataJson; + bool m_ignoreInputValidation; }; class SubmitActionParser : public ActionElementParser diff --git a/source/shared/cpp/ObjectModel/TextInput.cpp b/source/shared/cpp/ObjectModel/TextInput.cpp index 37622dc662..acbf74a54f 100644 --- a/source/shared/cpp/ObjectModel/TextInput.cpp +++ b/source/shared/cpp/ObjectModel/TextInput.cpp @@ -48,6 +48,11 @@ Json::Value TextInput::SerializeToJsonValue() const BaseCardElement::SerializeSelectAction(m_inlineAction); } + if (!m_regex.empty()) + { + root[AdaptiveCardSchemaKeyToString(AdaptiveCardSchemaKey::Regex)] = m_regex; + } + return root; } @@ -111,6 +116,16 @@ void TextInput::SetInlineAction(const std::shared_ptr action) m_inlineAction = action; } +std::string TextInput::GetRegex() const +{ + return m_regex; +} + +void TextInput::SetRegex(const std::string& value) +{ + m_regex = value; +} + std::shared_ptr TextInputParser::Deserialize(ParseContext& context, const Json::Value& json) { ParseUtil::ExpectTypeString(json, CardElementType::TextInput); @@ -123,6 +138,7 @@ std::shared_ptr TextInputParser::Deserialize(ParseContext& cont textInput->SetTextInputStyle( ParseUtil::GetEnumValue(json, AdaptiveCardSchemaKey::Style, TextInputStyle::Text, TextInputStyleFromString)); textInput->SetInlineAction(ParseUtil::GetAction(context, json, AdaptiveCardSchemaKey::InlineAction, false)); + textInput->SetRegex(ParseUtil::GetString(json, AdaptiveCardSchemaKey::Regex)); return textInput; } diff --git a/source/shared/cpp/ObjectModel/TextInput.h b/source/shared/cpp/ObjectModel/TextInput.h index 76a21d53aa..5e0cf43343 100644 --- a/source/shared/cpp/ObjectModel/TextInput.h +++ b/source/shared/cpp/ObjectModel/TextInput.h @@ -38,11 +38,15 @@ namespace AdaptiveSharedNamespace std::shared_ptr GetInlineAction() const; void SetInlineAction(const std::shared_ptr action); + std::string GetRegex() const; + void SetRegex(const std::string& value); + private: void PopulateKnownPropertiesSet() override; std::string m_placeholder; std::string m_value; + std::string m_regex; bool m_isMultiline; unsigned int m_maxLength; TextInputStyle m_style; diff --git a/source/uwp/AdaptiveCardTestApp/AdaptiveCardTestApp.csproj b/source/uwp/AdaptiveCardTestApp/AdaptiveCardTestApp.csproj index bbcb2d3bf7..95243b4003 100644 --- a/source/uwp/AdaptiveCardTestApp/AdaptiveCardTestApp.csproj +++ b/source/uwp/AdaptiveCardTestApp/AdaptiveCardTestApp.csproj @@ -170,6 +170,9 @@ LinkedCards\v1.2\Elements\%(FileName) + + LinkedCards\v1.3\Elements\%(FileName) + LinkedCards\v1.0\Tests\%(FileName) diff --git a/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Action.Submit.IgnoreInputValidation.json b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Action.Submit.IgnoreInputValidation.json new file mode 100644 index 0000000000..672447bb19 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Action.Submit.IgnoreInputValidation.json @@ -0,0 +1 @@ +{"HostConfigHash":null,"CardHash":"0003a6c","Error":null} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Action.Submit.IgnoreInputValidation.png b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Action.Submit.IgnoreInputValidation.png new file mode 100644 index 0000000000..16ea15726e Binary files /dev/null and b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Action.Submit.IgnoreInputValidation.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.AdaptiveCard.InputNecessityIndicators.json b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.AdaptiveCard.InputNecessityIndicators.json new file mode 100644 index 0000000000..111ee07eba --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.AdaptiveCard.InputNecessityIndicators.json @@ -0,0 +1 @@ +{"HostConfigHash":null,"CardHash":"372809f","Error":null} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.AdaptiveCard.InputNecessityIndicators.png b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.AdaptiveCard.InputNecessityIndicators.png new file mode 100644 index 0000000000..edddaa65ed Binary files /dev/null and b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.AdaptiveCard.InputNecessityIndicators.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Input.Text.Regex.json b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Input.Text.Regex.json new file mode 100644 index 0000000000..5e53d5bf61 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Input.Text.Regex.json @@ -0,0 +1 @@ +{"HostConfigHash":null,"CardHash":"3ed1fbe","Error":null} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Input.Text.Regex.png b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Input.Text.Regex.png new file mode 100644 index 0000000000..e8d413d67f Binary files /dev/null and b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Input.Text.Regex.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Input.Text.isRequired.json b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Input.Text.isRequired.json new file mode 100644 index 0000000000..dab55889b5 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Input.Text.isRequired.json @@ -0,0 +1 @@ +{"HostConfigHash":null,"CardHash":"49d993a","Error":null} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Input.Text.isRequired.png b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Input.Text.isRequired.png new file mode 100644 index 0000000000..1a6f0650de Binary files /dev/null and b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Elements.Input.Text.isRequired.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Tests.AdaptiveCard.Version1.3.png b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Tests.AdaptiveCard.Version1.3.png index f204a56ecc..70a487e607 100644 Binary files a/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Tests.AdaptiveCard.Version1.3.png and b/source/uwp/AdaptiveCardTestApp/Expected/Fixed Size Non-Interactive.v1.3.Tests.AdaptiveCard.Version1.3.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Action.Submit.IgnoreInputValidation.json b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Action.Submit.IgnoreInputValidation.json new file mode 100644 index 0000000000..672447bb19 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Action.Submit.IgnoreInputValidation.json @@ -0,0 +1 @@ +{"HostConfigHash":null,"CardHash":"0003a6c","Error":null} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Action.Submit.IgnoreInputValidation.png b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Action.Submit.IgnoreInputValidation.png new file mode 100644 index 0000000000..dc34280cd8 Binary files /dev/null and b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Action.Submit.IgnoreInputValidation.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.AdaptiveCard.InputNecessityIndicators.json b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.AdaptiveCard.InputNecessityIndicators.json new file mode 100644 index 0000000000..111ee07eba --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.AdaptiveCard.InputNecessityIndicators.json @@ -0,0 +1 @@ +{"HostConfigHash":null,"CardHash":"372809f","Error":null} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.AdaptiveCard.InputNecessityIndicators.png b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.AdaptiveCard.InputNecessityIndicators.png new file mode 100644 index 0000000000..22eaf00f2d Binary files /dev/null and b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.AdaptiveCard.InputNecessityIndicators.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Input.Text.Regex.json b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Input.Text.Regex.json new file mode 100644 index 0000000000..5e53d5bf61 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Input.Text.Regex.json @@ -0,0 +1 @@ +{"HostConfigHash":null,"CardHash":"3ed1fbe","Error":null} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Input.Text.Regex.png b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Input.Text.Regex.png new file mode 100644 index 0000000000..d1c2d98119 Binary files /dev/null and b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Input.Text.Regex.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Input.Text.isRequired.json b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Input.Text.isRequired.json new file mode 100644 index 0000000000..dab55889b5 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Input.Text.isRequired.json @@ -0,0 +1 @@ +{"HostConfigHash":null,"CardHash":"49d993a","Error":null} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Input.Text.isRequired.png b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Input.Text.isRequired.png new file mode 100644 index 0000000000..828cacdbf5 Binary files /dev/null and b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Elements.Input.Text.isRequired.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Tests.AdaptiveCard.Version1.3.png b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Tests.AdaptiveCard.Version1.3.png index 7e4d5021a7..7e07196e35 100644 Binary files a/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Tests.AdaptiveCard.Version1.3.png and b/source/uwp/AdaptiveCardTestApp/Expected/No host config (default values).v1.3.Tests.AdaptiveCard.Version1.3.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Elements.Action.Submit.IgnoreInputValidation.0003a6c.json b/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Elements.Action.Submit.IgnoreInputValidation.0003a6c.json new file mode 100644 index 0000000000..f97bf67cb1 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Elements.Action.Submit.IgnoreInputValidation.0003a6c.json @@ -0,0 +1,33 @@ +{ + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "version": "1.3", + "body": [ + { + "type": "TextBlock", + "text": "Here are some required inputs" + }, + { + "type": "Input.Text", + "id": "input1", + "isRequired": true + }, + { + "type": "Input.Text", + "id": "input2", + "isRequired": true + } + ], + "actions": [ + { + "type": "Action.Submit", + "title": "OK", + "ignoreInputValidation": false + }, + { + "type": "Action.Submit", + "title": "Cancel", + "ignoreInputValidation": true + } + ] +} diff --git a/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Elements.AdaptiveCard.InputNecessityIndicators.372809f.json b/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Elements.AdaptiveCard.InputNecessityIndicators.372809f.json new file mode 100644 index 0000000000..23454aa61c --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Elements.AdaptiveCard.InputNecessityIndicators.372809f.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "inputNecessityIndicators": "optionalInputs", + "version": "1.3", + "body": [ + { + "type": "TextBlock", + "text": "This one is optional" + }, + { + "type": "Input.Text", + "id": "input1", + "isRequired": false + }, + { + "type": "TextBlock", + "text": "This one too" + }, + { + "type": "Input.Text", + "id": "input2" + }, + { + "type": "TextBlock", + "text": "This is required" + }, + { + "type": "Input.Text", + "id": "input3", + "isRequired": true + } + ], + "actions": [ + { + "type": "Action.Submit", + "title": "OK" + } + ] +} diff --git a/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Elements.Input.Text.Regex.3ed1fbe.json b/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Elements.Input.Text.Regex.3ed1fbe.json new file mode 100644 index 0000000000..93f66297a5 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Elements.Input.Text.Regex.3ed1fbe.json @@ -0,0 +1,34 @@ +{ + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "inputNecessityIndicators": "none", + "version": "1.3", + "body": [ + { + "type": "TextBlock", + "text": "This input is required and has a regex" + }, + { + "type": "Input.Text", + "id": "input1", + "isRequired": true, + "regEx": "([A-Z])\\w+" + }, + { + "type": "TextBlock", + "text": "This input is optional and has a regex" + }, + { + "type": "Input.Text", + "id": "input2", + "isRequired": false, + "regEx": "([A-Z])\\w+" + } + ], + "actions": [ + { + "type": "Action.Submit", + "title": "OK" + } + ] +} diff --git a/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Elements.Input.Text.isRequired.49d993a.json b/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Elements.Input.Text.isRequired.49d993a.json new file mode 100644 index 0000000000..cc1cffbcc5 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Elements.Input.Text.isRequired.49d993a.json @@ -0,0 +1,33 @@ +{ + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "inputNecessityIndicators": "requiredInputs", + "version": "1.3", + "body": [ + { + "type": "TextBlock", + "text": "Two required inputs and one optional" + }, + { + "type": "Input.Text", + "id": "input1", + "isRequired": true + }, + { + "type": "Input.Text", + "id": "input2", + "isRequired": true + }, + { + "type": "Input.Text", + "id": "input3", + "isRequired": false + } + ], + "actions": [ + { + "type": "Action.Submit", + "title": "OK" + } + ] +} diff --git a/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Tests.AdaptiveCard.Version1.3.c1e72aa.json b/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Tests.AdaptiveCard.Version1.3.c1e72aa.json deleted file mode 100644 index b288ca7676..0000000000 --- a/source/uwp/AdaptiveCardTestApp/Expected/SourceCards/v1.3.Tests.AdaptiveCard.Version1.3.c1e72aa.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", - "type": "AdaptiveCard", - "version": "1.3", - "fallbackText": "This card requires Adaptive Cards version 1.3.", - "body": [ - { - "type": "TextBlock", - "text": "This should not appear if renderer version < card version.", - "wrap": true - } - ] -} diff --git a/source/uwp/AdaptiveCardTestApp/Expected/SourceHostConfigs/testVariantHostConfig.569178d.json b/source/uwp/AdaptiveCardTestApp/Expected/SourceHostConfigs/testVariantHostConfig.569178d.json deleted file mode 100644 index 148b93e0cd..0000000000 --- a/source/uwp/AdaptiveCardTestApp/Expected/SourceHostConfigs/testVariantHostConfig.569178d.json +++ /dev/null @@ -1,288 +0,0 @@ -{ - "spacing": { - "small": 5, - "default": 10, - "medium": 15, - "large": 20, - "extraLarge": 25, - "padding": 15 - }, - "separator": { - "lineThickness": 2, - "lineColor": "#EEEEEE" - }, - "supportsInteractivity": true, - "fontTypes": { - "default": { - "fontFamily": "Times New Roman", - "fontSizes": { - "small": 12, - "default": 14, - "medium": 17, - "large": 21, - "extraLarge": 26 - }, - "fontWeights": { - "lighter": 100, - "default": 400, - "bolder": 1000 - } - }, - "monospace": { - "fontFamily": "Consolas", - "fontSizes": { - "small": 12, - "default": 14, - "medium": 17, - "large": 21, - "extraLarge": 26 - }, - "fontWeights": { - "lighter": 100, - "default": 400, - "bolder": 1000 - } - } - }, - "imageSizes": { - "small": 20, - "medium": 40, - "large": 80 - }, - "actions": { - "maxActions": 3, - "spacing": "small", - "buttonSpacing": 20, - "showCard": { - "actionMode": "popup", - "inlineTopMargin": 10 - }, - "actionsOrientation": "vertical", - "actionAlignment": "left" - }, - "adaptiveCard": { - "allowCustomStyle": false - }, - "imageSet": { - "imageSize": "medium", - "maxImageHeight": 100 - }, - "factSet": { - "title": { - "color": "attention", - "size": "small", - "isSubtle": false, - "weight": "bolder", - "wrap": true, - "maxWidth": 100 - }, - "value": { - "color": "warning", - "size": "small", - "isSubtle": false, - "weight": "lighter", - "wrap": true - }, - "spacing": 5 - }, - "containerStyles": { - "default": { - "foregroundColors": { - "default": { - "default": "#ffffffff", - "subtle": "#bfffffff" - }, - "dark": { - "default": "#ff201f1f", - "subtle": "#ff2d2c2c" - }, - "light": { - "default": "#ffffffff", - "subtle": "#bfffffff" - }, - "accent": { - "default": "#ffa6a7dc", - "subtle": "#ff8b8cc7" - }, - "good": { - "default": "#ff92c353", - "subtle": "#e592c353" - }, - "warning": { - "default": "#fff8d22a", - "subtle": "#e5f8d22a" - }, - "attention": { - "default": "#ffd74654", - "subtle": "#e5d74654" - } - }, - "backgroundColor": "#ff2d2c2c" - }, - "emphasis": { - "foregroundColors": { - "default": { - "default": "#ffffffff", - "subtle": "#bfffffff" - }, - "dark": { - "default": "#ff201f1f", - "subtle": "#ff2d2c2c" - }, - "light": { - "default": "#ffffffff", - "subtle": "#bfffffff" - }, - "accent": { - "default": "#ffa6a7dc", - "subtle": "#ff8b8cc7" - }, - "good": { - "default": "#ff92c353", - "subtle": "#e592c353" - }, - "warning": { - "default": "#fff8d22a", - "subtle": "#e5f8d22a" - }, - "attention": { - "default": "#ffd74654", - "subtle": "#e5d74654" - } - }, - "backgroundColor": "#ff292828" - }, - "accent": { - "backgroundColor": "#C7DEF9", - "foregroundColors": { - "default": { - "default": "#ff201f1f", - "subtle": "#ff2d2c2c" - }, - "dark": { - "default": "#ff201f1f", - "subtle": "#ff2d2c2c" - }, - "light": { - "default": "#ffffffff", - "subtle": "#bfffffff" - }, - "accent": { - "default": "#ffa6a7dc", - "subtle": "#ff8b8cc7" - }, - "good": { - "default": "#ff92c353", - "subtle": "#e592c353" - }, - "warning": { - "default": "#fff8d22a", - "subtle": "#e5f8d22a" - }, - "attention": { - "default": "#ffd74654", - "subtle": "#e5d74654" - } - } - }, - "good": { - "backgroundColor": "#CCFFCC", - "foregroundColors": { - "default": { - "default": "#ff201f1f", - "subtle": "#ff2d2c2c" - }, - "dark": { - "default": "#ff201f1f", - "subtle": "#ff2d2c2c" - }, - "light": { - "default": "#ffffffff", - "subtle": "#bfffffff" - }, - "accent": { - "default": "#ffa6a7dc", - "subtle": "#ff8b8cc7" - }, - "good": { - "default": "#ff92c353", - "subtle": "#e592c353" - }, - "warning": { - "default": "#fff8d22a", - "subtle": "#e5f8d22a" - }, - "attention": { - "default": "#ffd74654", - "subtle": "#e5d74654" - } - } - }, - "attention": { - "backgroundColor": "#FFC5B2", - "foregroundColors": { - "default": { - "default": "#ff201f1f", - "subtle": "#ff2d2c2c" - }, - "dark": { - "default": "#ff201f1f", - "subtle": "#ff2d2c2c" - }, - "light": { - "default": "#ffffffff", - "subtle": "#bfffffff" - }, - "accent": { - "default": "#ffa6a7dc", - "subtle": "#ff8b8cc7" - }, - "good": { - "default": "#ff92c353", - "subtle": "#e592c353" - }, - "warning": { - "default": "#fff8d22a", - "subtle": "#e5f8d22a" - }, - "attention": { - "default": "#ffd74654", - "subtle": "#e5d74654" - } - } - }, - "warning": { - "backgroundColor": "#FFE2B2", - "foregroundColors": { - "default": { - "default": "#ff201f1f", - "subtle": "#ff2d2c2c" - }, - "dark": { - "default": "#ff201f1f", - "subtle": "#ff2d2c2c" - }, - "light": { - "default": "#ffffffff", - "subtle": "#bfffffff" - }, - "accent": { - "default": "#ffa6a7dc", - "subtle": "#ff8b8cc7" - }, - "good": { - "default": "#ff92c353", - "subtle": "#e592c353" - }, - "warning": { - "default": "#fff8d22a", - "subtle": "#e5f8d22a" - }, - "attention": { - "default": "#ffd74654", - "subtle": "#e5d74654" - } - } - } - } -} diff --git a/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Action.Submit.IgnoreInputValidation.json b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Action.Submit.IgnoreInputValidation.json new file mode 100644 index 0000000000..9191270399 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Action.Submit.IgnoreInputValidation.json @@ -0,0 +1 @@ +{"HostConfigHash":"569178d","CardHash":"0003a6c","Error":null} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Action.Submit.IgnoreInputValidation.png b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Action.Submit.IgnoreInputValidation.png new file mode 100644 index 0000000000..d1261ed360 Binary files /dev/null and b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Action.Submit.IgnoreInputValidation.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.AdaptiveCard.InputNecessityIndicators.json b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.AdaptiveCard.InputNecessityIndicators.json new file mode 100644 index 0000000000..e4018585da --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.AdaptiveCard.InputNecessityIndicators.json @@ -0,0 +1 @@ +{"HostConfigHash":"569178d","CardHash":"372809f","Error":null} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.AdaptiveCard.InputNecessityIndicators.png b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.AdaptiveCard.InputNecessityIndicators.png new file mode 100644 index 0000000000..9f73797b98 Binary files /dev/null and b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.AdaptiveCard.InputNecessityIndicators.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Input.Text.Regex.json b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Input.Text.Regex.json new file mode 100644 index 0000000000..dfc7fa597d --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Input.Text.Regex.json @@ -0,0 +1 @@ +{"HostConfigHash":"569178d","CardHash":"3ed1fbe","Error":null} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Input.Text.Regex.png b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Input.Text.Regex.png new file mode 100644 index 0000000000..3e72ff3191 Binary files /dev/null and b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Input.Text.Regex.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Input.Text.isRequired.json b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Input.Text.isRequired.json new file mode 100644 index 0000000000..5e142a0521 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Input.Text.isRequired.json @@ -0,0 +1 @@ +{"HostConfigHash":"569178d","CardHash":"49d993a","Error":null} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Input.Text.isRequired.png b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Input.Text.isRequired.png new file mode 100644 index 0000000000..6a3b46e504 Binary files /dev/null and b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Elements.Input.Text.isRequired.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Tests.AdaptiveCard.Version1.3.png b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Tests.AdaptiveCard.Version1.3.png index 929738b638..3ac79ab3c7 100644 Binary files a/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Tests.AdaptiveCard.Version1.3.png and b/source/uwp/AdaptiveCardTestApp/Expected/testVariantHostConfig.v1.3.Tests.AdaptiveCard.Version1.3.png differ diff --git a/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Elements.Action.Submit.IgnoreInputValidationToJson.json b/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Elements.Action.Submit.IgnoreInputValidationToJson.json new file mode 100644 index 0000000000..e7972026c4 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Elements.Action.Submit.IgnoreInputValidationToJson.json @@ -0,0 +1 @@ +{"actions":[{"title":"OK","type":"Action.Submit"},{"ignoreInputValidation":true,"title":"Cancel","type":"Action.Submit"}],"body":[{"text":"Here are some required inputs","type":"TextBlock"},{"id":"input1","isRequired":true,"type":"Input.Text"},{"id":"input2","isRequired":true,"type":"Input.Text"}],"type":"AdaptiveCard","version":"1.3"} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Elements.AdaptiveCard.InputNecessityIndicatorsToJson.json b/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Elements.AdaptiveCard.InputNecessityIndicatorsToJson.json new file mode 100644 index 0000000000..7b3e78e5f3 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Elements.AdaptiveCard.InputNecessityIndicatorsToJson.json @@ -0,0 +1 @@ +{"actions":[{"title":"OK","type":"Action.Submit"}],"body":[{"text":"This one is optional","type":"TextBlock"},{"id":"input1","type":"Input.Text"},{"text":"This one too","type":"TextBlock"},{"id":"input2","type":"Input.Text"},{"text":"This is required","type":"TextBlock"},{"id":"input3","isRequired":true,"type":"Input.Text"}],"inputNecessityIndicators":"OptionalInputs","type":"AdaptiveCard","version":"1.3"} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Elements.Input.Text.RegexToJson.json b/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Elements.Input.Text.RegexToJson.json new file mode 100644 index 0000000000..f406a5e8b6 --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Elements.Input.Text.RegexToJson.json @@ -0,0 +1 @@ +{"actions":[{"title":"OK","type":"Action.Submit"}],"body":[{"text":"This input is required and has a regex","type":"TextBlock"},{"id":"input1","isRequired":true,"regEx":"([A-Z])\\w+","type":"Input.Text"},{"text":"This input is optional and has a regex","type":"TextBlock"},{"id":"input2","regEx":"([A-Z])\\w+","type":"Input.Text"}],"type":"AdaptiveCard","version":"1.3"} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Elements.Input.Text.isRequiredToJson.json b/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Elements.Input.Text.isRequiredToJson.json new file mode 100644 index 0000000000..e508689cec --- /dev/null +++ b/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Elements.Input.Text.isRequiredToJson.json @@ -0,0 +1 @@ +{"actions":[{"title":"OK","type":"Action.Submit"}],"body":[{"text":"Two required inputs and one optional","type":"TextBlock"},{"id":"input1","isRequired":true,"type":"Input.Text"},{"id":"input2","isRequired":true,"type":"Input.Text"},{"id":"input3","type":"Input.Text"}],"inputNecessityIndicators":"RequiredInputs","type":"AdaptiveCard","version":"1.3"} \ No newline at end of file diff --git a/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Tests.AdaptiveCard.Version1.3ToJson.json b/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Tests.AdaptiveCard.Version1.3ToJson.json index d58706d9ea..48812abe40 100644 --- a/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Tests.AdaptiveCard.Version1.3ToJson.json +++ b/source/uwp/AdaptiveCardTestApp/Expected/v1.3.Tests.AdaptiveCard.Version1.3ToJson.json @@ -1 +1 @@ -{"actions":[],"body":[{"text":"This card requires Adaptive Cards version 1.3.","type":"TextBlock"}],"fallbackText":"This card requires Adaptive Cards version 1.3.","speak":"This card requires Adaptive Cards version 1.3.","style":"Default","type":"AdaptiveCard","version":"1.0"} \ No newline at end of file +{"actions":[],"body":[{"text":"This should not appear if renderer version < card version.","type":"TextBlock","wrap":true}],"fallbackText":"This card requires Adaptive Cards version 1.3.","type":"AdaptiveCard","version":"1.3"} \ No newline at end of file diff --git a/source/uwp/Renderer/idl/AdaptiveCards.Rendering.Uwp.idl b/source/uwp/Renderer/idl/AdaptiveCards.Rendering.Uwp.idl index 9fcd706223..decb58333d 100644 --- a/source/uwp/Renderer/idl/AdaptiveCards.Rendering.Uwp.idl +++ b/source/uwp/Renderer/idl/AdaptiveCards.Rendering.Uwp.idl @@ -383,6 +383,16 @@ AdaptiveNamespaceStart All = Left | Right | Up | Down } BleedDirection; + [version(NTDDI_WIN10_RS1), flags] +#ifdef ADAPTIVE_CARDS_WINDOWS + [contract(InternalContract, 1)][internal] +#endif + typedef[v1_enum] enum InputNecessityIndicators { + None = 0, + RequiredInputs, + OptionalInputs + } InputNecessityIndicators; + declare { interface Windows.Foundation.Collections.IVector; @@ -622,6 +632,7 @@ AdaptiveNamespaceStart VerticalContentAlignment VerticalContentAlignment; HeightType Height; UInt32 MinHeight; + InputNecessityIndicators InputNecessityIndicators; Windows.Data.Json.JsonObject ToJson(); Windows.Foundation.Collections.IVectorView GetResourceInformation(); @@ -706,6 +717,7 @@ AdaptiveNamespaceStart interface IAdaptiveInputElement { Boolean IsRequired; + String ErrorMessage; }; [ @@ -793,6 +805,7 @@ AdaptiveNamespaceStart String Value; TextInputStyle TextInputStyle; IAdaptiveActionElement InlineAction; + String Regex; }; [ @@ -1462,6 +1475,7 @@ AdaptiveNamespaceStart AdaptiveSubmitAction(); Windows.Data.Json.JsonValue DataJson; + Boolean IgnoreInputValidation; }; [ diff --git a/source/uwp/Renderer/lib/AdaptiveCard.cpp b/source/uwp/Renderer/lib/AdaptiveCard.cpp index ba300c9938..b2ace11cd0 100644 --- a/source/uwp/Renderer/lib/AdaptiveCard.cpp +++ b/source/uwp/Renderer/lib/AdaptiveCard.cpp @@ -99,7 +99,7 @@ namespace AdaptiveNamespace try { ParseContext context(sharedModelElementParserRegistration, sharedModelActionParserRegistration); - const std::string c_rendererVersion = "1.2"; + const std::string c_rendererVersion = "1.3"; std::shared_ptr sharedParseResult = AdaptiveSharedNamespace::AdaptiveCard::DeserializeFromString(jsonString, c_rendererVersion, context); ComPtr adaptiveCard; @@ -163,6 +163,8 @@ namespace AdaptiveNamespace static_cast(sharedAdaptiveCard->GetVerticalContentAlignment()); m_height = static_cast(sharedAdaptiveCard->GetHeight()); m_minHeight = sharedAdaptiveCard->GetMinHeight(); + m_inputNecessityIndicators = + static_cast(sharedAdaptiveCard->GetInputNecessityIndicators()); auto backgroundImage = sharedAdaptiveCard->GetBackgroundImage(); if (backgroundImage != nullptr && !backgroundImage->GetUrl().empty()) @@ -275,6 +277,18 @@ namespace AdaptiveNamespace return S_OK; } + IFACEMETHODIMP AdaptiveCard::get_InputNecessityIndicators(ABI::AdaptiveNamespace::InputNecessityIndicators* inputNecessityIndicators) + { + *inputNecessityIndicators = m_inputNecessityIndicators; + return S_OK; + } + + IFACEMETHODIMP AdaptiveCard::put_InputNecessityIndicators(ABI::AdaptiveNamespace::InputNecessityIndicators inputNecessityIndicators) + { + m_inputNecessityIndicators = inputNecessityIndicators; + return S_OK; + } + HRESULT AdaptiveCard::ToJson(_COM_Outptr_ IJsonObject** result) { std::shared_ptr sharedModel; @@ -304,6 +318,7 @@ namespace AdaptiveNamespace adaptiveCard->SetStyle(static_cast(m_style)); adaptiveCard->SetVerticalContentAlignment(static_cast(m_verticalAlignment)); + adaptiveCard->SetInputNecessityIndicators(static_cast(m_inputNecessityIndicators)); if (m_selectAction != nullptr) { diff --git a/source/uwp/Renderer/lib/AdaptiveCard.h b/source/uwp/Renderer/lib/AdaptiveCard.h index 90810811ea..02a898b656 100644 --- a/source/uwp/Renderer/lib/AdaptiveCard.h +++ b/source/uwp/Renderer/lib/AdaptiveCard.h @@ -57,6 +57,9 @@ namespace AdaptiveNamespace IFACEMETHODIMP get_MinHeight(_Out_ UINT32* minHeight); IFACEMETHODIMP put_MinHeight(UINT32 minHeight); + IFACEMETHODIMP get_InputNecessityIndicators(_Out_ ABI::AdaptiveNamespace::InputNecessityIndicators* inputNecessityIndicators); + IFACEMETHODIMP put_InputNecessityIndicators(ABI::AdaptiveNamespace::InputNecessityIndicators inputNecessityIndicators); + IFACEMETHODIMP ToJson(_COM_Outptr_ ABI::Windows::Data::Json::IJsonObject** result); IFACEMETHODIMP GetResourceInformation( @@ -84,6 +87,7 @@ namespace AdaptiveNamespace Microsoft::WRL::ComPtr m_selectAction; ABI::AdaptiveNamespace::ContainerStyle m_style; ABI::AdaptiveNamespace::VerticalContentAlignment m_verticalAlignment; + ABI::AdaptiveNamespace::InputNecessityIndicators m_inputNecessityIndicators; }; class AdaptiveCardStaticsImpl WrlFinal : public Microsoft::WRL::AgileActivationFactory diff --git a/source/uwp/Renderer/lib/AdaptiveChoiceSetInput.h b/source/uwp/Renderer/lib/AdaptiveChoiceSetInput.h index a27e0305e1..f1011bb02f 100644 --- a/source/uwp/Renderer/lib/AdaptiveChoiceSetInput.h +++ b/source/uwp/Renderer/lib/AdaptiveChoiceSetInput.h @@ -53,6 +53,15 @@ namespace AdaptiveNamespace return AdaptiveInputElementBase::put_IsRequired(isRequired); } + IFACEMETHODIMP get_ErrorMessage(_Outptr_ HSTRING* errorMessage) + { + return AdaptiveInputElementBase::get_ErrorMessage(errorMessage); + } + IFACEMETHODIMP put_ErrorMessage(_In_ HSTRING errorMessage) + { + return AdaptiveInputElementBase::put_ErrorMessage(errorMessage); + } + // IAdaptiveCardElement IFACEMETHODIMP get_ElementType(_Out_ ABI::AdaptiveNamespace::ElementType* elementType); diff --git a/source/uwp/Renderer/lib/AdaptiveDateInput.h b/source/uwp/Renderer/lib/AdaptiveDateInput.h index 3471e886d6..c1a5df028b 100644 --- a/source/uwp/Renderer/lib/AdaptiveDateInput.h +++ b/source/uwp/Renderer/lib/AdaptiveDateInput.h @@ -46,6 +46,15 @@ namespace AdaptiveNamespace return AdaptiveInputElementBase::put_IsRequired(isRequired); } + IFACEMETHODIMP get_ErrorMessage(_Outptr_ HSTRING* errorMessage) + { + return AdaptiveInputElementBase::get_ErrorMessage(errorMessage); + } + IFACEMETHODIMP put_ErrorMessage(_In_ HSTRING errorMessage) + { + return AdaptiveInputElementBase::put_ErrorMessage(errorMessage); + } + // IAdaptiveCardElement IFACEMETHODIMP get_ElementType(_Out_ ABI::AdaptiveNamespace::ElementType* elementType); diff --git a/source/uwp/Renderer/lib/AdaptiveInputElement.cpp b/source/uwp/Renderer/lib/AdaptiveInputElement.cpp index cf191026d0..a2c7f9d19e 100644 --- a/source/uwp/Renderer/lib/AdaptiveInputElement.cpp +++ b/source/uwp/Renderer/lib/AdaptiveInputElement.cpp @@ -16,6 +16,8 @@ namespace AdaptiveNamespace { AdaptiveCardElementBase::InitializeBaseElement(std::static_pointer_cast(sharedModel)); m_isRequired = sharedModel->GetIsRequired(); + RETURN_IF_FAILED(UTF8ToHString(sharedModel->GetErrorMessage(), m_errorMessage.GetAddressOf())); + return S_OK; } @@ -31,10 +33,15 @@ namespace AdaptiveNamespace return S_OK; } + HRESULT AdaptiveInputElementBase::get_ErrorMessage(HSTRING* title) { return m_errorMessage.CopyTo(title); } + + HRESULT AdaptiveInputElementBase::put_ErrorMessage(HSTRING title) { return m_errorMessage.Set(title); } + HRESULT AdaptiveInputElementBase::SetSharedElementProperties(std::shared_ptr sharedCardElement) { AdaptiveCardElementBase::SetSharedElementProperties(sharedCardElement); sharedCardElement->SetIsRequired(m_isRequired); + sharedCardElement->SetErrorMessage(HStringToUTF8(m_errorMessage.Get())); return S_OK; } } diff --git a/source/uwp/Renderer/lib/AdaptiveInputElement.h b/source/uwp/Renderer/lib/AdaptiveInputElement.h index 467f344772..35eea6bf92 100644 --- a/source/uwp/Renderer/lib/AdaptiveInputElement.h +++ b/source/uwp/Renderer/lib/AdaptiveInputElement.h @@ -17,9 +17,13 @@ namespace AdaptiveNamespace IFACEMETHODIMP get_IsRequired(_Out_ boolean* isRequired); IFACEMETHODIMP put_IsRequired(boolean isRequired); + IFACEMETHODIMP get_ErrorMessage(_Outptr_ HSTRING* title); + IFACEMETHODIMP put_ErrorMessage(_In_ HSTRING title); + HRESULT SetSharedElementProperties(std::shared_ptr sharedCardElement); private: boolean m_isRequired; + Microsoft::WRL::Wrappers::HString m_errorMessage; }; } diff --git a/source/uwp/Renderer/lib/AdaptiveNumberInput.h b/source/uwp/Renderer/lib/AdaptiveNumberInput.h index 41d7f3c6cb..7076b7fc8a 100644 --- a/source/uwp/Renderer/lib/AdaptiveNumberInput.h +++ b/source/uwp/Renderer/lib/AdaptiveNumberInput.h @@ -46,6 +46,15 @@ namespace AdaptiveNamespace return AdaptiveInputElementBase::put_IsRequired(isRequired); } + IFACEMETHODIMP get_ErrorMessage(_Outptr_ HSTRING* errorMessage) + { + return AdaptiveInputElementBase::get_ErrorMessage(errorMessage); + } + IFACEMETHODIMP put_ErrorMessage(_In_ HSTRING errorMessage) + { + return AdaptiveInputElementBase::put_ErrorMessage(errorMessage); + } + // IAdaptiveCardElement IFACEMETHODIMP get_ElementType(_Out_ ABI::AdaptiveNamespace::ElementType* elementType); diff --git a/source/uwp/Renderer/lib/AdaptiveSubmitAction.cpp b/source/uwp/Renderer/lib/AdaptiveSubmitAction.cpp index f758d4a3bf..87940b3538 100644 --- a/source/uwp/Renderer/lib/AdaptiveSubmitAction.cpp +++ b/source/uwp/Renderer/lib/AdaptiveSubmitAction.cpp @@ -31,6 +31,8 @@ namespace AdaptiveNamespace RETURN_IF_FAILED(StringToJsonValue(sharedSubmitAction->GetDataJson(), &m_dataJson)); } + m_ignoreInputValidation = sharedSubmitAction->GetIgnoreInputValidation(); + InitializeBaseElement(std::static_pointer_cast(sharedSubmitAction)); return S_OK; } @@ -50,6 +52,18 @@ namespace AdaptiveNamespace return S_OK; } + HRESULT AdaptiveSubmitAction::get_IgnoreInputValidation(boolean* ignoreInputValidation) + { + *ignoreInputValidation = m_ignoreInputValidation; + return S_OK; + } + + HRESULT AdaptiveSubmitAction::put_IgnoreInputValidation(boolean ignoreInputValidation) + { + m_ignoreInputValidation = ignoreInputValidation; + return S_OK; + } + HRESULT AdaptiveSubmitAction::GetSharedModel(std::shared_ptr& sharedModel) try { std::shared_ptr submitAction = @@ -63,6 +77,8 @@ namespace AdaptiveNamespace submitAction->SetDataJson(jsonAsString); } + submitAction->SetIgnoreInputValidation(m_ignoreInputValidation); + sharedModel = submitAction; return S_OK; } diff --git a/source/uwp/Renderer/lib/AdaptiveSubmitAction.h b/source/uwp/Renderer/lib/AdaptiveSubmitAction.h index cfb794b544..683ef0b7bc 100644 --- a/source/uwp/Renderer/lib/AdaptiveSubmitAction.h +++ b/source/uwp/Renderer/lib/AdaptiveSubmitAction.h @@ -26,6 +26,9 @@ namespace AdaptiveNamespace IFACEMETHODIMP get_DataJson(_COM_Outptr_ ABI::Windows::Data::Json::IJsonValue** data); IFACEMETHODIMP put_DataJson(_In_ ABI::Windows::Data::Json::IJsonValue* data); + IFACEMETHODIMP get_IgnoreInputValidation(_Out_ boolean* ignoreInputValidation); + IFACEMETHODIMP put_IgnoreInputValidation(boolean ignoreInputValidation); + // IAdaptiveActionElement IFACEMETHODIMP get_ActionType(_Out_ ABI::AdaptiveNamespace::ActionType* actionType); IFACEMETHODIMP get_ActionTypeString(_Outptr_ HSTRING* value) @@ -95,6 +98,7 @@ namespace AdaptiveNamespace private: Microsoft::WRL::ComPtr m_dataJson; + boolean m_ignoreInputValidation; }; ActivatableClass(AdaptiveSubmitAction); diff --git a/source/uwp/Renderer/lib/AdaptiveTextInput.cpp b/source/uwp/Renderer/lib/AdaptiveTextInput.cpp index 64df6bc5b0..c519f41486 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextInput.cpp +++ b/source/uwp/Renderer/lib/AdaptiveTextInput.cpp @@ -31,6 +31,7 @@ namespace AdaptiveNamespace RETURN_IF_FAILED(UTF8ToHString(sharedTextInput->GetPlaceholder(), m_placeholder.GetAddressOf())); RETURN_IF_FAILED(UTF8ToHString(sharedTextInput->GetValue(), m_value.GetAddressOf())); + RETURN_IF_FAILED(UTF8ToHString(sharedTextInput->GetRegex(), m_regex.GetAddressOf())); m_maxLength = sharedTextInput->GetMaxLength(); m_isMultiline = sharedTextInput->GetIsMultiline(); m_textInputStyle = static_cast(sharedTextInput->GetTextInputStyle()); @@ -77,29 +78,33 @@ namespace AdaptiveNamespace return S_OK; } - IFACEMETHODIMP AdaptiveTextInput::get_TextInputStyle(_Out_ ABI::AdaptiveNamespace::TextInputStyle* textInputStyle) + HRESULT AdaptiveTextInput::get_TextInputStyle(_Out_ ABI::AdaptiveNamespace::TextInputStyle* textInputStyle) { *textInputStyle = m_textInputStyle; return S_OK; } - IFACEMETHODIMP AdaptiveTextInput::put_TextInputStyle(ABI::AdaptiveNamespace::TextInputStyle textInputStyle) + HRESULT AdaptiveTextInput::put_TextInputStyle(ABI::AdaptiveNamespace::TextInputStyle textInputStyle) { m_textInputStyle = textInputStyle; return S_OK; } - IFACEMETHODIMP AdaptiveTextInput::get_InlineAction(_COM_Outptr_ IAdaptiveActionElement** action) + HRESULT AdaptiveTextInput::get_InlineAction(_COM_Outptr_ IAdaptiveActionElement** action) { return m_inlineAction.CopyTo(action); } - IFACEMETHODIMP AdaptiveTextInput::put_InlineAction(_In_ IAdaptiveActionElement* action) + HRESULT AdaptiveTextInput::put_InlineAction(_In_ IAdaptiveActionElement* action) { m_inlineAction = action; return S_OK; } + HRESULT AdaptiveTextInput::get_Regex(HSTRING* regex) { return m_regex.CopyTo(regex); } + + HRESULT AdaptiveTextInput::put_Regex(HSTRING regex) { return m_regex.Set(regex); } + HRESULT AdaptiveTextInput::get_ElementType(_Out_ ElementType* elementType) { *elementType = ElementType::TextInput; @@ -118,6 +123,7 @@ namespace AdaptiveNamespace textInput->SetPlaceholder(HStringToUTF8(m_placeholder.Get())); textInput->SetValue(HStringToUTF8(m_value.Get())); + textInput->SetRegex(HStringToUTF8(m_regex.Get())); if (m_inlineAction != nullptr) { diff --git a/source/uwp/Renderer/lib/AdaptiveTextInput.h b/source/uwp/Renderer/lib/AdaptiveTextInput.h index 9e69b90ba8..381b008ef5 100644 --- a/source/uwp/Renderer/lib/AdaptiveTextInput.h +++ b/source/uwp/Renderer/lib/AdaptiveTextInput.h @@ -42,6 +42,9 @@ namespace AdaptiveNamespace IFACEMETHODIMP get_InlineAction(_COM_Outptr_ ABI::AdaptiveNamespace::IAdaptiveActionElement** action); IFACEMETHODIMP put_InlineAction(_In_ ABI::AdaptiveNamespace::IAdaptiveActionElement* action); + IFACEMETHODIMP get_Regex(_Outptr_ HSTRING* regex); + IFACEMETHODIMP put_Regex(_In_ HSTRING regex); + // IAdaptiveInputElement IFACEMETHODIMP get_IsRequired(_Out_ boolean* isRequired) { @@ -52,6 +55,15 @@ namespace AdaptiveNamespace return AdaptiveInputElementBase::put_IsRequired(isRequired); } + IFACEMETHODIMP get_ErrorMessage(_Outptr_ HSTRING* errorMessage) + { + return AdaptiveInputElementBase::get_ErrorMessage(errorMessage); + } + IFACEMETHODIMP put_ErrorMessage(_In_ HSTRING errorMessage) + { + return AdaptiveInputElementBase::put_ErrorMessage(errorMessage); + } + // IAdaptiveCardElement IFACEMETHODIMP get_ElementType(_Out_ ABI::AdaptiveNamespace::ElementType* elementType); @@ -144,6 +156,7 @@ namespace AdaptiveNamespace boolean m_isMultiline; ABI::AdaptiveNamespace::TextInputStyle m_textInputStyle; Microsoft::WRL::ComPtr m_inlineAction; + Microsoft::WRL::Wrappers::HString m_regex; }; ActivatableClass(AdaptiveTextInput); diff --git a/source/uwp/Renderer/lib/AdaptiveTimeInput.h b/source/uwp/Renderer/lib/AdaptiveTimeInput.h index f91b6bf8b4..df6b845b3c 100644 --- a/source/uwp/Renderer/lib/AdaptiveTimeInput.h +++ b/source/uwp/Renderer/lib/AdaptiveTimeInput.h @@ -46,6 +46,15 @@ namespace AdaptiveNamespace return AdaptiveInputElementBase::put_IsRequired(isRequired); } + IFACEMETHODIMP get_ErrorMessage(_Outptr_ HSTRING* errorMessage) + { + return AdaptiveInputElementBase::get_ErrorMessage(errorMessage); + } + IFACEMETHODIMP put_ErrorMessage(_In_ HSTRING errorMessage) + { + return AdaptiveInputElementBase::put_ErrorMessage(errorMessage); + } + // IAdaptiveCardElement IFACEMETHODIMP get_ElementType(_Out_ ABI::AdaptiveNamespace::ElementType* elementType); diff --git a/source/uwp/Renderer/lib/AdaptiveToggleInput.h b/source/uwp/Renderer/lib/AdaptiveToggleInput.h index 8f191be838..75c1c25b84 100644 --- a/source/uwp/Renderer/lib/AdaptiveToggleInput.h +++ b/source/uwp/Renderer/lib/AdaptiveToggleInput.h @@ -49,6 +49,15 @@ namespace AdaptiveNamespace return AdaptiveInputElementBase::put_IsRequired(isRequired); } + IFACEMETHODIMP get_ErrorMessage(_Outptr_ HSTRING* errorMessage) + { + return AdaptiveInputElementBase::get_ErrorMessage(errorMessage); + } + IFACEMETHODIMP put_ErrorMessage(_In_ HSTRING errorMessage) + { + return AdaptiveInputElementBase::put_ErrorMessage(errorMessage); + } + // IAdaptiveCardElement IFACEMETHODIMP get_ElementType(_Out_ ABI::AdaptiveNamespace::ElementType* elementType); diff --git a/source/uwp/UWPUnitTests/ObjectModelTests.cs b/source/uwp/UWPUnitTests/ObjectModelTests.cs index e56ac6c225..dab265bf00 100644 --- a/source/uwp/UWPUnitTests/ObjectModelTests.cs +++ b/source/uwp/UWPUnitTests/ObjectModelTests.cs @@ -21,6 +21,7 @@ public void Card() }, FallbackText = "Fallback Text", Height = HeightType.Stretch, + InputNecessityIndicators = InputNecessityIndicators.RequiredInputs, Language = "en", Speak = "This is a card", Style = ContainerStyle.Emphasis, @@ -31,6 +32,7 @@ public void Card() Assert.AreEqual("https://www.stuff.com/background.jpg", card.BackgroundImage.Url); Assert.AreEqual("Fallback Text", card.FallbackText); Assert.AreEqual(HeightType.Stretch, card.Height); + Assert.AreEqual(InputNecessityIndicators.RequiredInputs, card.InputNecessityIndicators); Assert.AreEqual("en", card.Language); Assert.AreEqual("This is a card", card.Speak); Assert.AreEqual(ContainerStyle.Emphasis, card.Style); @@ -75,7 +77,7 @@ public void Card() Assert.AreEqual("Submit Two", card.Actions[1].Title); var jsonString = card.ToJson().ToString(); - Assert.AreEqual("{\"actions\":[{\"title\":\"Submit One\",\"type\":\"Action.Submit\"},{\"title\":\"Submit Two\",\"type\":\"Action.Submit\"}],\"backgroundImage\":\"https://www.stuff.com/background.jpg\",\"body\":[{\"text\":\"This is a text block\",\"type\":\"TextBlock\"},{\"text\":\"This is another text block\",\"type\":\"TextBlock\"}],\"fallbackText\":\"Fallback Text\",\"height\":\"Stretch\",\"lang\":\"en\",\"speak\":\"This is a card\",\"style\":\"Emphasis\",\"type\":\"AdaptiveCard\",\"version\":\"1.3\",\"verticalContentAlignment\":\"Center\"}", jsonString); + Assert.AreEqual("{\"actions\":[{\"title\":\"Submit One\",\"type\":\"Action.Submit\"},{\"title\":\"Submit Two\",\"type\":\"Action.Submit\"}],\"backgroundImage\":\"https://www.stuff.com/background.jpg\",\"body\":[{\"text\":\"This is a text block\",\"type\":\"TextBlock\"},{\"text\":\"This is another text block\",\"type\":\"TextBlock\"}],\"fallbackText\":\"Fallback Text\",\"height\":\"Stretch\",\"inputNecessityIndicators\":\"RequiredInputs\",\"lang\":\"en\",\"speak\":\"This is a card\",\"style\":\"Emphasis\",\"type\":\"AdaptiveCard\",\"version\":\"1.3\",\"verticalContentAlignment\":\"Center\"}", jsonString); } public void ValidateBaseElementProperties( @@ -435,6 +437,8 @@ public void TextInput() MaxLength = 5, Placeholder = "Placeholder", Value = "Value", + ErrorMessage = "Text Input Error Message", + Regex = "([A-Z])\\w+", TextInputStyle = TextInputStyle.Email, Height = HeightType.Stretch, Id = "TextInputId", @@ -445,6 +449,9 @@ public void TextInput() ValidateBaseElementProperties(textInput, "TextInputId", false, true, Spacing.Medium, HeightType.Stretch); + Assert.IsFalse(textInput.IsRequired); + Assert.AreEqual("Text Input Error Message", textInput.ErrorMessage); + Assert.AreEqual("([A-Z])\\w+", textInput.Regex); Assert.AreEqual(true, textInput.IsMultiline); Assert.AreEqual(5, textInput.MaxLength); Assert.AreEqual("Placeholder", textInput.Placeholder); @@ -459,7 +466,7 @@ public void TextInput() Assert.AreEqual("Inline Action", textInput.InlineAction.Title); var jsonString = textInput.ToJson().ToString(); - Assert.AreEqual("{\"height\":\"Stretch\",\"id\":\"TextInputId\",\"inlineAction\":{\"title\":\"Inline Action\",\"type\":\"Action.Submit\"},\"isMultiline\":true,\"isVisible\":false,\"maxLength\":5,\"placeholder\":\"Placeholder\",\"separator\":true,\"spacing\":\"medium\",\"style\":\"Email\",\"type\":\"Input.Text\",\"value\":\"Value\"}", jsonString); + Assert.AreEqual("{\"errorMessage\":\"Text Input Error Message\",\"height\":\"Stretch\",\"id\":\"TextInputId\",\"inlineAction\":{\"title\":\"Inline Action\",\"type\":\"Action.Submit\"},\"isMultiline\":true,\"isVisible\":false,\"maxLength\":5,\"placeholder\":\"Placeholder\",\"regex\":\"([A-Z])\\\\w+\",\"separator\":true,\"spacing\":\"medium\",\"style\":\"Email\",\"type\":\"Input.Text\",\"value\":\"Value\"}", jsonString); } [TestMethod] @@ -471,6 +478,8 @@ public void NumberInput() Min = 40, Placeholder = "Placeholder", Value = 42, + IsRequired = false, + ErrorMessage = "Number Input Error Message", Height = HeightType.Stretch, Id = "NumberInputId", IsVisible = false, @@ -480,13 +489,15 @@ public void NumberInput() ValidateBaseElementProperties(numberInput, "NumberInputId", false, true, Spacing.Medium, HeightType.Stretch); + Assert.IsFalse(numberInput.IsRequired); + Assert.AreEqual("Number Input Error Message", numberInput.ErrorMessage); Assert.AreEqual(50, numberInput.Max); Assert.AreEqual(40, numberInput.Min); Assert.AreEqual("Placeholder", numberInput.Placeholder); Assert.AreEqual(42, numberInput.Value); var jsonString = numberInput.ToJson().ToString(); - Assert.AreEqual("{\"height\":\"Stretch\",\"id\":\"NumberInputId\",\"isVisible\":false,\"max\":50,\"min\":40,\"placeholder\":\"Placeholder\",\"separator\":true,\"spacing\":\"medium\",\"type\":\"Input.Number\",\"value\":42}", jsonString); + Assert.AreEqual("{\"errorMessage\":\"Number Input Error Message\",\"height\":\"Stretch\",\"id\":\"NumberInputId\",\"isVisible\":false,\"max\":50,\"min\":40,\"placeholder\":\"Placeholder\",\"separator\":true,\"spacing\":\"medium\",\"type\":\"Input.Number\",\"value\":42}", jsonString); } [TestMethod] @@ -494,26 +505,30 @@ public void DateInput() { AdaptiveDateInput dateInput = new AdaptiveDateInput { + ErrorMessage = "Date Input Error Message", Max = "2019-01-14", Min = "2017-01-14", Placeholder = "Placeholder", - Value = "2018-01-14", Height = HeightType.Stretch, Id = "DateInputId", + IsRequired = true, IsVisible = false, Separator = true, Spacing = Spacing.Medium, + Value = "2018-01-14", }; ValidateBaseElementProperties(dateInput, "DateInputId", false, true, Spacing.Medium, HeightType.Stretch); + Assert.IsTrue(dateInput.IsRequired); + Assert.AreEqual("Date Input Error Message", dateInput.ErrorMessage); Assert.AreEqual("2019-01-14", dateInput.Max); Assert.AreEqual("2017-01-14", dateInput.Min); Assert.AreEqual("Placeholder", dateInput.Placeholder); Assert.AreEqual("2018-01-14", dateInput.Value); var jsonString = dateInput.ToJson().ToString(); - Assert.AreEqual("{\"height\":\"Stretch\",\"id\":\"DateInputId\",\"isVisible\":false,\"max\":\"2019-01-14\",\"min\":\"2017-01-14\",\"placeholder\":\"Placeholder\",\"separator\":true,\"spacing\":\"medium\",\"type\":\"Input.Date\",\"value\":\"2018-01-14\"}", jsonString); + Assert.AreEqual("{\"errorMessage\":\"Date Input Error Message\",\"height\":\"Stretch\",\"id\":\"DateInputId\",\"isRequired\":true,\"isVisible\":false,\"max\":\"2019-01-14\",\"min\":\"2017-01-14\",\"placeholder\":\"Placeholder\",\"separator\":true,\"spacing\":\"medium\",\"type\":\"Input.Date\",\"value\":\"2018-01-14\"}", jsonString); } [TestMethod] @@ -534,6 +549,9 @@ public void TimeInput() ValidateBaseElementProperties(timeInput, "TimeInputId", false, true, Spacing.Medium, HeightType.Stretch); + Assert.IsFalse(timeInput.IsRequired); + Assert.IsTrue(timeInput.ErrorMessage.Length == 0); + Assert.AreEqual("05:00", timeInput.Max); Assert.AreEqual("01:00", timeInput.Min); Assert.AreEqual("Placeholder", timeInput.Placeholder); @@ -561,6 +579,9 @@ public void ToggleInput() ValidateBaseElementProperties(toggleInput, "ToggleInputId", false, true, Spacing.Medium, HeightType.Stretch); + Assert.IsFalse(toggleInput.IsRequired); + Assert.IsTrue(toggleInput.ErrorMessage.Length == 0); + Assert.AreEqual("Title", toggleInput.Title); Assert.AreEqual("Value", toggleInput.Value); Assert.AreEqual("ValueOff", toggleInput.ValueOff); diff --git a/source/uwp/UWPUnitTests/UWPUnitTests.csproj b/source/uwp/UWPUnitTests/UWPUnitTests.csproj index 00d115f6ea..4862831943 100644 --- a/source/uwp/UWPUnitTests/UWPUnitTests.csproj +++ b/source/uwp/UWPUnitTests/UWPUnitTests.csproj @@ -170,6 +170,9 @@ LinkedCards\v1.2\Elements\%(FileName) + + LinkedCards\v1.3\Elements\%(FileName) + LinkedCards\v1.0\Tests\%(FileName)