Skip to content

Commit

Permalink
Implemented basic BOT Powered ACE
Browse files Browse the repository at this point in the history
  • Loading branch information
PaoloPia committed Dec 12, 2023
1 parent 458eb11 commit 68952ae
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 19 deletions.
1 change: 1 addition & 0 deletions samples/BotPowered-BasicAce/BotPowered-BasicAce.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="AdaptiveCards.Templating" Version="1.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.1" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.21.2" />
</ItemGroup>
Expand Down
106 changes: 104 additions & 2 deletions samples/BotPowered-BasicAce/QuickViewTemplates/ListTasksQuickView.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,105 @@
{

}
"schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.2",
"body": [
{
"type": "TextBlock",
"weight": "Bolder",
"text": "${title}"
},
{
"type": "Container",
"spacing": "Large",
"style": "emphasis",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"weight": "Bolder",
"text": "Title",
"wrap": true
}
],
"width": "60px"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"weight": "Bolder",
"text": "Description",
"wrap": true
}
],
"width": "150px"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"weight": "Bolder",
"text": "Due Date",
"wrap": true
}
],
"width": "80px"
}
]
}
],
"bleed": true
},
{
"$data": "${tasks}",
"type": "Container",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "${Title}",
"wrap": true
}
],
"width": "60px"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "${Description}",
"wrap": true
}
],
"width": "150px"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "${formatDateTime(DueDate, 'yyyy-MM-dd')}",
"wrap": true
}
],
"width": "80px"
}
]
}
]
}
]
}
86 changes: 69 additions & 17 deletions samples/BotPowered-BasicAce/TasksBot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using System.IO;
using AdaptiveCards.Templating;

