From 500c03df1bf9829ee19a3779062e3d019ffd48d7 Mon Sep 17 00:00:00 2001 From: Khaja Nizamuddin Date: Mon, 29 May 2017 15:39:41 +0530 Subject: [PATCH 01/25] Simulator Version Updated --- ANAConversationSimulator/Package.appxmanifest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ANAConversationSimulator/Package.appxmanifest b/ANAConversationSimulator/Package.appxmanifest index 9a1f684..f6ee7e0 100644 --- a/ANAConversationSimulator/Package.appxmanifest +++ b/ANAConversationSimulator/Package.appxmanifest @@ -1,6 +1,6 @@  - + ANA Conversation Simulator From a798c06fc32293ebd82d70c752ebad1eedafb8aa Mon Sep 17 00:00:00 2001 From: Khaja Nizamuddin Date: Tue, 30 May 2017 21:41:23 +0530 Subject: [PATCH 02/25] Next node selection based on API response done --- ANAConversationPlatform/Models/Button.cs | 15 ++++++---- .../Models/Chat/Button.cs | 3 ++ .../ViewModels/MainPageViewModel.cs | 29 ++++++++++++++---- ANAConversationStudio/Models/Chat/Button.cs | 30 +++++++++++++++++++ 4 files changed, 65 insertions(+), 12 deletions(-) diff --git a/ANAConversationPlatform/Models/Button.cs b/ANAConversationPlatform/Models/Button.cs index dcdf56c..daf36c7 100644 --- a/ANAConversationPlatform/Models/Button.cs +++ b/ANAConversationPlatform/Models/Button.cs @@ -22,15 +22,18 @@ public Button(string id = "", string buttonName = "", string buttonText = "", Em public ButtonTypeEnum ButtonType { get; set; } public string DeepLinkUrl { get; set; } public string Url { get; set; } - public int? BounceTimeout { get; set; } = null; + public int? BounceTimeout { get; set; } public string NextNodeId { get; set; } - public bool DefaultButton { get; set; } = false; + public bool DefaultButton { get; set; } public bool Hidden { get; set; } - public string VariableValue { get; set; } = null; + public string VariableValue { get; set; } public bool ConfirmInput { get; set; } - public string PrefixText { get; set; } = null; - public string PostfixText { get; set; } = null; - public string PlaceholderText { get; set; } = null; + public string PrefixText { get; set; } + public string PostfixText { get; set; } + public string PlaceholderText { get; set; } + + public string APIResponseMatchKey { get; set; } + public string APIResponseMatchValue { get; set; } } public enum ButtonTypeEnum { diff --git a/ANAConversationSimulator/Models/Chat/Button.cs b/ANAConversationSimulator/Models/Chat/Button.cs index 585070b..c3dd9b7 100644 --- a/ANAConversationSimulator/Models/Chat/Button.cs +++ b/ANAConversationSimulator/Models/Chat/Button.cs @@ -25,6 +25,9 @@ public Button() { } public string PrefixText { get; set; } public string PostfixText { get; set; } + public string APIResponseMatchKey { get; set; } + public string APIResponseMatchValue { get; set; } + private Dictionary _items; /// /// Contains visible/filtered items in case of diff --git a/ANAConversationSimulator/ViewModels/MainPageViewModel.cs b/ANAConversationSimulator/ViewModels/MainPageViewModel.cs index 13d0ea0..8cf2400 100644 --- a/ANAConversationSimulator/ViewModels/MainPageViewModel.cs +++ b/ANAConversationSimulator/ViewModels/MainPageViewModel.cs @@ -114,17 +114,25 @@ public async void ProcessNode(JToken node, JToken section = null) var query = string.Join("&", paramDict.Select(x => $"{x.Key}={Uri.EscapeDataString(x.Value + "")}")); var api = string.IsNullOrWhiteSpace(query) ? parsedNode.ApiUrl : parsedNode.ApiUrl + "?" + query; - var resp = await APIHelper.HitAsync>(api); - if (resp.ContainsKey("NextNodeId")) + var resp = await APIHelper.HitAsync(api); + + if (!string.IsNullOrWhiteSpace(resp["NextNodeId"] + "")) nextNodeId = resp["NextNodeId"] + ""; - ButtonActionHelper.HandleSaveMultiple(resp); + + ButtonActionHelper.HandleSaveMultiple(resp.ToObject>()); + var apiNextNodeId = ExtractNextNodeIdFromAPIResp(parsedNode, resp); + if (!string.IsNullOrWhiteSpace(apiNextNodeId)) + nextNodeId = apiNextNodeId; } break; case "POST": { - var resp = await APIHelper.HitPostAsync, Dictionary>(parsedNode.ApiUrl, paramDict); - if (resp.ContainsKey("NextNodeId")) + var resp = await APIHelper.HitPostAsync, JObject>(parsedNode.ApiUrl, paramDict); + if (!string.IsNullOrWhiteSpace(resp["NextNodeId"] + "")) nextNodeId = resp["NextNodeId"] + ""; + var apiNextNodeId = ExtractNextNodeIdFromAPIResp(parsedNode, resp); + if (!string.IsNullOrWhiteSpace(apiNextNodeId)) + nextNodeId = apiNextNodeId; } break; default: @@ -352,7 +360,16 @@ public void NavigateToNode(string nextNodeId) if (!string.IsNullOrWhiteSpace(nextNodeId)) ProcessNode(GetNodeById(nextNodeId)); } - + private string ExtractNextNodeIdFromAPIResp(ChatNode node, JObject resp) + { + if (node.Buttons == null) + return null; + return node.Buttons.FirstOrDefault(btn => + !string.IsNullOrWhiteSpace(btn.APIResponseMatchKey) && + resp[btn.APIResponseMatchKey] != null && + resp.SelectToken(btn.APIResponseMatchKey) + "" == btn.APIResponseMatchValue + "") + ?.NextNodeId; + } #region Default public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary suspensionState) { diff --git a/ANAConversationStudio/Models/Chat/Button.cs b/ANAConversationStudio/Models/Chat/Button.cs index fdcb351..0249eea 100644 --- a/ANAConversationStudio/Models/Chat/Button.cs +++ b/ANAConversationStudio/Models/Chat/Button.cs @@ -105,6 +105,36 @@ public bool ConfirmInput #endregion #region Misc + private string _APIResponseMatchKey; + [Category("Misc")] + public string APIResponseMatchKey + { + get { return _APIResponseMatchKey; } + set + { + if (_APIResponseMatchKey != value) + { + _APIResponseMatchKey = value; + OnPropertyChanged(); + } + } + } + + private string _APIResponseMatchValue; + [Category("Misc")] + public string APIResponseMatchValue + { + get { return _APIResponseMatchValue; } + set + { + if (_APIResponseMatchValue != value) + { + _APIResponseMatchValue = value; + OnPropertyChanged(); + } + } + } + private string _DeepLinkUrl; [Category("Misc")] public string DeepLinkUrl From 18ef02fa9c52babf6f94011add68d71a3fe232c2 Mon Sep 17 00:00:00 2001 From: Khaja Nizamuddin Date: Wed, 31 May 2017 15:06:29 +0530 Subject: [PATCH 03/25] Versions Updated --- ANAConversationSimulator/Package.appxmanifest | 2 +- ANAConversationStudio/Properties/AssemblyInfo.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ANAConversationSimulator/Package.appxmanifest b/ANAConversationSimulator/Package.appxmanifest index f6ee7e0..170736b 100644 --- a/ANAConversationSimulator/Package.appxmanifest +++ b/ANAConversationSimulator/Package.appxmanifest @@ -1,6 +1,6 @@  - + ANA Conversation Simulator diff --git a/ANAConversationStudio/Properties/AssemblyInfo.cs b/ANAConversationStudio/Properties/AssemblyInfo.cs index 83fffbb..bf3c2d6 100644 --- a/ANAConversationStudio/Properties/AssemblyInfo.cs +++ b/ANAConversationStudio/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.12.0.0")] -[assembly: AssemblyFileVersion("3.12.0.0")] +[assembly: AssemblyVersion("3.15.0.0")] +[assembly: AssemblyFileVersion("3.15.0.0")] From 1e313fa0ade372b9edcda36783fdb9152a31daca Mon Sep 17 00:00:00 2001 From: Khaja Nizamuddin Date: Thu, 1 Jun 2017 23:10:04 +0530 Subject: [PATCH 04/25] SectionType: Carousel Support Given --- ANAConversationPlatform/Helpers/Extensions.cs | 12 ++ .../Helpers/MongoHelper.cs | 115 +++++++++------ ANAConversationPlatform/Models/ChatNode.cs | 12 +- ANAConversationPlatform/Models/Content.cs | 4 + .../Models/Sections/CarouselSection.cs | 39 +++++ .../Models/Sections/Section.cs | 28 ++-- .../Models/Chat/Sections/CarouselSection.cs | 71 +++++---- .../ButtonActionCommand.cs | 42 ++++++ ANAConversationSimulator/Styles/Custom.xaml | 41 ++++++ .../ViewModels/MainPageViewModel.cs | 20 ++- .../ANAConversationStudio.csproj | 8 + .../Controls/ChatContentCollectionControl.cs | 7 + .../Controls/ChatElementCollectionEditor.cs | 139 ++++++++++++++++++ .../Controls/ChatNodeCollectionEditor.cs | 6 + ANAConversationStudio/Helpers/MongoHelper.cs | 6 + ANAConversationStudio/Helpers/Utilities.cs | 29 ++-- .../Models/Chat/BaseContent.cs | 81 ++++++++++ ANAConversationStudio/Models/Chat/ChatNode.cs | 2 +- .../Models/Chat/Sections/CarouselSection.cs | 56 +++---- .../Properties/AssemblyInfo.cs | 4 +- .../ChatElementCollectionEditorWindow.xaml | 18 +++ .../ChatElementCollectionEditorWindow.xaml.cs | 26 ++++ 22 files changed, 624 insertions(+), 142 deletions(-) create mode 100644 ANAConversationPlatform/Models/Sections/CarouselSection.cs create mode 100644 ANAConversationStudio/Controls/ChatElementCollectionEditor.cs create mode 100644 ANAConversationStudio/Views/ChatElementCollectionEditorWindow.xaml create mode 100644 ANAConversationStudio/Views/ChatElementCollectionEditorWindow.xaml.cs diff --git a/ANAConversationPlatform/Helpers/Extensions.cs b/ANAConversationPlatform/Helpers/Extensions.cs index 9799d15..26cdd7b 100644 --- a/ANAConversationPlatform/Helpers/Extensions.cs +++ b/ANAConversationPlatform/Helpers/Extensions.cs @@ -23,6 +23,18 @@ public static Content GetFor(this List contentCollection, Section secti return contentCollection.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x.SectionId) && x.SectionId == section._id); } + public static Content GetFor(this List contentCollection, CarouselItem carouselItem) + { + if (string.IsNullOrWhiteSpace(carouselItem._id)) return null; + return contentCollection.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x.CarouselItemId) && x.CarouselItemId == carouselItem._id); + } + + public static Content GetFor(this List contentCollection, CarouselButton carouselBtn) + { + if (string.IsNullOrWhiteSpace(carouselBtn._id)) return null; + return contentCollection.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x.CarouselButtonId) && x.CarouselButtonId == carouselBtn._id); + } + public static Content GetFor(this List contentCollection, Button btn) { if (string.IsNullOrWhiteSpace(btn._id)) return null; diff --git a/ANAConversationPlatform/Helpers/MongoHelper.cs b/ANAConversationPlatform/Helpers/MongoHelper.cs index 9123fa1..e457155 100644 --- a/ANAConversationPlatform/Helpers/MongoHelper.cs +++ b/ANAConversationPlatform/Helpers/MongoHelper.cs @@ -159,58 +159,59 @@ private static Section GetSection(BsonDocument sectionBsonDocument) break; case "graph": - - GraphSection gphObj = BsonSerializer.Deserialize(sectionBsonDocument); - - Content docContent = Contents.GetFor(gphObj); - if (docContent != null) { - gphObj.Caption = docContent.Caption; - - gphObj.X.Label = docContent.XLabel; - gphObj.Y.Label = docContent.YLabel; - } - gphObj.CoordinatesSet = new List(); - BsonArray coordinateSetBsonArray = sectionBsonDocument.GetValue("CoordinatesSet").AsBsonArray; + GraphSection gphObj = BsonSerializer.Deserialize(sectionBsonDocument); - - if (coordinateSetBsonArray != null) - foreach (BsonDocument coordinateSetBsonDoc in coordinateSetBsonArray) + Content docContent = Contents.GetFor(gphObj); + if (docContent != null) { - var coordinateListId = coordinateSetBsonDoc.GetValue("CoordinateListId")?.ToString(); - if (!string.IsNullOrWhiteSpace(coordinateListId)) - continue; + gphObj.Caption = docContent.Caption; - var coordinatesObj = new Coordinates() - { - CoordinateListId = coordinateListId - }; + gphObj.X.Label = docContent.XLabel; + gphObj.Y.Label = docContent.YLabel; + } + gphObj.CoordinatesSet = new List(); + BsonArray coordinateSetBsonArray = sectionBsonDocument.GetValue("CoordinatesSet").AsBsonArray; - var coordinateContent = Contents.GetFor(coordinatesObj); - coordinatesObj.LegendName = coordinateContent?.CoordinateListLegend; - if (coordinateSetBsonDoc.TryGetValue("CoordinateList", out BsonValue tempCoordinateList)) + if (coordinateSetBsonArray != null) + foreach (BsonDocument coordinateSetBsonDoc in coordinateSetBsonArray) { - BsonArray coordinateListBsonArray = tempCoordinateList?.AsBsonArray; - if (coordinateListBsonArray != null) - foreach (BsonDocument coordinateBsonDoc in coordinateListBsonArray) - { - string x = coordinateBsonDoc.GetValue("X")?.AsString; - string y = coordinateBsonDoc.GetValue("Y")?.AsString; - - string coordinateText = coordinateContent?.CoordinateText; - - if (string.IsNullOrWhiteSpace(coordinateText)) - coordinatesObj.AddXYCoordinates(x, y); - else - coordinatesObj.AddXYCoordinates(x, y, coordinateText); - - Debug.WriteLine(coordinatesObj.ToJson()); - } + var coordinateListId = coordinateSetBsonDoc.GetValue("CoordinateListId")?.ToString(); + if (!string.IsNullOrWhiteSpace(coordinateListId)) + continue; + + var coordinatesObj = new Coordinates() + { + CoordinateListId = coordinateListId + }; + + var coordinateContent = Contents.GetFor(coordinatesObj); + coordinatesObj.LegendName = coordinateContent?.CoordinateListLegend; + + if (coordinateSetBsonDoc.TryGetValue("CoordinateList", out BsonValue tempCoordinateList)) + { + BsonArray coordinateListBsonArray = tempCoordinateList?.AsBsonArray; + if (coordinateListBsonArray != null) + foreach (BsonDocument coordinateBsonDoc in coordinateListBsonArray) + { + string x = coordinateBsonDoc.GetValue("X")?.AsString; + string y = coordinateBsonDoc.GetValue("Y")?.AsString; + + string coordinateText = coordinateContent?.CoordinateText; + + if (string.IsNullOrWhiteSpace(coordinateText)) + coordinatesObj.AddXYCoordinates(x, y); + else + coordinatesObj.AddXYCoordinates(x, y, coordinateText); + + Debug.WriteLine(coordinatesObj.ToJson()); + } + } + gphObj.CoordinatesSet.Add(coordinatesObj); } - gphObj.CoordinatesSet.Add(coordinatesObj); - } - sectObj = gphObj; + sectObj = gphObj; + } break; @@ -264,6 +265,32 @@ private static Section GetSection(BsonDocument sectionBsonDocument) sectObj = embeddedHtmlObj; break; + case "carousel": + var carouselObj = BsonSerializer.Deserialize(sectionBsonDocument); + var carContent = Contents.GetFor(carouselObj); + if (carContent != null) + { + carouselObj.Title = carContent.Title; + carouselObj.Caption = carContent.Caption; + } + if (carouselObj.Items != null) + foreach (var carItem in carouselObj.Items) + { + var content = Contents.GetFor(carItem); + if (content != null) + { + carItem.Title = content.Title; + carItem.Caption = content.Caption; + } + if (carItem.Buttons != null) + foreach (var carBtn in carItem.Buttons) + { + var carBtnContent = Contents.GetFor(carBtn); + carBtn.Text = carBtnContent?.ButtonText; + } + } + sectObj = carouselObj; + break; default: sectObj = null; break; diff --git a/ANAConversationPlatform/Models/ChatNode.cs b/ANAConversationPlatform/Models/ChatNode.cs index b53795a..2225043 100644 --- a/ANAConversationPlatform/Models/ChatNode.cs +++ b/ANAConversationPlatform/Models/ChatNode.cs @@ -11,18 +11,18 @@ public ChatNode(string id) this.Id = id; } - public string Name { get; set; } = null; + public string Name { get; set; } public string Id { get; set; } public EmotionEnum Emotion { get; set; } public int TimeoutInMs { get; set; } public NodeTypeEnum NodeType { get; set; } = NodeTypeEnum.Combination; public List
Sections { get; set; } = new List
(); public List + + + + + + + + + + + + diff --git a/ANAConversationSimulator/ViewModels/MainPageViewModel.cs b/ANAConversationSimulator/ViewModels/MainPageViewModel.cs index 8cf2400..82717d8 100644 --- a/ANAConversationSimulator/ViewModels/MainPageViewModel.cs +++ b/ANAConversationSimulator/ViewModels/MainPageViewModel.cs @@ -83,7 +83,11 @@ public async void StartChatting() private DispatcherTimer buttonTimeoutTimer; public async void ProcessNode(JToken node, JToken section = null) { - if (node == null) return; + if (node == null) + { + Utils.ShowDialog("Node not found!"); + return; + } ClearButtonTimer(); //Replaceing verbs @@ -118,7 +122,7 @@ public async void ProcessNode(JToken node, JToken section = null) if (!string.IsNullOrWhiteSpace(resp["NextNodeId"] + "")) nextNodeId = resp["NextNodeId"] + ""; - + ButtonActionHelper.HandleSaveMultiple(resp.ToObject>()); var apiNextNodeId = ExtractNextNodeIdFromAPIResp(parsedNode, resp); if (!string.IsNullOrWhiteSpace(apiNextNodeId)) @@ -192,9 +196,19 @@ public async void ProcessNode(JToken node, JToken section = null) case SectionTypeEnum.EmbeddedHtml: parsedSection = currentSectionSource.ToObject(); break; + case SectionTypeEnum.Carousel: + parsedSection = currentSectionSource.ToObject(); + (parsedSection as CarouselSection).Items + .SelectMany(x => x.Buttons) + .Where(X => X != null).ToList() + .ForEach(x => + { + x.VariableName = parsedNode.VariableName; + x.NodeId = parsedNode.Id; + }); + break; case SectionTypeEnum.Link: case SectionTypeEnum.Graph: - case SectionTypeEnum.Carousel: Utils.ShowDialog($"{secType} Coming soon!"); break; default: diff --git a/ANAConversationStudio/ANAConversationStudio.csproj b/ANAConversationStudio/ANAConversationStudio.csproj index 6bc0424..3769ff2 100644 --- a/ANAConversationStudio/ANAConversationStudio.csproj +++ b/ANAConversationStudio/ANAConversationStudio.csproj @@ -131,6 +131,7 @@ MSBuild:Compile Designer + @@ -138,6 +139,9 @@ + + ChatElementCollectionEditorWindow.xaml + DBConnectionManager.xaml @@ -166,6 +170,10 @@ + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/ANAConversationStudio/Controls/ChatContentCollectionControl.cs b/ANAConversationStudio/Controls/ChatContentCollectionControl.cs index db3e257..3d51501 100644 --- a/ANAConversationStudio/Controls/ChatContentCollectionControl.cs +++ b/ANAConversationStudio/Controls/ChatContentCollectionControl.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Windows; using Xceed.Wpf.Toolkit; +using ANAConversationStudio.Models.Chat.Sections; namespace ANAConversationStudio.Controls { @@ -115,6 +116,12 @@ private void PreProccessAddingItem(object item) else if (ChatContentOwner is Button && item is ButtonContent) (item as ButtonContent).ButtonId = (ChatContentOwner as Button)._id; } + + if (item is CarouselButtonContent cBtnContent && ChatContentOwner != null && ChatContentOwner is CarouselButton cBtn) + cBtnContent.CarouselButtonId = cBtn._id; + + if (item is CarouselItemContent cItemContent && ChatContentOwner != null && ChatContentOwner is CarouselItem cItem) + cItemContent.CarouselItemId = cItem._id; } private void ContentItemAdded(BaseContent item) { diff --git a/ANAConversationStudio/Controls/ChatElementCollectionEditor.cs b/ANAConversationStudio/Controls/ChatElementCollectionEditor.cs new file mode 100644 index 0000000..a641e42 --- /dev/null +++ b/ANAConversationStudio/Controls/ChatElementCollectionEditor.cs @@ -0,0 +1,139 @@ +using MongoDB.Bson; +using ANAConversationStudio.Models; +using ANAConversationStudio.Views; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using Xceed.Wpf.Toolkit; +using Xceed.Wpf.Toolkit.PropertyGrid; +using Xceed.Wpf.Toolkit.PropertyGrid.Attributes; +using Xceed.Wpf.Toolkit.PropertyGrid.Editors; +using System.Threading.Tasks; + +namespace ANAConversationStudio.Controls +{ + public class ChatElementCollectionEditor : TypeEditor