namespace BotPowered_BasicAce
{
Expand All @@ -28,24 +29,28 @@ public class TasksBot : SharePointActivityHandler

private static ConcurrentDictionary<string, CardViewResponse> cardViews = new ConcurrentDictionary<string, CardViewResponse>();
private static ConcurrentDictionary<string, QuickViewResponse> quickViews = new ConcurrentDictionary<string, QuickViewResponse>();
private static bool cardsInitialized = false;

private static string MainCardView_ID = "MAIN_TASKS_CARD_VIEW";
private static string SingleTaskCardView_ID = "SINGLE_TASK_CARD_VIEW";
private static string ListTasksQuickView_ID = "LIST_TASKS_QUICK_VIEW";

private static List<TaskItem> tasks = new List<TaskItem>(new TaskItem[] {
private static List<TaskItem> tasks = new List<TaskItem>(new TaskItem[] {
new TaskItem { ID = Guid.NewGuid(), Title = "Wash your car", Description = "Remember to wash your car", DueDate = DateTime.Now.AddDays(2) },
new TaskItem { ID = Guid.NewGuid(), Title = "Buy groceries", Description = "Buy ham, cheese and bread", DueDate= DateTime.Now.AddDays(1) },
new TaskItem { ID = Guid.NewGuid(), Title = "Pickup kids at school", Description = "Stop coding! You have kids to pickup at school!", DueDate = DateTime.Now },
new TaskItem { ID = Guid.NewGuid(), Title = "Take a little break", Description = "Remember to stop few minutes and breath", DueDate = DateTime.Now }
});
});

public TasksBot(IConfiguration configuration)
: base()
{
this.configuration = configuration;
this.baseUrl = configuration["BaseUrl"];

// Skip cards init if it has already been done
// if (cardsInitialized) return;

// Add the CardViews
var aceData = new AceData()
{
Expand All @@ -71,6 +76,7 @@ public TasksBot(IConfiguration configuration)
{
new CardButtonComponent()
{
Id = "AllTasks",
Title = "All Tasks",
Action = new QuickViewAction()
{
Expand All @@ -82,7 +88,8 @@ public TasksBot(IConfiguration configuration)
},
new CardButtonComponent()
{
Title = "Next task",
Id = "SingleTask",
Title = "Single task",
Action = new SubmitAction()
{
Parameters = new Dictionary<string, object>()
Expand Down Expand Up @@ -129,19 +136,18 @@ public TasksBot(IConfiguration configuration)
{
new CardButtonComponent()
{
Title = "Complete",
Style = CardButtonStyle.Positive,
Id = "MainView",
Title = "Recap",
Action = new SubmitAction()
{
Parameters = new Dictionary<string, object>()
{
{"taskId", "<TaskId>"}
}
}
},
new CardButtonComponent()
{
Id = "NextTask",
Title = "Next task",
Style = CardButtonStyle.Positive,
Action = new SubmitAction()
{
Parameters = new Dictionary<string, object>()
Expand All @@ -159,11 +165,19 @@ public TasksBot(IConfiguration configuration)

// Add the QuickViews
QuickViewResponse listTasksQuickViewResponse = new QuickViewResponse();
listTasksQuickViewResponse.Title = "Primary Text quick view";
listTasksQuickViewResponse.Template = AdaptiveCard.FromJson(readQuickViewJson("ListTasksQuickView.json")).Card;
listTasksQuickViewResponse.Title = "Detailed tasks list";
listTasksQuickViewResponse.Template = createDynamicAdaptiveCard(
readQuickViewJson("ListTasksQuickView.json"),
new {
title = "Here are your tasks:",
tasks
});
listTasksQuickViewResponse.ViewId = ListTasksQuickView_ID;

quickViews.TryAdd(listTasksQuickViewResponse.ViewId, listTasksQuickViewResponse);

// Set cards as already initialized
cardsInitialized = true;
}

protected override Task<CardViewResponse> OnSharePointTaskGetCardViewAsync(ITurnContext<IInvokeActivity> turnContext, AceRequest aceRequest, CancellationToken cancellationToken)
Expand Down Expand Up @@ -364,29 +378,43 @@ protected override Task<BaseHandleActionResponse> OnSharePointTaskHandleActionAs
Trace.Write("\n\n\nStarted to handle action.\n\n\n");
JObject actionParameters = (JObject)((JObject)turnContext.Activity.Value).Property("data").Value;

if (actionParameters["type"].ToString().Equals("Submit"))
if (actionParameters["type"].ToString().Equals("Submit", StringComparison.InvariantCultureIgnoreCase) &&
(actionParameters["id"].ToString().Equals("NextTask", StringComparison.InvariantCultureIgnoreCase)) ||
actionParameters["id"].ToString().Equals("SingleTask", StringComparison.InvariantCultureIgnoreCase))
{
string viewToNavigateTo = actionParameters["data"]["viewToNavigateTo"].ToString();
int nextTaskId = int.Parse(actionParameters["data"]["nextTaskId"].ToString());
CardViewHandleActionResponse response = new CardViewHandleActionResponse();

string viewToNavigateTo = actionParameters["data"]["viewToNavigateTo"].ToString();
int nextTaskId = int.Parse(actionParameters["data"]["nextTaskId"]?.ToString() ?? "0");

var nextCard = cardViews[viewToNavigateTo];

// Configure title and description of task
((nextCard.CardViewParameters.Header.ToList())[0] as CardTextComponent).Text = tasks[nextTaskId].Title;
((nextCard.CardViewParameters.Body.ToList())[0] as CardTextComponent).Text = tasks[nextTaskId].Description;

// Configure next task submit action parameters
var newNextTaskId = nextTaskId + 1 > tasks.Count ? 0 : nextTaskId + 1;
var submitActionParameters = ((SubmitAction)((nextCard.CardViewParameters.Footer.ToList())[1] as CardButtonComponent).Action);
submitActionParameters.Parameters["nextTaskId"] = newNextTaskId;
var newNextTaskId = nextTaskId + 1 >= tasks.Count ? 0 : nextTaskId + 1;
var nextTaskSubmitActionParameters = ((SubmitAction)((nextCard.CardViewParameters.Footer.ToList())[1] as CardButtonComponent).Action);
nextTaskSubmitActionParameters.Parameters["nextTaskId"] = newNextTaskId;

// Set the response for the action
response.RenderArguments = cardViews[viewToNavigateTo];

Trace.Write("\n\n\nFinished handling action.\n\n\n");
return Task.FromResult<BaseHandleActionResponse>(response);
}
else if (actionParameters["type"].ToString().Equals("Submit", StringComparison.InvariantCultureIgnoreCase) &&
actionParameters["id"].ToString().Equals("MainView", StringComparison.InvariantCultureIgnoreCase))
{
CardViewHandleActionResponse response = new CardViewHandleActionResponse();

// Return to the main view
response.RenderArguments = cardViews[MainCardView_ID];

Trace.Write("\n\n\nFinished handling action.\n\n\n");
return Task.FromResult<BaseHandleActionResponse>(response);
}

Trace.Write("\n\n\nFinished handling action.\n\n\n");
return Task.FromResult<BaseHandleActionResponse>(new NoOpHandleActionResponse());
Expand All @@ -406,5 +434,29 @@ private string readQuickViewJson(string quickViewTemplateFileName)

return json;
}

private AdaptiveCard createDynamicAdaptiveCard(string cardJson, object dataSource)
{
AdaptiveCardTemplate template = new AdaptiveCardTemplate(cardJson);
var cardJsonWithData = template.Expand(dataSource);

// Deserialize the JSON string into an AdaptiveCard object
AdaptiveCardParseResult parseResult = AdaptiveCard.FromJson(cardJsonWithData);

// Check for errors during parsing
if (parseResult.Warnings.Count > 0)
{
Trace.Write("Warnings during parsing:");
foreach (var warning in parseResult.Warnings)
{
Trace.Write(warning.Message);
}
}

// Get the AdaptiveCard object
AdaptiveCard card = parseResult.Card;

return card;
}
}
}
}

0 comments on commit 68952ae

Please sign in to comment.