Initial parsing service and bot service commit.
This commit is contained in:
Родитель
0962648b1d
Коммит
6c5519ddb4
|
@ -0,0 +1,63 @@
|
|||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
|
@ -328,3 +328,4 @@ ASALocalRun/
|
|||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
CELA-Tag_Parsing_Service_Configuration_Utilities/CELA_Tag_Services_Deployment_Configurations.json
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[config]
|
||||
command = deploy.cmd
|
|
@ -0,0 +1,5 @@
|
|||
*.dll
|
||||
*.pdb
|
||||
obj/**
|
||||
bin/**
|
||||
runtimes/**
|
Двоичный файл не отображается.
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="Microsoft Managed Recommended Rules" Description="These rules focus on the most critical problems in your code, including potential security holes, application crashes, and other important logic and design errors. It is recommended to include this rule set in any custom rule set you create for your projects." ToolsVersion="15.0">
|
||||
<Localization ResourceAssembly="Microsoft.VisualStudio.CodeAnalysis.RuleSets.Strings.dll" ResourceBaseName="Microsoft.VisualStudio.CodeAnalysis.RuleSets.Strings.Localized">
|
||||
<Name Resource="MinimumRecommendedRules_Name" />
|
||||
<Description Resource="MinimumRecommendedRules_Description" />
|
||||
</Localization>
|
||||
<Rules AnalyzerId="AsyncUsageAnalyzers" RuleNamespace="AsyncUsageAnalyzers">
|
||||
<Rule Id="AvoidAsyncVoid" Action="Warning" />
|
||||
</Rules>
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
|
||||
<Rule Id="SA1011" Action="None" />
|
||||
<Rule Id="SA1101" Action="None" />
|
||||
<Rule Id="SA1129" Action="None" />
|
||||
<Rule Id="SA1200" Action="None" />
|
||||
<Rule Id="SA1305" Action="Warning" />
|
||||
<Rule Id="SA1309" Action="None" />
|
||||
<Rule Id="SA1412" Action="Warning" />
|
||||
<Rule Id="SA1600" Action="None" />
|
||||
<Rule Id="SA1609" Action="Warning" />
|
||||
<Rule Id="SA1633" Action="None" />
|
||||
</Rules>
|
||||
</RuleSet>
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "netcoreapp2.0",
|
||||
"framework": {
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "2.0.0"
|
||||
},
|
||||
"configProperties": {
|
||||
"System.GC.Server": true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27428.2043
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CELA-Knowledge_Management_Assistant", "CELA-Knowledge_Management_Assistant.csproj", "{D85EBBFC-F5F1-4274-80B9-8FC3A4F304D8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D85EBBFC-F5F1-4274-80B9-8FC3A4F304D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D85EBBFC-F5F1-4274-80B9-8FC3A4F304D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D85EBBFC-F5F1-4274-80B9-8FC3A4F304D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D85EBBFC-F5F1-4274-80B9-8FC3A4F304D8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {A7450314-AAE3-4639-8B12-558699156494}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Bot.Builder.AI.Luis;
|
||||
using Microsoft.Bot.Configuration;
|
||||
|
||||
namespace CELA_Knowledge_Management_Agent
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents references to external services.
|
||||
///
|
||||
/// For example, LUIS services are kept here as a singleton. This external service is configured
|
||||
/// using the <see cref="BotConfiguration"/> class.
|
||||
/// </summary>
|
||||
/// <seealso cref="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1"/>
|
||||
/// <seealso cref="https://www.luis.ai/home"/>
|
||||
public class BotServices
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BotServices"/> class.
|
||||
/// </summary>
|
||||
/// <param name="luisServices">A dictionary of named <see cref="LuisRecognizer"/> instances for usage within the bot.</param>
|
||||
public BotServices(BotConfiguration botConfiguration)
|
||||
{
|
||||
foreach (var service in botConfiguration.Services)
|
||||
{
|
||||
switch (service.Type)
|
||||
{
|
||||
case ServiceTypes.Luis:
|
||||
{
|
||||
var luis = (LuisService)service;
|
||||
if (luis == null)
|
||||
{
|
||||
throw new InvalidOperationException("The LUIS service is not configured correctly in your '.bot' file.");
|
||||
}
|
||||
|
||||
var endpoint = (luis.Region?.StartsWith("https://") ?? false) ? luis.Region : luis.GetEndpoint();
|
||||
var app = new LuisApplication(luis.AppId, luis.AuthoringKey, endpoint);
|
||||
var recognizer = new LuisRecognizer(app);
|
||||
this.LuisServices.Add(luis.Name, recognizer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the set of LUIS Services used.
|
||||
/// Given there can be multiple <see cref="LuisRecognizer"/> services used in a single bot,
|
||||
/// LuisServices is represented as a dictionary. This is also modeled in the
|
||||
/// ".bot" file since the elements are named.
|
||||
/// </summary>
|
||||
/// <remarks>The LUIS services collection should not be modified while the bot is running.</remarks>
|
||||
/// <value>
|
||||
/// A <see cref="LuisRecognizer"/> client instance created based on configuration in the .bot file.
|
||||
/// </value>
|
||||
public Dictionary<string, LuisRecognizer> LuisServices { get; } = new Dictionary<string, LuisRecognizer>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<CodeAnalysisRuleSet>BasicBot.ruleset</CodeAnalysisRuleSet>
|
||||
<RootNamespace>CELA_Knowledge_Management_Assistant</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.8" />
|
||||
<PackageReference Include="Microsoft.Azure.CognitiveServices.ContentModerator" Version="0.12.1-preview" />
|
||||
<PackageReference Include="Microsoft.Azure.CognitiveServices.Language" Version="1.0.1-preview" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Version="4.1.5" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.AI.Luis" Version="4.1.5" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Azure" Version="4.1.5" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Dialogs" Version="4.1.5" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.1.5" />
|
||||
<PackageReference Include="Microsoft.Bot.Configuration" Version="4.1.5" />
|
||||
<PackageReference Include="Microsoft.Bot.Connector" Version="4.1.5" />
|
||||
<PackageReference Include="Microsoft.Bot.Schema" Version="4.1.5" />
|
||||
<PackageReference Include="Microsoft.Graph" Version="1.10.0" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta008">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CELA-Knowledge_Management_Data_Services\CELA-Knowledge_Management_Data_Services.csproj" />
|
||||
<ProjectReference Include="..\CELA-Tags_Parsing_Service\CELA-Tags_Parsing_Service.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<WCFMetadata Include="Connected Services" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="*.bot">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="PostDeployScripts\IncludeSources.targets" Condition="Exists('PostDeployScripts\IncludeSources.targets')" />
|
||||
<Import Project="..\PostDeployScripts\IncludeSources.targets" Condition="Exists('..\PostDeployScripts\IncludeSources.targets')" />
|
||||
</Project>
|
|
@ -0,0 +1,62 @@
|
|||
# How To Deploy
|
||||
This bot relies on the [LUIS.ai][1] cognitive service to function. This document will show how to use simple command line tools to setup LUIS for use with this bot.
|
||||
|
||||
# Install required tools
|
||||
To successfully setup and configure the services this bot depends on, you need to install the MSBOT, LUIS, and Ludown CLI tools. See the documentation for the [Bot Framework CLI Tools][5] for additional information on what CLI tools are available to help you build your bot.
|
||||
|
||||
Ensure you have [Node.js](https://nodejs.org/) version 8.5 or higher
|
||||
|
||||
```bash
|
||||
npm i -g msbot luis-apis ludown
|
||||
```
|
||||
|
||||
# Keeping track of service references using .bot file
|
||||
We highly recommend you can keep track of all the services your bot depends on in a .bot file. You can use either the `msbot` CLI tool or use [Bot Framework Emulator][7] to manage your .bot file. This project was created with a bot file named [`basic-bot.bot`](../basic-bot.bot)
|
||||
|
||||
# Configure all required servies
|
||||
You can use [MSBOT][5] to create and configure the required services for this bot. To do this, simply run the following command from a terminal.
|
||||
You can get your LUIS authoring key by following steps [here][8] and get your Azure subscription ID by following steps [here][9].
|
||||
|
||||
```bash
|
||||
> cd samples/javascript_nodejs/13.basic-bot
|
||||
|
||||
> msbot clone -n <YOUR BOT NAME> -f deploymentScripts/msbotClone --luisAuthoringKey <LUIS-KEY> --subscriptionId <AZURE-SUBSCRIPTION-ID>
|
||||
```
|
||||
|
||||
# Using the CLI tools to create and configure services
|
||||
The LUIS application created for this bot is described in a markdown based .lu file(s) [here](../dialogs/greeting/resources/main.lu). To update your published LUIS application with any changes made to the .lu files, run the following commands.
|
||||
|
||||
```bash
|
||||
> cd samples/javascript_nodejs/13.basic-bot
|
||||
```
|
||||
|
||||
1. To parse the .lu files to a LUIS model:
|
||||
```bash
|
||||
> ludown parse toluis --in dialogs/greeting/resources/main.lu -o cognitiveModels/ --out basicBot.luis -n 'basic-bot-LUIS' -d 'Basic bot Bot Builder V4 sample.' --verbose
|
||||
```
|
||||
2. To create a new LUIS application using the LUIS model generated in step 1 and update the .bot file with the LUIS service configuration:
|
||||
```bash
|
||||
> luis import application --in cognitiveModels/basicBot.luis --authoringKey <YOUR-LUIS-AUTHORING-KEY> --msbot --endpointRegion --region <LUIS-AUTHORING-REGION> | msbot connect luis --stdin
|
||||
```
|
||||
You can obtain your LUIS authoring key by following instructions [here][8]
|
||||
LUIS authoring regions are listed [here][10]. They can be one of westus | westeurope | australiaeast.
|
||||
3. To train the LUIS application,
|
||||
```bash
|
||||
> msbot get basic-bot-LUIS | luis train version --wait --stdin
|
||||
```
|
||||
4. To publish the LUIS application,
|
||||
```bash
|
||||
> msbot get basic-bot-LUIS | luis publish version --stdin
|
||||
```
|
||||
|
||||
See [Bot Builder tools](https://github.com/microsoft/botbuilder-tools) to learn more about the Bot Builder CLI tools.
|
||||
|
||||
[1]: https://www.luis.ai
|
||||
[2]: https://docs.microsoft.com/en-us/azure/bot-service/bot-service-concept-intelligence
|
||||
[3]: https://portal.azure.com
|
||||
[4]: https://azure.microsoft.com/en-us/get-started/
|
||||
[5]: https://github.com/microsoft/botbuilder-tools
|
||||
[6]: https://dev.botframework.com
|
||||
[7]: https://www.github.com/microsoft/botframework-emulator
|
||||
[8]: https://docs.microsoft.com/en-us/azure/cognitive-services/luis/luis-how-to-account-settings
|
||||
[9]: https://blogs.msdn.microsoft.com/mschray/2016/03/18/getting-your-azure-subscription-guid-new-portal/
|
Двоичный файл не отображается.
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace CELA_Knowledge_Management_Agent
|
||||
{
|
||||
/// <summary>
|
||||
/// User state properties for Greeting.
|
||||
/// </summary>
|
||||
public class GreetingState
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public string City { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
> Cancel intent and utterances
|
||||
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
|
||||
# Cancel
|
||||
- please cancel
|
||||
- cancel
|
||||
- quit
|
||||
- stop
|
||||
- abort
|
||||
- don't do it
|
||||
- don't do that
|
||||
- i would like to cancel
|
||||
- i will not give you my name
|
||||
- i won't give you my name
|
||||
- no way, I won't give you my location
|
||||
- I'm not going to tell you where i live
|
||||
- I will not give you my location or name
|
||||
- no way
|
||||
- please stop
|
||||
- I'm bailing
|
|
@ -0,0 +1,9 @@
|
|||
user=Vishwac
|
||||
bot=BasicBot
|
||||
|
||||
user: hi
|
||||
bot: What is your name?
|
||||
user: my name is vishwac
|
||||
bot: Hello Vishwac, what city do you live in?
|
||||
user: I'm from seattle
|
||||
bot: Hi Vishwac, from Seattle, nice to meet you!
|
|
@ -0,0 +1,61 @@
|
|||
> Greeting intent and utterances
|
||||
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
|
||||
# Greeting
|
||||
- good evening
|
||||
- good morning
|
||||
- hello
|
||||
- hello bot
|
||||
- hey
|
||||
- hey there
|
||||
- hi
|
||||
- hi bot
|
||||
- hiya
|
||||
- how are you
|
||||
- how are you today
|
||||
- what's your name
|
||||
- who am i speaking to
|
||||
- who am i speaking with
|
||||
- who are you
|
||||
- yo
|
||||
|
||||
> Add utterances with machine learned simple entity values
|
||||
- call me {userName=scott}
|
||||
- {userName=dan}
|
||||
- {userLocation=delhi}
|
||||
- {userLocation=dhaka}
|
||||
- i live in {userLocation=london}
|
||||
- i reside in {userLocation=san francisco}
|
||||
- i'm from {userLocation=georgia}
|
||||
- i'm {userName=john} from {userLocation=cairo}
|
||||
- i'm {userName=lauren}, and i'm from {userLocation=madrid}
|
||||
- i'm {userName=lili}
|
||||
- {userName=melanie}
|
||||
- {userLocation=mumbai}
|
||||
- my location is {userLocation=new york}
|
||||
- my name is {userName=maria} and i'm from {userLocation=sydney}
|
||||
- my name is {userName=tom}
|
||||
- {userLocation=paris}
|
||||
- {userLocation=portland}
|
||||
- {userLocation=seattle} is my current city
|
||||
- {userLocation=shangai}
|
||||
- {userName=tony} is my name
|
||||
- {userLocation=toronto}
|
||||
- {userName=vishwac} is my name
|
||||
- you can assume i live in {userLocation=cairo}
|
||||
- you can call me {userName=steve}
|
||||
|
||||
> Add patterns with pattern.any entitiy
|
||||
- some people call me {userName_patternAny}
|
||||
- {userName_patternAny}.
|
||||
- i'm {userName_patternAny}
|
||||
- {userName_patternAny} is my name
|
||||
- my name is {userName_patternAny} and i'm from {userLocation_patternAny}
|
||||
- {userLocation_patternAny} is where i live
|
||||
- i'm from {userLocation_patternAny}
|
||||
- my name is {userName_patternAny}
|
||||
- i reside in {userLocation_patternAny}
|
||||
- you can call me {userName_patternAny}
|
||||
- you can assume i live in {userLocation_patternAny}
|
||||
- call me {userName_patternAny}
|
||||
- i live in {userLocation_patternAny}
|
||||
- i'm {userName_patternAny}[,] [and i'm] from {userLocation_patternAny}
|
|
@ -0,0 +1,22 @@
|
|||
> Help intent and utterances
|
||||
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
|
||||
# Help
|
||||
- what can you do
|
||||
- ?
|
||||
- I'm lost
|
||||
- lost
|
||||
- confused
|
||||
- frustrated
|
||||
- what are your capabilities
|
||||
- help me
|
||||
- help
|
||||
- how do I interact with you
|
||||
- help please
|
||||
- i'm stuck
|
||||
- i don't understand
|
||||
- what can I say
|
||||
- what can you help me with
|
||||
- what can you do
|
||||
- what do i do now
|
||||
- why doesn't this work
|
||||
- can you help me
|
|
@ -0,0 +1,3 @@
|
|||
> Reference to other .lu files
|
||||
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
|
||||
[All intents](./*)
|
|
@ -0,0 +1,21 @@
|
|||
> None intent and example utterances
|
||||
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
|
||||
# None
|
||||
- spaghetti
|
||||
- gnocchi
|
||||
- her cat has no teeth
|
||||
- world wide pants
|
||||
- i'd rather be riding my bike
|
||||
- Cook me something
|
||||
- Have you any dreams?
|
||||
- Dont you ever sleep?
|
||||
- Do you play games?
|
||||
- Can you fly?
|
||||
- What's your age?
|
||||
- Are you old?
|
||||
- How old are you?
|
||||
- Getting tired of you
|
||||
- I am tired of you
|
||||
- You are boring
|
||||
- Who is your boss?
|
||||
- Are you busy?
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.0",
|
||||
"body": [
|
||||
{
|
||||
"type": "Image",
|
||||
"url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtB3AwMUeNoq4gUBGe6Ocj8kyh3bXa9ZbV7u1fVKQoyKFHdkqU",
|
||||
"size": "stretch"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"spacing": "medium",
|
||||
"size": "default",
|
||||
"weight": "bolder",
|
||||
"text": "Welcome to Bot Framework!",
|
||||
"wrap": true,
|
||||
"maxLines": 0
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"size": "default",
|
||||
"isSubtle": "yes",
|
||||
"text": "Now that you have successfully run your bot, follow the links in this Adaptive Card to expand your knowledge of Bot Framework.",
|
||||
"wrap": true,
|
||||
"maxLines": 0
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"type": "Action.OpenUrl",
|
||||
"title": "Get an overview",
|
||||
"url": "https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"
|
||||
},
|
||||
{
|
||||
"type": "Action.OpenUrl",
|
||||
"title": "Ask a question",
|
||||
"url": "https://stackoverflow.com/questions/tagged/botframework"
|
||||
},
|
||||
{
|
||||
"type": "Action.OpenUrl",
|
||||
"title": "Learn how to deploy",
|
||||
"url": "https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<CoreCompileDependsOn>$(CoreCompileDependsOn);IncludeSource</CoreCompileDependsOn>
|
||||
</PropertyGroup>
|
||||
<Target Name="IncludeSource">
|
||||
<ItemGroup>
|
||||
<Content Include="**\*.cs" />
|
||||
<Content Include="**\*.csproj" />
|
||||
<Content Include="PostDeployScripts\*.*" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "{WEB_SITE_NAME}",
|
||||
"description": "{WEB_SITE_NAME} Azure Bot Service Code",
|
||||
"homepage": "https://github.com",
|
||||
"private": false,
|
||||
"has_issues": true,
|
||||
"has_projects": true,
|
||||
"has_wiki": true
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const appSettingPath = path.resolve('./appsettings.json');
|
||||
const envPath = path.resolve('./.env');
|
||||
|
||||
const settings = readSettingsFile(appSettingPath, envPath);
|
||||
const env = process.env;
|
||||
|
||||
const envNames = Object.keys(env)
|
||||
.filter(function(x){ return x.indexOf("APPSETTING_") === 0;})
|
||||
.filter(function(x){ return x.indexOf("APPSETTING_WEBSITE_") < 0; });
|
||||
const appSettings = envNames.reduce(function(cur, key) { return {...cur, [key.substring(11)]: env[key]};}, {});
|
||||
|
||||
const newSettings = {...settings, ...appSettings};
|
||||
|
||||
updateSettingsFile(appSettingPath, envPath, newSettings);
|
||||
|
||||
function readDotEnv(file) {
|
||||
const text = fs.readFileSync(file, 'utf-8');
|
||||
const lines = text.split(/[\r\n]/);
|
||||
const settings = lines.reduce(function(cur, line) {
|
||||
const parts = line.split('=');
|
||||
if (parts.length >= 2) {
|
||||
const name = parts.splice(0, 1);
|
||||
cur[name] = parts.join('=');
|
||||
}
|
||||
return cur;
|
||||
}, {});
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
function readSettingsFile(appSettingPath, envPath) {
|
||||
if (fs.existsSync(appSettingPath)) {
|
||||
return JSON.parse(fs.readFileSync(appSettingPath, 'utf-8'));
|
||||
}
|
||||
|
||||
if (fs.existsSync(envPath)) {
|
||||
return readDotEnv(envPath);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
function isNodeJSProject() {
|
||||
return fs.existsSync(path.resolve('./iisnode.yml'));
|
||||
}
|
||||
|
||||
function updateSettingsFile(appSettingPath, envPath, settings) {
|
||||
if (isNodeJSProject()) {
|
||||
const keys = Object.keys(settings);
|
||||
const lines = keys.reduce(function(cur, key) {
|
||||
return [...cur, key + '=' + settings[key]];
|
||||
}, []);
|
||||
fs.writeFileSync(envPath, lines.join('\n'), {encoding: 'utf-8'});
|
||||
} else {
|
||||
fs.writeFileSync(appSettingPath, JSON.stringify(settings, null, 2), {encoding: 'utf-8'});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
@echo off
|
||||
setlocal
|
||||
SET password=%1
|
||||
SET exportSettings=%2
|
||||
SET repoName=srcRepo
|
||||
SET repoUrl=file:///%HOMEDRIVE:~0,1%/%HOMEPATH:~1%/site/%repoName%
|
||||
SET download=bot-src
|
||||
|
||||
echo %repoUrl%
|
||||
|
||||
rem cd to project root
|
||||
pushd ..\wwwroot
|
||||
|
||||
rem init git
|
||||
call git init
|
||||
call git config user.name "botframework"
|
||||
call git config user.email "util@botframework.com"
|
||||
call git add .
|
||||
call git commit -m "prepare to download source"
|
||||
call git remote add srcRepo %repoUrl%
|
||||
popd
|
||||
|
||||
rem init upstream
|
||||
pushd %HOME%\site
|
||||
mkdir srcRepo
|
||||
cd srcRepo
|
||||
call git init --bare
|
||||
popd
|
||||
|
||||
rem push to upstream
|
||||
pushd ..\wwwroot
|
||||
call git push --set-upstream srcRepo master
|
||||
popd
|
||||
|
||||
rem clone srcRepo
|
||||
pushd %HOME%\site
|
||||
call git clone %repoUrl% %download%
|
||||
rem delete .git
|
||||
cd %download%
|
||||
call rm -r -f .git
|
||||
popd
|
||||
|
||||
rem prepare for publish
|
||||
pushd %HOME%\site\%download%
|
||||
mkdir Properties\PublishProfiles
|
||||
pushd Properties\PublishProfiles
|
||||
type ..\..\PostDeployScripts\publishProfile.xml.template | sed -e s/\{WEB_SITE_NAME\}/%WEBSITE_SITE_NAME%/g > %WEBSITE_SITE_NAME%-Web-Deploy.pubxml
|
||||
popd
|
||||
|
||||
set SOLUTION_NAME=
|
||||
for /f "delims=" %%a in ('dir /b *.sln') do @set SOLUTION_NAME=%%a
|
||||
|
||||
type PostDeployScripts\publish.cmd.template | sed -e s/\{SOLUTION_NAME\}/%SOLUTION_NAME%/g | sed -e s/\{PUBLISH_PROFILE\}/%WEBSITE_SITE_NAME%-Web-Deploy.pubxml/g | sed -e s/\{PASSWORD\}/%password%/g > publish.cmd
|
||||
type PostDeployScripts\publishSettings.xml.template | sed -e s/\{WEB_SITE_NAME\}/%WEBSITE_SITE_NAME%/g | sed -e s/\{PASSWORD\}/%password%/g > PostDeployScripts\%WEBSITE_SITE_NAME%.PublishSettings
|
||||
|
||||
popd
|
||||
|
||||
echo %exportSettings%
|
||||
|
||||
if "%exportSettings%" == "" goto zip
|
||||
pushd %HOME%\site\%download%
|
||||
echo 'export app settings'
|
||||
call :APP_SETTINGS
|
||||
popd
|
||||
|
||||
|
||||
:zip
|
||||
rem preare the zip file
|
||||
%HOMEDRIVE%\7zip\7za a %HOME%\site\%download%.zip %HOME%\site\%download%\*
|
||||
|
||||
rem cleanup git stuff
|
||||
pushd ..\wwwroot
|
||||
call rm -r -f .git
|
||||
popd
|
||||
|
||||
pushd %HOME%\site
|
||||
call rm -r -f %download%
|
||||
call rm -r -f %repoName%
|
||||
popd
|
||||
|
||||
endlocal
|
||||
|
||||
goto :EOF
|
||||
|
||||
:APP_SETTINGS
|
||||
echo 'dump app settings'
|
||||
node %HOME%\site\wwwroot\PostDeployScripts\mergeSettings.js
|
||||
exit /b
|
|
@ -0,0 +1,3 @@
|
|||
nuget restore
|
||||
msbuild {SOLUTION_NAME} -p:DeployOnBuild=true -p:PublishProfile={PUBLISH_PROFILE} -p:Password={PASSWORD}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
|
||||
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<WebPublishMethod>MSDeploy</WebPublishMethod>
|
||||
<PublishProvider>AzureWebSite</PublishProvider>
|
||||
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
|
||||
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
||||
<SiteUrlToLaunchAfterPublish>http://{WEB_SITE_NAME}.azurewebsites.net</SiteUrlToLaunchAfterPublish>
|
||||
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
|
||||
<ExcludeApp_Data>False</ExcludeApp_Data>
|
||||
<MSDeployServiceURL>{WEB_SITE_NAME}.scm.azurewebsites.net:443</MSDeployServiceURL>
|
||||
<DeployIisAppPath>{WEB_SITE_NAME}</DeployIisAppPath>
|
||||
<RemoteSitePhysicalPath />
|
||||
<SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
|
||||
<MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
|
||||
<EnableMSDeployBackup>True</EnableMSDeployBackup>
|
||||
<UserName>${WEB_SITE_NAME}</UserName>
|
||||
<_SavePWD>True</_SavePWD>
|
||||
<_DestinationType>AzureWebSite</_DestinationType>
|
||||
</PropertyGroup>
|
||||
</Project>
|
|
@ -0,0 +1,15 @@
|
|||
<publishData>
|
||||
<publishProfile profileName="{WEB_SITE_NAME}-Web-Deploy"
|
||||
publishMethod="MSDeploy"
|
||||
publishUrl="{WEB_SITE_NAME}.scm.azurewebsites.net:443"
|
||||
msdeploySite="{WEB_SITE_NAME}" userName="${WEB_SITE_NAME}"
|
||||
userPWD="{PASSWORD}"
|
||||
destinationAppUrl="http://{WEB_SITE_NAME}.azurewebsites.net"
|
||||
SQLServerDBConnectionString=""
|
||||
mySQLDBConnectionString=""
|
||||
hostingProviderForumLink=""
|
||||
controlPanelLink="http://windows.azure.com"
|
||||
webSystem="WebSites">
|
||||
<databases />
|
||||
</publishProfile>
|
||||
</publishData>
|
|
@ -0,0 +1,23 @@
|
|||
@echo off
|
||||
setlocal
|
||||
|
||||
set DEPLOYMENT_SOURCE=
|
||||
set IN_PLACE_DEPLOYMENT=1
|
||||
|
||||
if exist ..\wwwroot\deploy.cmd (
|
||||
pushd ..\wwwroot
|
||||
call deploy.cmd
|
||||
popd
|
||||
)
|
||||
|
||||
rem kick of build of csproj
|
||||
|
||||
echo record deployment timestamp
|
||||
date /t >> ..\deployment.log
|
||||
time /t >> ..\deployment.log
|
||||
echo ---------------------- >> ..\deployment.log
|
||||
echo Deployment done
|
||||
|
||||
endlocal
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
@echo off
|
||||
setlocal
|
||||
rem ------------------------------------------------------------------------------------------
|
||||
rem setupVsoRemoteRepo [remoteUser] [personalAccessToken] [projName{optional}]
|
||||
rem create and populate VSO git repo for the ABS code instance
|
||||
rem
|
||||
rem remoteUser: user account name of the personal access token
|
||||
rem personalAccessToken: the personal access token used to access github REST API (requires repos scope)
|
||||
rem projName the name of the project to create (default to WEBSITE_SITE_NAME)
|
||||
rem ------------------------------------------------------------------------------------------
|
||||
set remoteUrl=https://api.github.com
|
||||
set remoteUser=%1
|
||||
set remotePwd=%2
|
||||
set projName=%3
|
||||
if '%projName%'=='' set projName=%WEBSITE_SITE_NAME%
|
||||
set repoUrl=https://%remoteUser%:%remotePwd%@github.com/%remoteUser%/%projName%.git
|
||||
rem use curl to create project
|
||||
pushd ..\wwwroot
|
||||
type PostDeployScripts\githubProject.json.template | sed -e s/\{WEB_SITE_NAME\}/%projName%/g > %TEMP%\githubProject.json
|
||||
call curl -H "Content-Type: application/json" -u %remoteUser%:%remotePwd% -d "@%TEMP%\githubProject.json" -X POST %remoteUrl%/user/repos
|
||||
rem rm %TEMP%\githubProject.json
|
||||
popd
|
||||
|
||||
popd
|
||||
rem cd to project root
|
||||
pushd ..\wwwroot
|
||||
|
||||
rem init git
|
||||
call git init
|
||||
call git config user.name "%remoteUser%"
|
||||
call git config user.password "%remotePwd%"
|
||||
call git config user.email "util@botframework.com"
|
||||
call git add .
|
||||
call git commit -m "prepare to setup source control"
|
||||
call git push %repoUrl% master
|
||||
popd
|
||||
|
||||
|
||||
rem cleanup git stuff
|
||||
pushd ..\wwwroot
|
||||
call rm -r -f .git
|
||||
popd
|
||||
|
||||
endlocal
|
|
@ -0,0 +1,50 @@
|
|||
@echo off
|
||||
setlocal
|
||||
rem ------------------------------------------------------------------------------------------
|
||||
rem setupVsoRemoteRepo [vsoRemote] [vsoUserName] [vsoPersonalAccessToken] [projName{optional}]
|
||||
rem create and populate VSO git repo for the ABS code instance
|
||||
rem
|
||||
rem vsoRmote: url of the VSO site (e.g. https://awesomebot.visualstudio.com )
|
||||
rem vosUserName: user account name of the personal access token
|
||||
rem vsoPersonalAccessToken: the personal access token used to access VSO REST api
|
||||
rem projName the name of the project to create (default to WEBSITE_SITE_NAME)
|
||||
rem ------------------------------------------------------------------------------------------
|
||||
set remoteUrl=%1
|
||||
set remoteUser=%2
|
||||
set remotePwd=%3
|
||||
set projName=%4
|
||||
if '%projName%'=='' set projName=%WEBSITE_SITE_NAME%
|
||||
set vstsRoot=%remoteUrl%
|
||||
set repoUrl=https://%remoteUser%:%remotePwd%@%remoteUrl:~8%/_git/%projName%
|
||||
set vstsCreateProject=https://%remoteUser%:%remotePwd%@%remoteUrl:~8%/defaultcollection/_apis/projects?api-version=3.0
|
||||
|
||||
rem use curl to create project
|
||||
pushd ..\wwwroot
|
||||
type PostDeployScripts\vsoProject.json.template | sed -e s/\{WEB_SITE_NAME\}/%projName%/g > %TEMP%\vsoProject.json
|
||||
call curl -H "Content-Type: application/json" -d "@%TEMP%\vsoProject.json" -X POST %vstsCreateProject%
|
||||
rm %TEMP%\vsoProject.json
|
||||
rem sleep for 15 seconds for the creation to complete, this is a wild guess
|
||||
call sleep 15
|
||||
popd
|
||||
|
||||
popd
|
||||
rem cd to project root
|
||||
pushd ..\wwwroot
|
||||
|
||||
rem init git
|
||||
call git init
|
||||
call git config user.name "%remoteUser%"
|
||||
call git config user.password "%remotePwd%"
|
||||
call git config user.email "util@botframework.com"
|
||||
call git add .
|
||||
call git commit -m "prepare to setup source control"
|
||||
call git push %repoUrl% master
|
||||
popd
|
||||
|
||||
|
||||
rem cleanup git stuff
|
||||
pushd ..\wwwroot
|
||||
call rm -r -f .git
|
||||
popd
|
||||
|
||||
endlocal
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name": "{WEB_SITE_NAME}",
|
||||
"description": "{WEB_SITE_NAME} Azure Bot Service Code",
|
||||
"capabilities": {
|
||||
"versioncontrol": {
|
||||
"sourceControlType": "Git"
|
||||
},
|
||||
"processTemplate": {
|
||||
"templateTypeId": "6b724908-ef14-45cf-84f8-768b5384da45"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CELA_Knowledge_Management_Agent
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
BuildWebHost(args).Run();
|
||||
}
|
||||
|
||||
public static IWebHost BuildWebHost(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.ConfigureLogging((hostingContext, logging) =>
|
||||
{
|
||||
// Add Azure Logging
|
||||
logging.AddAzureWebAppDiagnostics();
|
||||
|
||||
// Other Loggers.
|
||||
// There are other logging options available:
|
||||
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-2.1
|
||||
// logging.AddDebug();
|
||||
// logging.AddConsole();
|
||||
})
|
||||
|
||||
// Application Insights.
|
||||
// An alternative logging and metrics service for your application.
|
||||
// https://azure.microsoft.com/en-us/services/application-insights/
|
||||
// .UseApplicationInsights()
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
# Basic Bot template
|
||||
This bot has been created using [Microsoft Bot Framework](https://dev.botframework.com),
|
||||
- Use [LUIS](https://luis.ai) to implement core AI capabilities
|
||||
- Implement a multi-turn conversation using Dialogs
|
||||
- Handle user interruptions for such things as Help or Cancel
|
||||
- Prompt for and validate requests for information from the user
|
||||
|
||||
# Prerequisite to run this bot locally
|
||||
- Download the bot code from the Build blade in the Azure Portal
|
||||
- Update the `appsettings.json` file in the root of the bot project with the botFilePath and botFileSecret
|
||||
- You can find the botFilePath and botFileSecret in the Azure App Service application settings.
|
||||
|
||||
Your appsettings.json file should look like this
|
||||
```bash
|
||||
{
|
||||
"botFilePath": "<copy value from App settings>",
|
||||
"botFileSecret": "<copy value from App settings>"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Run in Visual Studio
|
||||
- Open the .sln file with Visual Studio.
|
||||
- Press F5.
|
||||
## Run in Visual Studio Code
|
||||
- Open the bot project folder with Visual Studio Code.
|
||||
- Bring up a terminal.
|
||||
- Type 'dotnet run'.
|
||||
## Testing the bot using Bot Framework Emulator
|
||||
[Microsoft Bot Framework Emulator](https://aka.ms/botframework-emulator) is a desktop application that allows bot developers to test and debug
|
||||
their bots on localhost or running remotely through a tunnel.
|
||||
- Install the Bot Framework Emulator from [here](https://aka.ms/botframework-emulator).
|
||||
### Connect to bot using Bot Framework Emulator
|
||||
- Launch the Bot Framework Emulator
|
||||
- File -> Open bot and navigate to the bot project folder
|
||||
- Select `<your-bot-name>.bot` file
|
||||
|
||||
# Deploy this bot to Azure
|
||||
## Publish from Visual Studio
|
||||
- Open the .PublishSettings file you find in the PostDeployScripts folder
|
||||
- Copy the userPWD value
|
||||
- Right click on the Project and click on "Publish..."
|
||||
- Paste the password you just copied and publish
|
||||
|
||||
## Publish using the CLI tools
|
||||
You can use the [MSBot](https://github.com/microsoft/botbuilder-tools) Bot Builder CLI tool to clone and configure any services this sample depends on.
|
||||
To install all Bot Builder tools -
|
||||
|
||||
Ensure you have [Node.js](https://nodejs.org/) version 8.5 or higher
|
||||
|
||||
```bash
|
||||
npm i -g msbot chatdown ludown qnamaker luis-apis botdispatch luisgen
|
||||
```
|
||||
To clone this bot, run
|
||||
```
|
||||
msbot clone services -f deploymentScripts/msbotClone -n <BOT-NAME> -l <Azure-location> --subscriptionId <Azure-subscription-id>
|
||||
```
|
||||
# Further reading
|
||||
- [Bot Framework Documentation](https://docs.botframework.com)
|
||||
- [Bot basics](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0)
|
||||
- [Activity processing](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-concept-activity-processing?view=azure-bot-service-4.0)
|
||||
- [LUIS](https://luis.ai)
|
||||
- [Prompt Types](https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-prompts?view=azure-bot-service-4.0&tabs=javascript)
|
||||
- [Azure Bot Service Introduction](https://docs.microsoft.com/en-us/azure/bot-service/bot-service-overview-introduction?view=azure-bot-service-4.0)
|
||||
- [Channels and Bot Connector Service](https://docs.microsoft.com/en-us/azure/bot-service/bot-concepts?view=azure-bot-service-4.0)
|
||||
- [QnA Maker](https://qnamaker.ai)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
> Cancel intent and utterances
|
||||
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
|
||||
# Cancel
|
||||
- please cancel
|
||||
- cancel
|
||||
- quit
|
||||
- stop
|
||||
- abort
|
||||
- don't do it
|
||||
- don't do that
|
||||
- i would like to cancel
|
||||
- i will not give you my name
|
||||
- i won't give you my name
|
||||
- no way, I won't give you my location
|
||||
- I'm not going to tell you where i live
|
||||
- I will not give you my location or name
|
||||
- no way
|
||||
- please stop
|
||||
- I'm bailing
|
|
@ -0,0 +1,9 @@
|
|||
user=Vishwac
|
||||
bot=BasicBot
|
||||
|
||||
user: hi
|
||||
bot: What is your name?
|
||||
user: my name is vishwac
|
||||
bot: Hello Vishwac, what city do you live in?
|
||||
user: I'm from seattle
|
||||
bot: Hi Vishwac, from Seattle, nice to meet you!
|
|
@ -0,0 +1,19 @@
|
|||
> Greeting intent and utterances
|
||||
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
|
||||
# Greeting
|
||||
- good evening
|
||||
- good morning
|
||||
- hello
|
||||
- hello bot
|
||||
- hey
|
||||
- hey there
|
||||
- hi
|
||||
- hi bot
|
||||
- hiya
|
||||
- how are you
|
||||
- how are you today
|
||||
- what's your name
|
||||
- who am i speaking to
|
||||
- who am i speaking with
|
||||
- who are you
|
||||
- yo
|
|
@ -0,0 +1,22 @@
|
|||
> Help intent and utterances
|
||||
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
|
||||
# Help
|
||||
- what can you do
|
||||
- ?
|
||||
- I'm lost
|
||||
- lost
|
||||
- confused
|
||||
- frustrated
|
||||
- what are your capabilities
|
||||
- help me
|
||||
- help
|
||||
- how do I interact with you
|
||||
- help please
|
||||
- i'm stuck
|
||||
- i don't understand
|
||||
- what can I say
|
||||
- what can you help me with
|
||||
- what can you do
|
||||
- what do i do now
|
||||
- why doesn't this work
|
||||
- can you help me
|
|
@ -0,0 +1,3 @@
|
|||
> Reference to other .lu files
|
||||
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
|
||||
[All intents](./*)
|
|
@ -0,0 +1,21 @@
|
|||
> None intent and example utterances
|
||||
> See https://github.com/Microsoft/botbuilder-tools/tree/master/packages/Ludown to learn more about .lu files and the Ludown CLI tool.
|
||||
# None
|
||||
- spaghetti
|
||||
- gnocchi
|
||||
- her cat has no teeth
|
||||
- world wide pants
|
||||
- i'd rather be riding my bike
|
||||
- Cook me something
|
||||
- Have you any dreams?
|
||||
- Dont you ever sleep?
|
||||
- Do you play games?
|
||||
- Can you fly?
|
||||
- What's your age?
|
||||
- Are you old?
|
||||
- How old are you?
|
||||
- Getting tired of you
|
||||
- I am tired of you
|
||||
- You are boring
|
||||
- Who is your boss?
|
||||
- Are you busy?
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
|
||||
"type": "AdaptiveCard",
|
||||
"version": "1.0",
|
||||
"body": [
|
||||
{
|
||||
"type": "Image",
|
||||
"url": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQtB3AwMUeNoq4gUBGe6Ocj8kyh3bXa9ZbV7u1fVKQoyKFHdkqU",
|
||||
"size": "stretch"
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"spacing": "medium",
|
||||
"size": "default",
|
||||
"weight": "bolder",
|
||||
"text": "Welcome to Bot Framework!",
|
||||
"wrap": true,
|
||||
"maxLines": 0
|
||||
},
|
||||
{
|
||||
"type": "TextBlock",
|
||||
"size": "default",
|
||||
"isSubtle": "yes",
|
||||
"text": "Now that you have successfully run your bot, follow the links in this Adaptive Card to expand your knowledge of Bot Framework.",
|
||||
"wrap": true,
|
||||
"maxLines": 0
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"type": "Action.OpenUrl",
|
||||
"title": "Get an overview",
|
||||
"url": "https://docs.microsoft.com/en-us/azure/bot-service/?view=azure-bot-service-4.0"
|
||||
},
|
||||
{
|
||||
"type": "Action.OpenUrl",
|
||||
"title": "Ask a question",
|
||||
"url": "https://stackoverflow.com/questions/tagged/botframework"
|
||||
},
|
||||
{
|
||||
"type": "Action.OpenUrl",
|
||||
"title": "Learn how to deploy",
|
||||
"url": "https://docs.microsoft.com/en-us/azure/bot-service/bot-builder-howto-deploy-azure?view=azure-bot-service-4.0"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Bot.Builder;
|
||||
using Microsoft.Bot.Builder.BotFramework;
|
||||
using Microsoft.Bot.Builder.Integration.AspNet.Core;
|
||||
using Microsoft.Bot.Configuration;
|
||||
using Microsoft.Bot.Connector.Authentication;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CELA_Knowledge_Management_Agent
|
||||
{
|
||||
/// <summary>
|
||||
/// The Startup class configures services and the app's request pipeline.
|
||||
/// </summary>
|
||||
public class Startup
|
||||
{
|
||||
private ILoggerFactory _loggerFactory;
|
||||
private bool _isProduction = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Startup"/> class.
|
||||
/// This method gets called by the runtime. Use this method to add services to the container.
|
||||
/// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940.
|
||||
/// </summary>
|
||||
/// <param name="env">Provides information about the web hosting environment an application is running in.</param>
|
||||
/// <seealso cref="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-2.1"/>
|
||||
public Startup(IHostingEnvironment env)
|
||||
{
|
||||
_isProduction = env.IsProduction();
|
||||
|
||||
var builder = new ConfigurationBuilder()
|
||||
.SetBasePath(env.ContentRootPath)
|
||||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
|
||||
.AddEnvironmentVariables();
|
||||
|
||||
Configuration = builder.Build();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration that represents a set of key/value application configuration properties.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The <see cref="IConfiguration"/> that represents a set of key/value application configuration properties.
|
||||
/// </value>
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
/// <summary>
|
||||
/// This method gets called by the runtime. Use this method to add services to the container.
|
||||
/// </summary>
|
||||
/// <param name="services">Specifies the contract for a <see cref="IServiceCollection"/> of service descriptors.</param>
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton(sp => Configuration);
|
||||
|
||||
var secretKey = Configuration.GetSection("botFileSecret")?.Value;
|
||||
var botFilePath = Configuration.GetSection("botFilePath")?.Value;
|
||||
if (!File.Exists(botFilePath))
|
||||
{
|
||||
throw new FileNotFoundException($"The .bot configuration file was not found. botFilePath: {botFilePath}");
|
||||
}
|
||||
|
||||
// Loads .bot configuration file and adds a singleton that your Bot can access through dependency injection.
|
||||
BotConfiguration botConfig = null;
|
||||
try
|
||||
{
|
||||
botConfig = BotConfiguration.Load(botFilePath, secretKey);
|
||||
}
|
||||
catch
|
||||
{
|
||||
var msg = @"Error reading bot file. Please ensure you have valid botFilePath and botFileSecret set for your environment.
|
||||
- You can find the botFilePath and botFileSecret in the Azure App Service application settings.
|
||||
- If you are running this bot locally, consider adding a appsettings.json file with botFilePath and botFileSecret.
|
||||
- See https://aka.ms/about-bot-file to learn more about .bot file its use and bot configuration.
|
||||
";
|
||||
throw new InvalidOperationException(msg);
|
||||
}
|
||||
|
||||
services.AddSingleton(sp => botConfig ?? throw new InvalidOperationException($"The .bot configuration file could not be loaded. botFilePath: {botFilePath}"));
|
||||
|
||||
// Add BotServices singleton.
|
||||
// Create the connected services from .bot file.
|
||||
services.AddSingleton(sp => new BotServices(botConfig));
|
||||
|
||||
// Retrieve current endpoint.
|
||||
var environment = _isProduction ? "production" : "development";
|
||||
var service = botConfig.Services.FirstOrDefault(s => s.Type == "endpoint" && s.Name == environment);
|
||||
if (service == null && _isProduction)
|
||||
{
|
||||
// Attempt to load development environment
|
||||
service = botConfig.Services.Where(s => s.Type == "endpoint" && s.Name == "development").FirstOrDefault();
|
||||
}
|
||||
|
||||
if (!(service is EndpointService endpointService))
|
||||
{
|
||||
throw new InvalidOperationException($"The .bot file does not contain an endpoint with name '{environment}'.");
|
||||
}
|
||||
|
||||
// Memory Storage is for local bot debugging only. When the bot
|
||||
// is restarted, everything stored in memory will be gone.
|
||||
IStorage dataStore = new MemoryStorage();
|
||||
|
||||
// For production bots use the Azure Blob or
|
||||
// Azure CosmosDB storage providers. For the Azure
|
||||
// based storage providers, add the Microsoft.Bot.Builder.Azure
|
||||
// Nuget package to your solution. That package is found at:
|
||||
// https://www.nuget.org/packages/Microsoft.Bot.Builder.Azure/
|
||||
// Un-comment the following lines to use Azure Blob Storage
|
||||
|
||||
//TODO change bot to use Azure blob and table for storage
|
||||
|
||||
// // Storage configuration name or ID from the .bot file.
|
||||
// const string StorageConfigurationId = "<STORAGE-NAME-OR-ID-FROM-BOT-FILE>";
|
||||
// var blobConfig = botConfig.FindServiceByNameOrId(StorageConfigurationId);
|
||||
// if (!(blobConfig is BlobStorageService blobStorageConfig))
|
||||
// {
|
||||
// throw new InvalidOperationException($"The .bot file does not contain an blob storage with name '{StorageConfigurationId}'.");
|
||||
// }
|
||||
// // Default container name.
|
||||
// const string DefaultBotContainer = "botstate";
|
||||
// var storageContainer = string.IsNullOrWhiteSpace(blobStorageConfig.Container) ? DefaultBotContainer : blobStorageConfig.Container;
|
||||
// IStorage dataStore = new Microsoft.Bot.Builder.Azure.AzureBlobStorage(blobStorageConfig.ConnectionString, storageContainer);
|
||||
|
||||
// Create and add conversation state.
|
||||
var conversationState = new ConversationState(dataStore);
|
||||
services.AddSingleton(conversationState);
|
||||
|
||||
var userState = new UserState(dataStore);
|
||||
services.AddSingleton(userState);
|
||||
|
||||
services.AddBot<BasicBot>(options =>
|
||||
{
|
||||
options.CredentialProvider = new SimpleCredentialProvider(endpointService.AppId, endpointService.AppPassword);
|
||||
options.ChannelProvider = new ConfigurationChannelProvider(Configuration);
|
||||
|
||||
// Catches any errors that occur during a conversation turn and logs them to currently
|
||||
// configured ILogger.
|
||||
ILogger logger = _loggerFactory.CreateLogger<BasicBot>();
|
||||
options.OnTurnError = async (context, exception) =>
|
||||
{
|
||||
logger.LogError($"Exception caught : {exception}");
|
||||
await context.SendActivityAsync("Sorry, it looks like something went wrong.");
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
/// </summary>
|
||||
/// <param name="app">Application Builder.</param>
|
||||
/// <param name="env">Hosting Environment.</param>
|
||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/> to create logger object for tracing.</param>
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||
{
|
||||
_loggerFactory = loggerFactory;
|
||||
|
||||
app.UseDefaultFiles()
|
||||
.UseStaticFiles()
|
||||
.UseBotFramework();
|
||||
}
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
|
@ -0,0 +1,17 @@
|
|||
@echo off
|
||||
setlocal
|
||||
|
||||
set DEPLOYMENT_SOURCE=
|
||||
set DEPLOYMENT_TARGET=%~dp0%.
|
||||
|
||||
copy %~dp0wwwroot\default.htm %~dp0app_offline.htm
|
||||
|
||||
if exist ..\wwwroot\deploy.cmd (
|
||||
pushd ..\wwwroot
|
||||
call deploy.cmd
|
||||
popd
|
||||
)
|
||||
|
||||
del %~dp0%\app_offline.htm
|
||||
|
||||
endlocal
|
|
@ -0,0 +1,111 @@
|
|||
@if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off
|
||||
|
||||
:: ----------------------
|
||||
:: KUDU Deployment Script
|
||||
:: Version: 1.0.17
|
||||
:: ----------------------
|
||||
|
||||
:: Prerequisites
|
||||
:: -------------
|
||||
|
||||
:: Verify node.js installed
|
||||
where node 2>nul >nul
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
echo Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment.
|
||||
goto error
|
||||
)
|
||||
|
||||
:: Setup
|
||||
:: -----
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
SET ARTIFACTS=%~dp0%..\artifacts
|
||||
|
||||
:: ensure that artifacts exists
|
||||
IF NOT EXIST "%ARTIFACTS%" (
|
||||
mkdir "%ARTIFACTS%"
|
||||
)
|
||||
|
||||
IF NOT DEFINED DEPLOYMENT_SOURCE (
|
||||
SET DEPLOYMENT_SOURCE=%~dp0%.
|
||||
)
|
||||
|
||||
IF NOT DEFINED DEPLOYMENT_TARGET (
|
||||
SET DEPLOYMENT_TARGET=%ARTIFACTS%\wwwroot
|
||||
)
|
||||
|
||||
IF NOT DEFINED NEXT_MANIFEST_PATH (
|
||||
SET NEXT_MANIFEST_PATH=%ARTIFACTS%\manifest
|
||||
|
||||
IF NOT DEFINED PREVIOUS_MANIFEST_PATH (
|
||||
SET PREVIOUS_MANIFEST_PATH=%ARTIFACTS%\manifest
|
||||
)
|
||||
)
|
||||
|
||||
IF NOT DEFINED KUDU_SYNC_CMD (
|
||||
:: Install kudu sync
|
||||
echo Installing Kudu Sync
|
||||
call npm install kudusync -g --silent
|
||||
IF !ERRORLEVEL! NEQ 0 goto error
|
||||
|
||||
:: Locally just running "kuduSync" would also work
|
||||
SET KUDU_SYNC_CMD=%appdata%\npm\kuduSync.cmd
|
||||
)
|
||||
IF NOT DEFINED DEPLOYMENT_TEMP (
|
||||
SET DEPLOYMENT_TEMP=%temp%\___deployTemp%random%
|
||||
SET CLEAN_LOCAL_DEPLOYMENT_TEMP=true
|
||||
)
|
||||
|
||||
IF DEFINED CLEAN_LOCAL_DEPLOYMENT_TEMP (
|
||||
IF EXIST "%DEPLOYMENT_TEMP%" rd /s /q "%DEPLOYMENT_TEMP%"
|
||||
mkdir "%DEPLOYMENT_TEMP%"
|
||||
)
|
||||
|
||||
IF DEFINED MSBUILD_PATH goto MsbuildPathDefined
|
||||
SET MSBUILD_PATH=%ProgramFiles(x86)%\MSBuild\14.0\Bin\MSBuild.exe
|
||||
:MsbuildPathDefined
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
:: Deployment
|
||||
:: ----------
|
||||
|
||||
echo Handling ASP.NET Core Web Application deployment.
|
||||
|
||||
:: 1. Restore nuget packages
|
||||
call :ExecuteCmd dotnet restore "BasicBot.sln"
|
||||
IF !ERRORLEVEL! NEQ 0 goto error
|
||||
|
||||
:: 2. Build and publish
|
||||
call :ExecuteCmd dotnet publish "BasicBot.csproj" --output "%DEPLOYMENT_TEMP%" --configuration Release
|
||||
IF !ERRORLEVEL! NEQ 0 goto error
|
||||
|
||||
:: 3. KuduSync
|
||||
call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_TEMP%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
|
||||
IF !ERRORLEVEL! NEQ 0 goto error
|
||||
|
||||
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
goto end
|
||||
|
||||
:: Execute command routine that will echo out when error
|
||||
:ExecuteCmd
|
||||
setlocal
|
||||
set _CMD_=%*
|
||||
call %_CMD_%
|
||||
if "%ERRORLEVEL%" NEQ "0" echo Failed exitCode=%ERRORLEVEL%, command=%_CMD_%
|
||||
exit /b %ERRORLEVEL%
|
||||
|
||||
:error
|
||||
endlocal
|
||||
echo An error has occurred during web site deployment.
|
||||
call :exitSetErrorLevel
|
||||
call :exitFromFunction 2>nul
|
||||
|
||||
:exitSetErrorLevel
|
||||
exit /b 1
|
||||
|
||||
:exitFromFunction
|
||||
()
|
||||
|
||||
:end
|
||||
endlocal
|
||||
echo Finished successfully.
|
Двоичный файл не отображается.
|
@ -0,0 +1,3 @@
|
|||
nuget restore
|
||||
msbuild BasicBot.sln -p:DeployOnBuild=true -p:PublishProfile=knowmtest-Web-Deploy.pubxml -p:Password=P4NcGp0JpkhAjemhR9X9fhnzSqZPNpqdFNmFZpamWgrLxS5tNK9ANbYf86rn
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<aspNetCore processPath="dotnet" arguments=".\CELA-Knowledge_Management_Assistant.dll" stdoutLogEnabled="true" stdoutLogFile="\\?\%home%\LogFiles\stdout" />
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
<!--ProjectGuid: D85EBBFC-F5F1-4274-80B9-8FC3A4F304D8-->
|
|
@ -0,0 +1,425 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>CELA Knowledge Management Assistant</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
font-family: Segoe UI;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
header {
|
||||
background-image: url("data:image/svg+xml,%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 4638.9 651.6' style='enable-background:new 0 0 4638.9 651.6;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%2355A0E0;%7D .st1%7Bfill:none;%7D .st2%7Bfill:%230058A8;%7D .st3%7Bfill:%23328BD8;%7D .st4%7Bfill:%23B6DCF1;%7D .st5%7Bopacity:0.2;fill:url(%23SVGID_1_);enable-background:new ;%7D%0A%3C/style%3E%3Crect y='1.1' class='st0' width='4640' height='646.3'/%3E%3Cpath class='st1' d='M3987.8,323.6L4310.3,1.1h-65.6l-460.1,460.1c-17.5,17.5-46.1,17.5-63.6,0L3260.9,1.1H0v646.3h3660.3 L3889,418.7c17.5-17.5,46.1-17.5,63.6,0l228.7,228.7h66.6l-260.2-260.2C3970.3,369.8,3970.3,341.1,3987.8,323.6z'/%3E%3Cpath class='st2' d='M3784.6,461.2L4244.7,1.1h-983.9l460.1,460.1C3738.4,478.7,3767.1,478.7,3784.6,461.2z'/%3E%3Cpath class='st3' d='M4640,1.1h-329.8l-322.5,322.5c-17.5,17.5-17.5,46.1,0,63.6l260.2,260.2H4640L4640,1.1L4640,1.1z'/%3E%3Cpath class='st4' d='M3889,418.8l-228.7,228.7h521.1l-228.7-228.7C3935.2,401.3,3906.5,401.3,3889,418.8z'/%3E%3ClinearGradient id='SVGID_1_' gradientUnits='userSpaceOnUse' x1='3713.7576' y1='438.1175' x2='3911.4084' y2='14.2535' gradientTransform='matrix(1 0 0 -1 0 641.3969)'%3E%3Cstop offset='0' style='stop-color:%23FFFFFF;stop-opacity:0.5'/%3E%3Cstop offset='1' style='stop-color:%23FFFFFF'/%3E%3C/linearGradient%3E%3Cpath class='st5' d='M3952.7,124.5c-17.5-17.5-46.1-17.5-63.6,0l-523,523h1109.6L3952.7,124.5z'/%3E%3C/svg%3E%0A");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
background-position: right;
|
||||
background-color: #55A0E0;
|
||||
width: 100%;
|
||||
font-size: 44px;
|
||||
height: 120px;
|
||||
color: white;
|
||||
padding: 30px 0 40px 0px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
background-image: url("data:image/svg+xml;utf8,%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%20x%3D%220px%22%20y%3D%220px%22%0A%09%20viewBox%3D%220%200%20150.2%20125%22%20style%3D%22enable-background%3Anew%200%200%20150.2%20125%3B%22%20xml%3Aspace%3D%22preserve%22%3E%0A%3Cstyle%20type%3D%22text/css%22%3E%0A%09.st0%7Bfill%3Anone%3B%7D%0A%09.st1%7Bfill%3A%23FFFFFF%3B%7D%0A%3C/style%3E%0A%3Crect%20x%3D%220.5%22%20class%3D%22st0%22%20width%3D%22149.7%22%20height%3D%22125%22/%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M59%2C102.9L21.8%2C66c-3.5-3.5-3.5-9.1%2C0-12.5l37-36.5l2.9%2C3l-37%2C36.4c-1.8%2C1.8-1.8%2C4.7%2C0%2C6.6l37.2%2C37L59%2C102.9z%22%0A%09%09/%3E%0A%3C/g%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M92.5%2C102.9l-3-3l37.2-37c0.9-0.9%2C1.4-2%2C1.4-3.3c0-1.2-0.5-2.4-1.4-3.3L89.5%2C20l2.9-3l37.2%2C36.4%0A%09%09c1.7%2C1.7%2C2.6%2C3.9%2C2.6%2C6.3s-0.9%2C4.6-2.6%2C6.3L92.5%2C102.9z%22/%3E%0A%3C/g%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M90.1%2C68.4c-4.5%2C0-8-3.5-8-8.1c0-4.5%2C3.5-8.1%2C8-8.1c4.4%2C0%2C8%2C3.7%2C8%2C8.1C98.1%2C64.7%2C94.4%2C68.4%2C90.1%2C68.4z%0A%09%09%20M90.1%2C56.5c-2.2%2C0-3.8%2C1.7-3.8%2C3.9c0%2C2.2%2C1.7%2C3.9%2C3.8%2C3.9c1.9%2C0%2C3.8-1.6%2C3.8-3.9S91.9%2C56.5%2C90.1%2C56.5z%22/%3E%0A%3C/g%3E%0A%3Cg%3E%0A%09%3Cpath%20class%3D%22st1%22%20d%3D%22M61.4%2C68.4c-4.5%2C0-8-3.5-8-8.1c0-4.5%2C3.5-8.1%2C8-8.1c4.4%2C0%2C8%2C3.7%2C8%2C8.1C69.5%2C64.7%2C65.8%2C68.4%2C61.4%2C68.4z%0A%09%09%20M61.4%2C56.5c-2.2%2C0-3.8%2C1.7-3.8%2C3.9c0%2C2.2%2C1.7%2C3.9%2C3.8%2C3.9c1.9%2C0%2C3.8-1.6%2C3.8-3.9S63.3%2C56.5%2C61.4%2C56.5z%22/%3E%0A%3C/g%3E%0A%3C/svg%3E%0A");
|
||||
background-repeat: no-repeat;
|
||||
float: left;
|
||||
height: 140px;
|
||||
width: 140px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.header-text {
|
||||
padding-left: 1%;
|
||||
color: #FFFFFF;
|
||||
font-family: "Segoe UI";
|
||||
font-size: 72px;
|
||||
font-weight: 300;
|
||||
letter-spacing: 0.35px;
|
||||
line-height: 96px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.header-inner-container {
|
||||
min-width: 480px;
|
||||
max-width: 1366px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.header-inner-container::after {
|
||||
content: "";
|
||||
clear: both;
|
||||
display: table;
|
||||
}
|
||||
|
||||
.main-content-area {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.content-title {
|
||||
color: #000000;
|
||||
font-family: "Segoe UI";
|
||||
font-size: 46px;
|
||||
font-weight: 300;
|
||||
line-height: 62px;
|
||||
}
|
||||
|
||||
.main-text {
|
||||
color: #808080;
|
||||
font-size: 24px;
|
||||
font-family: "Segoe UI";
|
||||
font-size: 24px;
|
||||
font-weight: 200;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.main-text-p1 {
|
||||
padding-top: 48px;
|
||||
padding-bottom: 28px;
|
||||
}
|
||||
|
||||
.endpoint {
|
||||
height: 32px;
|
||||
width: 571px;
|
||||
color: #808080;
|
||||
font-family: "Segoe UI";
|
||||
font-size: 24px;
|
||||
font-weight: 200;
|
||||
line-height: 32px;
|
||||
padding-top: 28px;
|
||||
}
|
||||
|
||||
.how-to-build-section {
|
||||
padding-top: 20px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.how-to-build-section > h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.35px;
|
||||
line-height: 22px;
|
||||
margin: 0 0 24px 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.step-container {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.step-container dl {
|
||||
border-left: 1px solid #A0A0A0;
|
||||
display: block;
|
||||
padding: 0 24px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.step-container dl > dt::before {
|
||||
background-color: white;
|
||||
border: 1px solid #A0A0A0;
|
||||
border-radius: 100%;
|
||||
content: '';
|
||||
left: 47px;
|
||||
height: 11px;
|
||||
position: absolute;
|
||||
width: 11px;
|
||||
}
|
||||
|
||||
.step-container dl > .test-bullet::before {
|
||||
background-color: blue;
|
||||
}
|
||||
|
||||
.step-container dl > dt {
|
||||
display: block;
|
||||
font-size: inherit;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.step-container dl > dd {
|
||||
font-size: inherit;
|
||||
line-height: 20px;
|
||||
margin-left: 0;
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
.step-container:last-child dl {
|
||||
border-left: 1px solid transparent;
|
||||
}
|
||||
|
||||
.ctaLink {
|
||||
background-color: transparent;
|
||||
border: 1px solid transparent;
|
||||
color: #006AB1;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
padding: 0;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.ctaLink:focus {
|
||||
outline: 1px solid #00bcf2;
|
||||
}
|
||||
|
||||
.ctaLink:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.step-icon {
|
||||
display: flex;
|
||||
height: 38px;
|
||||
margin-right: 15px;
|
||||
width: 38px;
|
||||
}
|
||||
|
||||
.step-icon > div {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.ms-logo-container {
|
||||
min-width: 580px;
|
||||
max-width: 980px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transition: bottom 400ms;
|
||||
}
|
||||
|
||||
.ms-logo {
|
||||
float: right;
|
||||
background-image: url("data:image/svg+xml;utf8,%0A%3Csvg%20version%3D%221.1%22%20id%3D%22MS-symbol%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%20x%3D%220px%22%20y%3D%220px%22%0A%09%20viewBox%3D%220%200%20400%20120%22%20style%3D%22enable-background%3Anew%200%200%20400%20120%3B%22%20xml%3Aspace%3D%22preserve%22%3E%0A%3Cstyle%20type%3D%22text/css%22%3E%0A%09.st0%7Bfill%3Anone%3B%7D%0A%09.st1%7Bfill%3A%23737474%3B%7D%0A%09.st2%7Bfill%3A%23D63F26%3B%7D%0A%09.st3%7Bfill%3A%23167D3E%3B%7D%0A%09.st4%7Bfill%3A%232E76BC%3B%7D%0A%09.st5%7Bfill%3A%23FDB813%3B%7D%0A%3C/style%3E%0A%3Crect%20x%3D%220.6%22%20class%3D%22st0%22%20width%3D%22398.7%22%20height%3D%22119%22/%3E%0A%3Cpath%20class%3D%22st1%22%20d%3D%22M171.3%2C38.4v43.2h-7.5V47.7h-0.1l-13.4%2C33.9h-5l-13.7-33.9h-0.1v33.9h-6.9V38.4h10.8l12.4%2C32h0.2l13.1-32H171.3%0A%09z%20M177.6%2C41.7c0-1.2%2C0.4-2.2%2C1.3-3c0.9-0.8%2C1.9-1.2%2C3.1-1.2c1.3%2C0%2C2.4%2C0.4%2C3.2%2C1.3c0.8%2C0.8%2C1.3%2C1.8%2C1.3%2C3c0%2C1.2-0.4%2C2.2-1.3%2C3%0A%09c-0.9%2C0.8-1.9%2C1.2-3.2%2C1.2s-2.3-0.4-3.1-1.2C178%2C43.8%2C177.6%2C42.8%2C177.6%2C41.7z%20M185.7%2C50.6v31h-7.3v-31H185.7z%20M207.8%2C76.3%0A%09c1.1%2C0%2C2.3-0.3%2C3.6-0.8c1.3-0.5%2C2.5-1.2%2C3.6-2v6.8c-1.2%2C0.7-2.5%2C1.2-4%2C1.5c-1.5%2C0.3-3.1%2C0.5-4.9%2C0.5c-4.6%2C0-8.3-1.4-11.1-4.3%0A%09c-2.9-2.9-4.3-6.6-4.3-11c0-5%2C1.5-9.1%2C4.4-12.3c2.9-3.2%2C7-4.8%2C12.4-4.8c1.4%2C0%2C2.7%2C0.2%2C4.1%2C0.5c1.4%2C0.4%2C2.5%2C0.8%2C3.3%2C1.2v7%0A%09c-1.1-0.8-2.3-1.5-3.4-1.9c-1.2-0.5-2.4-0.7-3.6-0.7c-2.9%2C0-5.2%2C0.9-7%2C2.8c-1.8%2C1.9-2.7%2C4.4-2.7%2C7.6c0%2C3.1%2C0.8%2C5.6%2C2.5%2C7.3%0A%09C202.6%2C75.4%2C204.9%2C76.3%2C207.8%2C76.3z%20M235.7%2C50.1c0.6%2C0%2C1.1%2C0%2C1.6%2C0.1s0.9%2C0.2%2C1.2%2C0.3v7.4c-0.4-0.3-0.9-0.5-1.7-0.8%0A%09c-0.7-0.3-1.6-0.4-2.7-0.4c-1.8%2C0-3.3%2C0.8-4.5%2C2.3c-1.2%2C1.5-1.9%2C3.8-1.9%2C7v15.6h-7.3v-31h7.3v4.9h0.1c0.7-1.7%2C1.7-3%2C3-4%0A%09C232.2%2C50.6%2C233.8%2C50.1%2C235.7%2C50.1z%20M238.9%2C66.6c0-5.1%2C1.4-9.2%2C4.3-12.2c2.9-3%2C6.9-4.5%2C12.1-4.5c4.8%2C0%2C8.6%2C1.4%2C11.3%2C4.3%0A%09c2.7%2C2.9%2C4.1%2C6.8%2C4.1%2C11.7c0%2C5-1.4%2C9-4.3%2C12c-2.9%2C3-6.8%2C4.5-11.8%2C4.5c-4.8%2C0-8.6-1.4-11.4-4.2C240.3%2C75.3%2C238.9%2C71.4%2C238.9%2C66.6z%0A%09%20M246.5%2C66.3c0%2C3.2%2C0.7%2C5.7%2C2.2%2C7.4c1.5%2C1.7%2C3.6%2C2.6%2C6.3%2C2.6c2.7%2C0%2C4.7-0.9%2C6.1-2.6c1.4-1.7%2C2.1-4.2%2C2.1-7.6c0-3.3-0.7-5.8-2.2-7.5%0A%09c-1.4-1.7-3.4-2.5-6-2.5c-2.7%2C0-4.7%2C0.9-6.2%2C2.7C247.2%2C60.5%2C246.5%2C63%2C246.5%2C66.3z%20M281.5%2C58.8c0%2C1%2C0.3%2C1.9%2C1%2C2.5%0A%09c0.7%2C0.6%2C2.1%2C1.3%2C4.4%2C2.2c2.9%2C1.2%2C5%2C2.5%2C6.1%2C3.9c1.2%2C1.5%2C1.8%2C3.2%2C1.8%2C5.3c0%2C2.9-1.1%2C5.3-3.4%2C7c-2.2%2C1.8-5.3%2C2.7-9.1%2C2.7%0A%09c-1.3%2C0-2.7-0.2-4.3-0.5c-1.6-0.3-2.9-0.7-4-1.2v-7.2c1.3%2C0.9%2C2.8%2C1.7%2C4.3%2C2.2c1.5%2C0.5%2C2.9%2C0.8%2C4.2%2C0.8c1.6%2C0%2C2.9-0.2%2C3.6-0.7%0A%09c0.8-0.5%2C1.2-1.2%2C1.2-2.3c0-1-0.4-1.9-1.2-2.5c-0.8-0.7-2.4-1.5-4.6-2.4c-2.7-1.1-4.6-2.4-5.7-3.8c-1.1-1.4-1.7-3.2-1.7-5.4%0A%09c0-2.8%2C1.1-5.1%2C3.3-6.9c2.2-1.8%2C5.1-2.7%2C8.6-2.7c1.1%2C0%2C2.3%2C0.1%2C3.6%2C0.4c1.3%2C0.2%2C2.5%2C0.6%2C3.4%2C0.9v6.9c-1-0.6-2.1-1.2-3.4-1.7%0A%09c-1.3-0.5-2.6-0.7-3.8-0.7c-1.4%2C0-2.5%2C0.3-3.2%2C0.8C281.9%2C57.1%2C281.5%2C57.8%2C281.5%2C58.8z%20M297.9%2C66.6c0-5.1%2C1.4-9.2%2C4.3-12.2%0A%09c2.9-3%2C6.9-4.5%2C12.1-4.5c4.8%2C0%2C8.6%2C1.4%2C11.3%2C4.3c2.7%2C2.9%2C4.1%2C6.8%2C4.1%2C11.7c0%2C5-1.4%2C9-4.3%2C12c-2.9%2C3-6.8%2C4.5-11.8%2C4.5%0A%09c-4.8%2C0-8.6-1.4-11.4-4.2C299.4%2C75.3%2C297.9%2C71.4%2C297.9%2C66.6z%20M305.5%2C66.3c0%2C3.2%2C0.7%2C5.7%2C2.2%2C7.4c1.5%2C1.7%2C3.6%2C2.6%2C6.3%2C2.6%0A%09c2.7%2C0%2C4.7-0.9%2C6.1-2.6c1.4-1.7%2C2.1-4.2%2C2.1-7.6c0-3.3-0.7-5.8-2.2-7.5c-1.4-1.7-3.4-2.5-6-2.5c-2.7%2C0-4.7%2C0.9-6.2%2C2.7%0A%09C306.3%2C60.5%2C305.5%2C63%2C305.5%2C66.3z%20M353.9%2C56.6h-10.9v25h-7.4v-25h-5.2v-6h5.2v-4.3c0-3.3%2C1.1-5.9%2C3.2-8c2.1-2.1%2C4.8-3.1%2C8.1-3.1%0A%09c0.9%2C0%2C1.7%2C0%2C2.4%2C0.1c0.7%2C0.1%2C1.3%2C0.2%2C1.8%2C0.4V42c-0.2-0.1-0.7-0.3-1.3-0.5c-0.6-0.2-1.3-0.3-2.1-0.3c-1.5%2C0-2.7%2C0.5-3.5%2C1.4%0A%09s-1.2%2C2.4-1.2%2C4.2v3.7h10.9v-7l7.3-2.2v9.2h7.4v6h-7.4v14.5c0%2C1.9%2C0.3%2C3.3%2C1%2C4c0.7%2C0.8%2C1.8%2C1.2%2C3.3%2C1.2c0.4%2C0%2C0.9-0.1%2C1.5-0.3%0A%09c0.6-0.2%2C1.1-0.4%2C1.6-0.7v6c-0.5%2C0.3-1.2%2C0.5-2.3%2C0.7c-1.1%2C0.2-2.1%2C0.3-3.2%2C0.3c-3.1%2C0-5.4-0.8-6.9-2.5c-1.5-1.6-2.3-4.1-2.3-7.4%0A%09V56.6z%22/%3E%0A%3Cg%3E%0A%09%3Crect%20x%3D%2231%22%20y%3D%2224%22%20class%3D%22st2%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%09%3Crect%20x%3D%2268.8%22%20y%3D%2224%22%20class%3D%22st3%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%09%3Crect%20x%3D%2231%22%20y%3D%2261.8%22%20class%3D%22st4%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%09%3Crect%20x%3D%2268.8%22%20y%3D%2261.8%22%20class%3D%22st5%22%20width%3D%2234.2%22%20height%3D%2234.2%22/%3E%0A%3C/g%3E%0A%3C/svg%3E%0A");
|
||||
}
|
||||
|
||||
.ms-logo-container > div {
|
||||
min-height: 60px;
|
||||
width: 150px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 90px 0px 0 20px;
|
||||
min-width: 480px;
|
||||
max-width: 1366px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.column {
|
||||
float: left;
|
||||
width: 45%;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.row:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.download-the-emulator {
|
||||
height: 20px;
|
||||
color: #0063B1;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
padding-bottom: 70px;
|
||||
}
|
||||
|
||||
.how-to-iframe {
|
||||
max-width: 700px !important;
|
||||
min-width: 650px !important;
|
||||
height: 700px !important;
|
||||
}
|
||||
|
||||
.remove-frame-height {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1300px) {
|
||||
.ms-logo {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.header-text {
|
||||
font-size: 40x;
|
||||
}
|
||||
|
||||
.column {
|
||||
float: none;
|
||||
padding-top: 30px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ms-logo-container {
|
||||
padding-top: 30px;
|
||||
min-width: 480px;
|
||||
max-width: 650px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 20px 0px 0 20px;
|
||||
min-width: 480px;
|
||||
max-width: 650px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1370px) {
|
||||
header {
|
||||
background-color: #55A0E0;
|
||||
background-size: auto 200px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1230px) {
|
||||
header {
|
||||
background-color: #55A0E0;
|
||||
background-size: auto 200px;
|
||||
}
|
||||
|
||||
.header-text {
|
||||
font-size: 44px;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
height: 120px;
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1000px) {
|
||||
header {
|
||||
background-color: #55A0E0;
|
||||
background-image: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 632px) {
|
||||
.header-text {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 10px 0px 0 10px;
|
||||
max-width: 490px !important;
|
||||
min-width: 410px !important;
|
||||
}
|
||||
|
||||
.endpoint {
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
.main-text {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.step-container dl > dd {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.column {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.header-icon {
|
||||
height: 110px;
|
||||
width: 110px;
|
||||
}
|
||||
|
||||
.how-to-iframe {
|
||||
max-width: 480px !important;
|
||||
min-width: 400px !important;
|
||||
height: 650px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.remove-frame-height {
|
||||
max-height: 10px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
loadFrame();
|
||||
});
|
||||
var loadFrame = function () {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute("id", "iframe");
|
||||
var offLineHTMLContent = "";
|
||||
var frameElement = document.getElementById("how-to-iframe");
|
||||
if (window.navigator.onLine) {
|
||||
iframe.src = 'https://docs.botframework.com/static/abs/pages/f5.htm';
|
||||
iframe.setAttribute("scrolling", "no");
|
||||
iframe.setAttribute("frameborder", "0");
|
||||
iframe.setAttribute("width", "100%");
|
||||
iframe.setAttribute("height", "100%");
|
||||
var frameDiv = document.getElementById("how-to-iframe");
|
||||
frameDiv.appendChild(iframe);
|
||||
} else {
|
||||
frameElement.classList.add("remove-frame-height");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header class="header">
|
||||
<div class="header-inner-container">
|
||||
<div class="header-icon" style="display: inline-block"></div>
|
||||
<div class="header-text" style="display: inline-block">CELA KM Assistant</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="row">
|
||||
<div class="column" class="main-content-area">
|
||||
<iframe src='https://webchat.botframework.com/embed/knowmtest?s=[ENTER_KEY_HERE]' style='min-width: 400px; width: 100%; min-height: 500px;'></iframe>
|
||||
</div>
|
||||
<div class="column" class="main-content-area">
|
||||
<div class="content-title">How this Assistant works</div>
|
||||
<div class="main-text">
|
||||
-Create and send an email decorated with text tags (e.g., #MID-Testing and #Privacy). Include <a href="mailto:[UPDATE-THIS]@microsoft.com">[UPDATE-THIS]@microsoft.com</a> as a recipient.
|
||||
</div>
|
||||
<div class="main-text">
|
||||
-A <a href="https://flow.microsoft.com/en-us/">Microsoft Flow</a> triggers a workflow that sends the email contents to <a href="https://azure.microsoft.com/">Microsoft Azure</a>. Azure parses the email and hands data back to Flow that instructs Flow to store attached documents to <a href="https://products.office.com/en-us/sharepoint/collaboration">Microsoft SharePoint</a>.
|
||||
</div>
|
||||
<div class="main-text">
|
||||
-An <a href="https://azure.microsoft.com/en-us/services/app-service/web/">Azure Web App</a> deployed web service breaks the email into entities and stores them in <a href="https://docs.microsoft.com/en-us/azure/cosmos-db/introduction">Cosmos Graph Database</a>.
|
||||
</div>
|
||||
<div class="main-text">
|
||||
-An <a href="https://azure.microsoft.com/en-us/services/bot-service/">Azure Bot Service</a> calls the <a href="https://www.luis.ai/">Azure Language Understanding Cognitive Service</a> to translate natural language requests into graph queries that answer questions.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="ms-logo-container">
|
||||
<div class="ms-logo"></div>
|
||||
<div>Copyright Microsoft</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CELA_Knowledge_Management_Data_Services.tests.BusinessLogic
|
||||
{
|
||||
[TestClass()]
|
||||
public class CommunicationProcessingBusinessLogicTests
|
||||
{
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using CELA_Knowledge_Management_Data_Services.BusinessLogic;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CELA_Knowledge_Management_Data_Services.tests.BusinessLogic
|
||||
{
|
||||
[TestClass()]
|
||||
class GraphQueryBusinessLogicTests
|
||||
{
|
||||
[TestMethod]
|
||||
public void ConformStringForQueryTest()
|
||||
{
|
||||
var stringTest = "Some string that has an invalid character like $";
|
||||
var result = GraphQueryBusinessLogic.ConformStringForQuery(stringTest);
|
||||
if (result.Length >= stringTest.Length)
|
||||
{
|
||||
Assert.Fail("Failed to remove disallowed character.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{C58D9225-E2A2-417C-8745-D78A091BAB72}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>CELA_Knowledge_Management_Data_Services.tests</RootNamespace>
|
||||
<AssemblyName>CELA-Knowledge_Management_Data_Services.tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
|
||||
<IsCodedUITest>False</IsCodedUITest>
|
||||
<TestProjectType>UnitTest</TestProjectType>
|
||||
<NuGetPackageImportStamp>
|
||||
</NuGetPackageImportStamp>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Gremlin.Net, Version=3.4.0.0, Culture=neutral, PublicKeyToken=d2035e9aa387a711, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Gremlin.Net.3.4.0\lib\netstandard2.0\Gremlin.Net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.Azure.KeyVault.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.WindowsAzure.Storage, Version=9.3.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\WindowsAzure.Storage.9.3.3\lib\net45\Microsoft.WindowsAzure.Storage.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BusinessLogic\CommunicationProcessingBusinessLogicTests.cs" />
|
||||
<Compile Include="BusinessLogic\GraphQueryBusinessLogicTests.cs" />
|
||||
<Compile Include="KnowledgeManagementDataServicesTestSettings.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="GraphTransactionTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CELA-Knowledge_Management_Data_Services\CELA-Knowledge_Management_Data_Services.csproj">
|
||||
<Project>{6d8bc8a4-9750-4560-a544-7e53cd47948d}</Project>
|
||||
<Name>CELA-Knowledge_Management_Data_Services</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props'))" />
|
||||
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" />
|
||||
</Project>
|
Двоичный файл не отображается.
Двоичные данные
CELA-Knowledge_Management_Data_Services.tests/KnowledgeManagementDataServicesTestSettings.cs
Normal file
Двоичные данные
CELA-Knowledge_Management_Data_Services.tests/KnowledgeManagementDataServicesTestSettings.cs
Normal file
Двоичный файл не отображается.
|
@ -0,0 +1,20 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("CELA-Knowledge_Management_Data_Services.tests")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("CELA-Knowledge_Management_Data_Services.tests")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
[assembly: Guid("c58d9225-e2a2-417c-8745-d78a091bab72")]
|
||||
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Gremlin.Net" version="3.4.0" targetFramework="net461" />
|
||||
<package id="Microsoft.Azure.KeyVault.Core" version="1.0.0" targetFramework="net461" />
|
||||
<package id="Microsoft.CSharp" version="4.3.0" targetFramework="net461" />
|
||||
<package id="MSTest.TestAdapter" version="1.3.2" targetFramework="net461" />
|
||||
<package id="MSTest.TestFramework" version="1.3.2" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
|
||||
<package id="WindowsAzure.Storage" version="9.3.3" targetFramework="net461" />
|
||||
</packages>
|
Двоичные данные
CELA-Knowledge_Management_Data_Services/BusinessLogic/AzureTableTagQuery.cs
Normal file
Двоичные данные
CELA-Knowledge_Management_Data_Services/BusinessLogic/AzureTableTagQuery.cs
Normal file
Двоичный файл не отображается.
|
@ -0,0 +1,890 @@
|
|||
using CELA_Knowledge_Management_Data_Services.DataUtilities;
|
||||
using CELA_Knowledge_Management_Data_Services.Models;
|
||||
using Gremlin.Net.Driver;
|
||||
using Gremlin.Net.Driver.Exceptions;
|
||||
using Gremlin.Net.Structure.IO.GraphSON;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CELA_Knowledge_Management_Data_Services.BusinessLogic
|
||||
{
|
||||
public class CommunicationProcessingBusinessLogic
|
||||
{
|
||||
public const string CommunicationAddressDelimiter = ";";
|
||||
public const string KeyBinder = ")!(@*#&$^%";
|
||||
public const string DefaultGraphPartition = "CELA";
|
||||
public const string GraphPartitionKeyProperty = "partitionKey";
|
||||
public const int MaximumTagLength = 64;
|
||||
public const string TagDelimiter = " ";
|
||||
|
||||
// General Vertex Properties
|
||||
public const string VertexIDProperty = "id";
|
||||
public const string VertexNameProperty = "name";
|
||||
|
||||
//Communicator
|
||||
public const string CommunicatorVertexLabel = "communicator";
|
||||
public const string CommunicatorVertexFullnameProperty = "full name";
|
||||
public const string CommunicatorVertexEmailAliasProperty = "alias";
|
||||
|
||||
// Organization
|
||||
public const string OrganizationVertexLabel = "organization";
|
||||
public const string OrganizationVertexFullnameProperty = "full name";
|
||||
|
||||
// Communication
|
||||
public const string CommunicationVertexLabel = "communication";
|
||||
public const string CommunicationVertexPartitionKeyProperty = "partition key";
|
||||
public const string CommunicationVertexRowKeyProperty = "row key";
|
||||
public const string CommunicationVertexSubjectProperty = "subject";
|
||||
public const string CommunicationVertexUTCTimeProperty = "UTC time";
|
||||
public const string CommunicationVertexYearProperty = "year";
|
||||
public const string CommunicationVertexMonthProperty = "month";
|
||||
public const string CommunicationVertexDayProperty = "day";
|
||||
public const string CommunicationVertexConversationIDProperty = "conversation id";
|
||||
public const string CommunicationVertexReferenceKey = "reference key";
|
||||
|
||||
// Tag
|
||||
public const string TagVertexLabel = "tag";
|
||||
public const string TagVertexTypeProperty = "type";
|
||||
public const string TagVertexKeyProperty = "key";
|
||||
|
||||
// Topic
|
||||
public const string TopicVertexLabel = "topic";
|
||||
public const string TopicVertexDescriptionProperty = "description";
|
||||
public const string TopicVertexTypeProperty = "type";
|
||||
public const string TopicVertexKeyProperty = "key";
|
||||
|
||||
// Project
|
||||
public const string ProjectVertexLabel = "project";
|
||||
public const string ProjectVertexTypeProperty = "type";
|
||||
|
||||
// Document
|
||||
public const string DocumentVertexLabel = "document";
|
||||
public const string DocumentVertexNameProperty = "name";
|
||||
public const string DocumentVertexTypeProperty = "type";
|
||||
public const string DocumentVertexLibraryProperty = "library";
|
||||
public const string DocumentVertexPathProperty = "path";
|
||||
public const string DocumentVertexExternalKeyProperty = "key";
|
||||
|
||||
// Matter
|
||||
public const string MatterVertexLabel = "matter";
|
||||
|
||||
// Communicator->Organization
|
||||
public const string CommunicatorOrganizationEdgeLabel = "member of";
|
||||
|
||||
// Communicator->Communication
|
||||
public const string CommunicatorCommunicationEdgeLabel = "sends";
|
||||
|
||||
// Communication->Tag
|
||||
public const string CommunicationTagEdgeLabel = "relates to";
|
||||
|
||||
// Communication->Document
|
||||
public const string CommunicationDocumentEdgeLabel = "relates to";
|
||||
|
||||
// Tag->Tag
|
||||
public const string TagTagEdgeLabel = "used with";
|
||||
|
||||
// Communication->Communicator
|
||||
public const string CommunicationCommunicatorEdgeLabel = "receives";
|
||||
public const string CommunicationCommunicatorPrimaryRecipientEdgeProperty = "primary recipient";
|
||||
public const string CommunicationCommunicatorSecondaryRecipientEdgeProperty = "secondary recipient";
|
||||
|
||||
// Tag->Project
|
||||
public const string TagProjectEdgeLabel = "used by";
|
||||
public const string TagProjectUsageProperty = "relates to";
|
||||
|
||||
// Communication->Matter
|
||||
public const string CommunicationMatterEdgeLabel = "relates to";
|
||||
|
||||
// Tag->Matter
|
||||
public const string TagMatterEdgeLabel = "relates to";
|
||||
|
||||
// Document->Matter
|
||||
public const string DocumentMatterEdgeLabel = "relates to";
|
||||
|
||||
public CommunicationProcessingBusinessLogic()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static GremlinServer CreateGremlinServer(string Hostname, int Port, string AuthKey, string Database, string Collection)
|
||||
{
|
||||
return new GremlinServer(Hostname, Port, enableSsl: true,
|
||||
username: "/dbs/" + Database + "/colls/" + Collection,
|
||||
password: AuthKey);
|
||||
}
|
||||
|
||||
public static GremlinClient CreateGremlinClient(string Hostname, int Port, string AuthKey, string Database, string Collection)
|
||||
{
|
||||
return new GremlinClient(CreateGremlinServer(Hostname, Port, AuthKey, Database, Collection), new GraphSON2Reader(), new GraphSON2Writer(), GremlinClient.GraphSON2MimeType);
|
||||
}
|
||||
|
||||
public static GremlinClient CreateGremlinClient(IGraphConfiguration graphConfiguration)
|
||||
{
|
||||
return CreateGremlinClient(graphConfiguration.GetGraphDatabaseHostname(), graphConfiguration.GetGraphDatabasePort(), graphConfiguration.GetGraphDatabaseAccessKey(), graphConfiguration.GetGraphDatabaseName(), graphConfiguration.GetGraphDatabaseCollectionName());
|
||||
}
|
||||
|
||||
public static string ProcessDocumentToGraphDB(Document Attachment, string Hostname, int Port, string AuthKey, string Database, string Collection)
|
||||
{
|
||||
// Make sure we have a reference key to look up the associated email
|
||||
if (!string.IsNullOrEmpty(Attachment.referenceKey))
|
||||
{
|
||||
using (var gremlinClient = CreateGremlinClient(Hostname, Port, AuthKey, Database, Collection))
|
||||
{
|
||||
// Find the communication based on the reference key
|
||||
var results = GetGraphVertex(gremlinClient, CommunicationVertexLabel, CommunicationVertexReferenceKey, Attachment.referenceKey);
|
||||
// If the communication was found
|
||||
if (results.Count == 1)
|
||||
{
|
||||
var output = (JArray)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(results));
|
||||
|
||||
string communicationID = string.Empty;
|
||||
foreach (var item in output)
|
||||
{
|
||||
communicationID = item[VertexIDProperty].Value<string>();
|
||||
if (!string.IsNullOrEmpty(communicationID))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Pull the id property and return that if found.
|
||||
// var communicationID = output[VertexIDProperty].Value<string>();
|
||||
|
||||
// Create the attachment
|
||||
Dictionary<string, string> properties = new Dictionary<string, string>();
|
||||
if (string.IsNullOrEmpty(Attachment.type) && !string.IsNullOrEmpty(Attachment.name))
|
||||
{
|
||||
if (Attachment.name.IndexOf(".") > -1)
|
||||
{
|
||||
var attachmentType = Attachment.name.Substring(Attachment.name.LastIndexOf("."));
|
||||
properties.Add(DocumentVertexTypeProperty, attachmentType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
properties.Add(DocumentVertexTypeProperty, Attachment.type);
|
||||
}
|
||||
|
||||
properties.Add(DocumentVertexLibraryProperty, Attachment.sharepointlibrary);
|
||||
properties.Add(DocumentVertexPathProperty, Attachment.sharepointlibrarypath);
|
||||
|
||||
properties.Add(DocumentVertexExternalKeyProperty, Attachment.referenceKey);
|
||||
var attachmentID = AddGraphVertex(gremlinClient, DocumentVertexLabel, Attachment.name, properties, Attachment.id);
|
||||
|
||||
//Create the edge between the communication and the attachment
|
||||
var communicatorCommunicationEdgeQueryResult = AddGraphEdge(gremlinClient, communicationID, attachmentID, CommunicationDocumentEdgeLabel);
|
||||
|
||||
if (!string.IsNullOrEmpty(Attachment.matter))
|
||||
{
|
||||
//Insert or retrieve the ID for the matter
|
||||
var matterID = AddGraphVertex(gremlinClient, MatterVertexLabel, Attachment.matter);
|
||||
//Add an edge from the document to the matter
|
||||
var documentMatterEdgeQueryResults = AddGraphEdge(gremlinClient, attachmentID, matterID, DocumentMatterEdgeLabel);
|
||||
}
|
||||
|
||||
return attachmentID;
|
||||
}
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public static bool ProcessCommunicationToGraphDB(EmailSearch Communication, string Hostname, int Port, string AuthKey, string Database, string Collection)
|
||||
{
|
||||
using (var gremlinClient = CreateGremlinClient(Hostname, Port, AuthKey, Database, Collection))
|
||||
{
|
||||
//Add the communication sender
|
||||
var communicatorID = AddCommunicatorAndOrganization(Communication.EmailSender, gremlinClient);
|
||||
|
||||
//Add the communication with properties
|
||||
var communicationID = AddCommunication(Communication, gremlinClient);
|
||||
|
||||
//Add an edge from the communicator to the communcation
|
||||
var communicatorCommunicationEdgeQueryResult = AddGraphEdge(gremlinClient, communicatorID, communicationID, CommunicatorCommunicationEdgeLabel);
|
||||
|
||||
//Add the communication secondary recipients with edges, note that we put this first to ensure primary relationship overwrite if applicable
|
||||
var secondaryRecipientIDs = ProcessCommunicationRecipients(gremlinClient, communicationID, Communication.EmailCcRecipients, CommunicationCommunicatorSecondaryRecipientEdgeProperty);
|
||||
|
||||
//Add the communication primary recipients with edges
|
||||
var primaryRecipientIDs = ProcessCommunicationRecipients(gremlinClient, communicationID, Communication.EmailToRecipients, CommunicationCommunicatorPrimaryRecipientEdgeProperty);
|
||||
|
||||
|
||||
string matterID = string.Empty;
|
||||
if (!string.IsNullOrEmpty(Communication.MatterId))
|
||||
{
|
||||
//Add the matter
|
||||
matterID = AddGraphVertex(gremlinClient, MatterVertexLabel, Communication.MatterId);
|
||||
|
||||
//Add an edge from the communication to the matter
|
||||
var communicationMatterEdgeQueryResult = AddGraphEdge(gremlinClient, communicationID, matterID, CommunicationMatterEdgeLabel);
|
||||
}
|
||||
|
||||
//Add the tags and edges
|
||||
List<string> tagIDs = null;
|
||||
if (Communication.EmailTagCluster != null && Communication.EmailTagCluster.Length > 0)
|
||||
{
|
||||
List<string> tags = CommunicationProcessingBusinessLogic.ParseConcatenatedString(Communication.EmailTagCluster, TagDelimiter);
|
||||
tagIDs = new List<string>();
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
tagIDs.Add(AddGraphVertex(gremlinClient, TagVertexLabel, tag));
|
||||
|
||||
// Rethinking this//if there is a matter associated with this communication ensure the tag and the matter are connected
|
||||
//if (!string.IsNullOrEmpty(matterID) && string.Equals(matterID, tag, StringComparison.OrdinalIgnoreCase)
|
||||
//{
|
||||
|
||||
//}
|
||||
}
|
||||
|
||||
foreach (var tagID in tagIDs)
|
||||
{
|
||||
//Add an edge from the communication to the tags
|
||||
var communicationTagEdgeQueryResult = AddGraphEdge(gremlinClient, communicationID, tagID, CommunicationTagEdgeLabel);
|
||||
if (!string.IsNullOrEmpty(matterID))
|
||||
{
|
||||
var queryResults = GetGraphEdge(gremlinClient, tagID, matterID, TagMatterEdgeLabel);
|
||||
|
||||
//If we have no edge, add it
|
||||
if (queryResults.Count == 0)
|
||||
{
|
||||
//Add an edge from the tags to the matter
|
||||
var tagMatterEdgeQueryResults = AddGraphEdge(gremlinClient, tagID, matterID, TagMatterEdgeLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static List<string> ProcessCommunicationRecipients(GremlinClient gremlinClient, string communicationID, string CommunicationRecipients, string RecipientEdgePropertyName)
|
||||
{
|
||||
List<string> recipients = null;
|
||||
if (CommunicationRecipients != null && CommunicationRecipients.Length > 0)
|
||||
{
|
||||
recipients = new List<string>();
|
||||
|
||||
//Process the vertices
|
||||
foreach (var recipient in ParseConcatenatedString(CommunicationRecipients))
|
||||
{
|
||||
var receipientID = AddCommunicatorAndOrganization(recipient, gremlinClient);
|
||||
recipients.Add(receipientID);
|
||||
}
|
||||
|
||||
//Process the edges
|
||||
foreach (var recipientID in recipients)
|
||||
{
|
||||
Dictionary<string, string> queryProperties = new Dictionary<string, string>();
|
||||
queryProperties.Add(RecipientEdgePropertyName, "true");
|
||||
var communicationCommunicatorEdgeQueryResult = AddGraphEdge(gremlinClient, communicationID, recipientID, CommunicationCommunicatorEdgeLabel, queryProperties);
|
||||
}
|
||||
}
|
||||
|
||||
return recipients;
|
||||
}
|
||||
|
||||
public static string GetGraphVertexID()
|
||||
{
|
||||
return Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
public static ResultSet<dynamic> GetGraphVertex(GremlinClient GremlinClient, string VertexLabel, string PropertyName, string PropertyValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
var query = GraphQueryBusinessLogic.CreateRetrieveVertexGraphQuery(VertexLabel, PropertyName, PropertyValue);
|
||||
var results = TransactGraphQuery(GremlinClient, query);
|
||||
return results;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static string AddGraphVertex(GremlinClient GremlinClient, string VertexType, string VertexName = null, Dictionary<string, string> Properties = null, string id = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(id))
|
||||
{
|
||||
id = GetGraphVertexID();
|
||||
}
|
||||
|
||||
if (VertexName == null)
|
||||
{
|
||||
VertexName = id;
|
||||
}
|
||||
|
||||
var results = TransactGraphQuery(GremlinClient, GraphQueryBusinessLogic.CreateVertexIfDoesNotExistGraphQuery(VertexType, VertexName, id, Properties));
|
||||
foreach (var result in results)
|
||||
{
|
||||
// The vertex results are formed as Dictionaries with a nested dictionary for their properties
|
||||
var output = (JObject)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(result));
|
||||
// Pull the id property and return that if found.
|
||||
id = output[VertexIDProperty].Value<string>();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static ResultSet<dynamic> UpdateGraphEdge(GremlinClient GremlinClient, string FromVertexID, string ToVertexID, string EdgeLabel, Dictionary<string, string> Properties)
|
||||
{
|
||||
try
|
||||
{
|
||||
var query = GraphQueryBusinessLogic.CreateUpdateEdgeGraphQuery(FromVertexID, ToVertexID, EdgeLabel, Properties);
|
||||
var results = TransactGraphQuery(GremlinClient, query);
|
||||
return results;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static ResultSet<dynamic> GetGraphEdge(GremlinClient GremlinClient, string FromVertexID, string ToVertexID, string EdgeLabel)
|
||||
{
|
||||
try
|
||||
{
|
||||
var query = GraphQueryBusinessLogic.CreateRetrieveEdgeGraphQuery(FromVertexID, ToVertexID, EdgeLabel);
|
||||
var results = TransactGraphQuery(GremlinClient, query);
|
||||
return results;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static ResultSet<dynamic> AddGraphEdge(GremlinClient GremlinClient, string FromVertexID, string ToVertexID, string EdgeLabel, Dictionary<string, string> Properties = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var query = GraphQueryBusinessLogic.CreateAddEdgeGraphQuery(FromVertexID, ToVertexID, EdgeLabel, Properties);
|
||||
var results = TransactGraphQuery(GremlinClient, query);
|
||||
return results;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public static string AddCommunicatorAndOrganization(string CommunicatorIdentity, GremlinClient GremlinClient)
|
||||
{
|
||||
string communicatorID = AddGraphVertex(GremlinClient, CommunicatorVertexLabel, CommunicatorIdentity);
|
||||
|
||||
//Extract the communicator's domain and transact that in
|
||||
var communicatorOrganizationDomain = GetDomainFromEmailAddress(CommunicatorIdentity);
|
||||
string communicatorOrganizationDomainID = AddGraphVertex(GremlinClient, OrganizationVertexLabel, communicatorOrganizationDomain);
|
||||
|
||||
var queryResults = GetGraphEdge(GremlinClient, communicatorID, communicatorOrganizationDomainID, CommunicatorOrganizationEdgeLabel);
|
||||
|
||||
//If we have no edge, add it
|
||||
if (queryResults.Count == 0)
|
||||
{
|
||||
// Create an edge between the communicator and the domain
|
||||
AddGraphEdge(GremlinClient, communicatorID, communicatorOrganizationDomainID, CommunicatorOrganizationEdgeLabel);
|
||||
|
||||
}
|
||||
//If we have one edge, do nothing because the proper connection already exists
|
||||
//If we have many edges, that is a problem
|
||||
else if (queryResults.Count > 1)
|
||||
{
|
||||
//TODO: Add error logging
|
||||
}
|
||||
|
||||
return communicatorID;
|
||||
}
|
||||
|
||||
public static string AddCommunication(EmailSearch Communication, GremlinClient GremlinClient)
|
||||
{
|
||||
Dictionary<string, string> properties = new Dictionary<string, string>();
|
||||
properties.Add(CommunicationVertexPartitionKeyProperty, Communication.PartitionKey);
|
||||
properties.Add(CommunicationVertexRowKeyProperty, Communication.RowKey);
|
||||
properties.Add(CommunicationVertexSubjectProperty, Communication.EmailSubject);
|
||||
properties.Add(CommunicationVertexUTCTimeProperty, Communication.Timestamp.ToString());
|
||||
properties.Add(CommunicationVertexYearProperty, Communication.Timestamp.Year.ToString());
|
||||
properties.Add(CommunicationVertexMonthProperty, Communication.Timestamp.Month.ToString());
|
||||
properties.Add(CommunicationVertexDayProperty, Communication.Timestamp.Day.ToString());
|
||||
properties.Add(CommunicationVertexConversationIDProperty, Communication.EmailConversationId);
|
||||
properties.Add(CommunicationVertexReferenceKey, Communication.ReferenceKey);
|
||||
|
||||
string communicationID = AddGraphVertex(GremlinClient, CommunicationVertexLabel, null, properties);
|
||||
|
||||
return communicationID;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> ProcessCommunicationsIntoGraphQueries(List<EmailSearch> Communications)
|
||||
{
|
||||
Dictionary<string, string> gremlinQueries = new Dictionary<string, string> { };
|
||||
Dictionary<string, string> communicators = new Dictionary<string, string>();
|
||||
Dictionary<string, string> organizations = new Dictionary<string, string>();
|
||||
Dictionary<string, string> tags = new Dictionary<string, string>();
|
||||
Dictionary<string, int> senderTag = new Dictionary<string, int>();
|
||||
Dictionary<string, int> tagPrimaryRecipient = new Dictionary<string, int>();
|
||||
Dictionary<string, int> tagSecondaryRecipient = new Dictionary<string, int>();
|
||||
Dictionary<string, string> organizationCommunicators = new Dictionary<string, string>();
|
||||
Dictionary<string, int> tagRelationships = new Dictionary<string, int>();
|
||||
|
||||
List<CommunicationGraphModel> communicationModels = new List<CommunicationGraphModel>();
|
||||
|
||||
// Clear the model
|
||||
gremlinQueries.Add("Cleanup", "g.V().drop()");
|
||||
|
||||
// Preprocess the communications
|
||||
BuildInteractionDictionaries(Communications, communicators, organizations, organizationCommunicators, tags, senderTag, tagPrimaryRecipient, tagSecondaryRecipient, tagRelationships);
|
||||
|
||||
foreach (var communicator in communicators)
|
||||
{
|
||||
if (communicator.Key != null && communicator.Key.Length > 0)
|
||||
{
|
||||
GenerateVertexInsertionQuery(gremlinQueries, communicator, "communicator");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var organization in organizations)
|
||||
{
|
||||
if (organization.Key != null && organization.Key.Length > 0)
|
||||
{
|
||||
GenerateVertexInsertionQuery(gremlinQueries, organization, "organization");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
if (tag.Key != null && tag.Key.Length > 0)
|
||||
{
|
||||
GenerateVertexInsertionQuery(gremlinQueries, tag, "tag");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var item in organizationCommunicators)
|
||||
{
|
||||
GenerateEdgeInsertionQuery(gremlinQueries, item.Key, KeyBinder, "membership", null);
|
||||
}
|
||||
|
||||
foreach (var item in senderTag)
|
||||
{
|
||||
Dictionary<string, string> edgeProperties = new Dictionary<string, string>
|
||||
{
|
||||
{ "sent", item.Value.ToString() }
|
||||
};
|
||||
GenerateEdgeInsertionQuery(gremlinQueries, item.Key, KeyBinder, "sender", edgeProperties);
|
||||
}
|
||||
|
||||
foreach (var item in tagRelationships)
|
||||
{
|
||||
Dictionary<string, string> edgeProperties = new Dictionary<string, string>
|
||||
{
|
||||
{ "related to", item.Value.ToString() }
|
||||
};
|
||||
GenerateEdgeInsertionQuery(gremlinQueries, item.Key, KeyBinder, "related", edgeProperties);
|
||||
}
|
||||
|
||||
// Get the non-duplcated key union of the primary and secondary recipient lists
|
||||
var totalRecipientList = new List<string>(tagPrimaryRecipient.Keys).Union(new List<string>(tagSecondaryRecipient.Keys));
|
||||
|
||||
foreach (var item in totalRecipientList)
|
||||
{
|
||||
Dictionary<string, string> edgeProperties = new Dictionary<string, string>();
|
||||
ProcessRecipientForEdgeQuery(item, tagPrimaryRecipient, "primary recipient", edgeProperties);
|
||||
ProcessRecipientForEdgeQuery(item, tagSecondaryRecipient, "secondary recipient", edgeProperties);
|
||||
GenerateEdgeInsertionQuery(gremlinQueries, item, KeyBinder, "recipient", edgeProperties);
|
||||
}
|
||||
|
||||
Console.WriteLine(String.Format("Communicators [vertices]: {0}", communicators.Count));
|
||||
Console.WriteLine(String.Format("Organizations [vertices]: {0}", organizations.Count));
|
||||
Console.WriteLine(String.Format("Tags [vertices]: {0}", tags.Count));
|
||||
Console.WriteLine(String.Format("Communicators->Organizations [edges]: {0}", organizationCommunicators.Count));
|
||||
Console.WriteLine(String.Format("Communicators->Tags [edges]: {0}", organizationCommunicators.Count));
|
||||
Console.WriteLine(String.Format("Tags->Communicators (primary recipients) [edges]: {0}", tagPrimaryRecipient.Count));
|
||||
Console.WriteLine(String.Format("Tags->Communicators (secondary recipients) [edges]: {0}", tagSecondaryRecipient.Count));
|
||||
Console.WriteLine(String.Format("Tags->Tags [edges]: {0}", tagRelationships.Count));
|
||||
return gremlinQueries;
|
||||
}
|
||||
|
||||
public enum InsertionQueryPropertyTypes { StringType, IntegerType };
|
||||
|
||||
private static void ProcessRecipientForEdgeQuery(string Key, Dictionary<string, int> Entries, string PropertyName, Dictionary<string, string> EdgeProperties)
|
||||
{
|
||||
if (Entries.ContainsKey(Key))
|
||||
{
|
||||
EdgeProperties.Add(PropertyName, Entries[Key].ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateEdgeInsertionQuery(Dictionary<string, string> GremlinQueries, string LinkedVertices, string KeyBinder, string EdgeType, Dictionary<string, string> Properties)
|
||||
{
|
||||
// TODO Move this into GraphQueryBusinessLogic
|
||||
var tuple = LinkedVertices.Split(new string[] { KeyBinder }, StringSplitOptions.None);
|
||||
var key = String.Format("AddEdge {0}-{1}-{2}", tuple[0], EdgeType, tuple[1]);
|
||||
StringBuilder queryValue = new StringBuilder();
|
||||
//Create the base edge insertion query
|
||||
queryValue.Append(String.Format("g.V('{0}').addE('{1}').to(g.V('{2}'))", tuple[0], EdgeType, tuple[1]));
|
||||
|
||||
//Append properties that should be added to the edge
|
||||
if (Properties != null && Properties.Count > 0)
|
||||
{
|
||||
foreach (var propertyKey in Properties.Keys)
|
||||
{
|
||||
if (Int32.TryParse(Properties[propertyKey], out int intValue))
|
||||
{
|
||||
queryValue.Append(String.Format(".property('{0}',{1})", propertyKey, Properties[propertyKey]));
|
||||
}
|
||||
else
|
||||
{
|
||||
queryValue.Append(String.Format(".property('{0}','{1}')", propertyKey, Properties[propertyKey]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GremlinQueries.Add(key, queryValue.ToString());
|
||||
}
|
||||
|
||||
private static void GenerateEdgeInsertionQuery(Dictionary<string, string> GremlinQueries, string LinkedVertices, string KeyBinder, string EdgeType)
|
||||
{
|
||||
GenerateEdgeInsertionQuery(GremlinQueries, LinkedVertices, KeyBinder, EdgeType, null);
|
||||
}
|
||||
|
||||
private static void GenerateVertexInsertionQuery(Dictionary<string, string> GremlinQueries, KeyValuePair<string, string> KVP, string VertexType, string PartitionName = null)
|
||||
{
|
||||
var query = GraphQueryBusinessLogic.CreateAddVertexGraphQuery(VertexType, KVP.Key, Guid.NewGuid().ToString(), PartitionName);
|
||||
GremlinQueries.Add(String.Format("AddVertex {0}", KVP.Key), query);
|
||||
}
|
||||
|
||||
//Communications, communicators, organizations, organizationCommunicators, tags, senderTag, tagPrimaryRecipient, tagSecondaryRecipient, tagRelationships
|
||||
private static void BuildInteractionDictionaries(List<EmailSearch> Communications, Dictionary<string, string> Communicators, Dictionary<string, string> Organizations, Dictionary<string, string> OrganizationCommunicators, Dictionary<string, string> Tags, Dictionary<string, int> SenderTag, Dictionary<string, int> TagPrimaryRecipient, Dictionary<string, int> TagSecondaryRecipient, Dictionary<string, int> TagRelationships)
|
||||
{
|
||||
// Iterate through all the communications
|
||||
foreach (var communication in Communications)
|
||||
{
|
||||
//Only process entries that have tags
|
||||
if (communication.EmailTagCluster != null && communication.EmailTagCluster.Length > 0)
|
||||
{
|
||||
var communicationModel = new CommunicationGraphModel(communication);
|
||||
|
||||
//Add new communicators
|
||||
AddStringToDictionary(Communicators, communicationModel.CommunicationSender);
|
||||
AddStringListToDictionary(Communicators, communicationModel.ToRecipients);
|
||||
AddStringListToDictionary(Communicators, communicationModel.CcRecipients);
|
||||
|
||||
//Add orgs and create org-communicator mappings
|
||||
CreateCommunicatorOrganizationRelationship(Organizations, OrganizationCommunicators, communicationModel.CommunicationSender, KeyBinder);
|
||||
if (communicationModel.ToRecipients != null)
|
||||
{
|
||||
foreach (var item in communicationModel.ToRecipients)
|
||||
{
|
||||
CreateCommunicatorOrganizationRelationship(Organizations, OrganizationCommunicators, item, KeyBinder);
|
||||
}
|
||||
}
|
||||
|
||||
if (communicationModel.CcRecipients != null)
|
||||
{
|
||||
foreach (var item in communicationModel.CcRecipients)
|
||||
{
|
||||
CreateCommunicatorOrganizationRelationship(Organizations, OrganizationCommunicators, item, KeyBinder);
|
||||
}
|
||||
}
|
||||
|
||||
//Add new tags and tag relationships
|
||||
CreateTagRelationships(Tags, SenderTag, TagPrimaryRecipient, TagSecondaryRecipient, TagRelationships, communicationModel, KeyBinder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateTagRelationships(Dictionary<string, string> Tags, Dictionary<string, int> SenderTag, Dictionary<string, int> TagPrimaryRecipient, Dictionary<string, int> TagSecondaryRecipient, Dictionary<string, int> TagRelationships, CommunicationGraphModel CommunicationModel, string KeyBinder)
|
||||
{
|
||||
//Add new tags
|
||||
AddStringListToDictionary(Tags, CommunicationModel.Tags);
|
||||
|
||||
//Process the tag sender and recipient relationships
|
||||
foreach (var tag in CommunicationModel.Tags)
|
||||
{
|
||||
if (tag.Length > 0)
|
||||
{
|
||||
AddTagSender(SenderTag, CommunicationModel, tag);
|
||||
AddTagRecipients(TagPrimaryRecipient, tag, CommunicationModel.ToRecipients);
|
||||
AddTagRecipients(TagSecondaryRecipient, tag, CommunicationModel.CcRecipients);
|
||||
}
|
||||
}
|
||||
|
||||
// Only process relationships if there are multiple tags
|
||||
if (CommunicationModel.Tags.Count > 1)
|
||||
{
|
||||
// Iterate over the list of tags associated with the communication
|
||||
for (int i = 0; i < CommunicationModel.Tags.Count - 1; i++)
|
||||
{
|
||||
// Move forward in the list by one
|
||||
for (int j = i + 1; j < CommunicationModel.Tags.Count; j++)
|
||||
{
|
||||
var key = CommunicationModel.Tags.ElementAt(i) + KeyBinder + CommunicationModel.Tags.ElementAt(j);
|
||||
IncrementKeyedIntegerInDictionary(TagRelationships, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddTagSender(Dictionary<string, int> SenderTag, CommunicationGraphModel communicationModel, string tag)
|
||||
{
|
||||
string key = communicationModel.CommunicationSender + KeyBinder + tag;
|
||||
IncrementKeyedIntegerInDictionary(SenderTag, key);
|
||||
}
|
||||
|
||||
private static void IncrementKeyedIntegerInDictionary(Dictionary<string, int> KeyedDictionary, string key)
|
||||
{
|
||||
if (KeyedDictionary.ContainsKey(key))
|
||||
{
|
||||
KeyedDictionary[key] = KeyedDictionary[key] + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyedDictionary[key] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddTagRecipients(Dictionary<string, int> DictionaryToPopulate, string tag, List<string> Recipients)
|
||||
{
|
||||
if (Recipients != null && Recipients.Count > 0)
|
||||
{
|
||||
string key = "";
|
||||
foreach (var recipient in Recipients)
|
||||
{
|
||||
key = tag + KeyBinder + recipient;
|
||||
IncrementKeyedIntegerInDictionary(DictionaryToPopulate, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddStringListToDictionary(Dictionary<string, string> DictionaryToPopulate, List<string> ItemsToAdd)
|
||||
{
|
||||
if (ItemsToAdd != null && ItemsToAdd.Count > 0)
|
||||
{
|
||||
foreach (var item in ItemsToAdd)
|
||||
{
|
||||
AddStringToDictionary(DictionaryToPopulate, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddStringToDictionary(Dictionary<string, string> DictionaryToPopulate, String ItemToAdd)
|
||||
{
|
||||
if (ItemToAdd != null && ItemToAdd.Length > 0)
|
||||
{
|
||||
if (!DictionaryToPopulate.ContainsKey(ItemToAdd))
|
||||
{
|
||||
DictionaryToPopulate.Add(ItemToAdd, ItemToAdd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool AddEmailAddressToDictionary(Dictionary<string, string> EmailAddresses, string EmailAddressToAdd, bool ConvertToLowerCase = true)
|
||||
{
|
||||
if (ConvertToLowerCase)
|
||||
{
|
||||
EmailAddressToAdd = EmailAddressToAdd.ToLower();
|
||||
}
|
||||
|
||||
if (!EmailAddresses.ContainsKey(EmailAddressToAdd))
|
||||
{
|
||||
EmailAddresses.Add(EmailAddressToAdd, EmailAddressToAdd);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> ParseConcatenatedString(string ConcatenatedStrings, string Delimiter = null, bool MakeLowerCase = true, bool RemoveReservedCharacters = true, string ReplacementCharacters = "")
|
||||
{
|
||||
if (Delimiter == null)
|
||||
{
|
||||
Delimiter = CommunicationAddressDelimiter;
|
||||
}
|
||||
List<string> returnList = new List<string>();
|
||||
if (ConcatenatedStrings != null && ConcatenatedStrings.Length > 0)
|
||||
{
|
||||
var entries = ConcatenatedStrings.Split(new string[] { Delimiter }, StringSplitOptions.None);
|
||||
foreach (var entry in entries)
|
||||
{
|
||||
//Limiting total tag length
|
||||
if (entry.Length <= MaximumTagLength)
|
||||
{
|
||||
var entryValue = entry;
|
||||
entryValue = GraphQueryBusinessLogic.ConformStringForQuery(entryValue, MakeLowerCase, RemoveReservedCharacters, ReplacementCharacters);
|
||||
returnList.Add(entryValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public static List<string> CreateCommunicationSendEdgeQuery(string SenderID, string RecipientID)
|
||||
{
|
||||
List<string> queries = new List<string>
|
||||
{
|
||||
GraphQueryBusinessLogic.CreateSenderRecipientEdgeGraphQuery(SenderID, RecipientID)
|
||||
};
|
||||
return queries;
|
||||
}
|
||||
|
||||
public static List<string> CreateCommunicationTagEdgeQuery(string SenderID, string RecipientID, string TagID)
|
||||
{
|
||||
List<string> queries = new List<string>
|
||||
{
|
||||
GraphQueryBusinessLogic.CreateSenderTagEdgeGraphQuery(SenderID, TagID),
|
||||
GraphQueryBusinessLogic.CreateTagRecipientEdgeGraphQuery(TagID, RecipientID)
|
||||
};
|
||||
return queries;
|
||||
}
|
||||
|
||||
public static string GetDomainFromEmailAddress(String CommunicationSender)
|
||||
{
|
||||
if (CommunicationSender != null && CommunicationSender.Length > 0)
|
||||
{
|
||||
var atSymbolIndex = CommunicationSender.IndexOf("@");
|
||||
if (atSymbolIndex > -1)
|
||||
{
|
||||
var domainSuffixDelimiterIndex = CommunicationSender.LastIndexOf(".");
|
||||
// Process a result like someone.somewho@someplace.com
|
||||
if (CommunicationSender.IndexOf(".", atSymbolIndex) == domainSuffixDelimiterIndex)
|
||||
{
|
||||
return CommunicationSender.Substring(atSymbolIndex + 1);
|
||||
}
|
||||
// Process a result like someone.somewho@something.someplace.com
|
||||
else if (CommunicationSender.IndexOf(".", atSymbolIndex) < domainSuffixDelimiterIndex)
|
||||
{
|
||||
return CommunicationSender.Substring(CommunicationSender.IndexOf(".", atSymbolIndex) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void CreateCommunicatorOrganizationRelationship(Dictionary<string, string> Organizations, Dictionary<string, string> OrganizationCommunicators, string CommunicationSender, string KeyBinder)
|
||||
{
|
||||
if (CommunicationSender != null && CommunicationSender.Length > 0)
|
||||
{
|
||||
var domain = GetDomainFromEmailAddress(CommunicationSender);
|
||||
if (domain != null && domain.Length > 0)
|
||||
{
|
||||
AddStringToDictionary(Organizations, domain);
|
||||
var orgCommunicatorKey = domain + KeyBinder + CommunicationSender;
|
||||
AddStringToDictionary(OrganizationCommunicators, orgCommunicatorKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Task<ResultSet<dynamic>> SubmitRequest(GremlinClient gremlinClient, string query)
|
||||
{
|
||||
try
|
||||
{
|
||||
return gremlinClient.SubmitAsync<dynamic>(query);
|
||||
}
|
||||
catch (ResponseException e)
|
||||
{
|
||||
Console.WriteLine("\tRequest Error!");
|
||||
|
||||
// Print the Gremlin status code.
|
||||
Console.WriteLine($"\tStatusCode: {e.StatusCode}");
|
||||
|
||||
// On error, ResponseException.StatusAttributes will include the common StatusAttributes for successful requests, as well as
|
||||
// additional attributes for retry handling and diagnostics.
|
||||
// These include:
|
||||
// x-ms-retry-after-ms : The number of milliseconds to wait to retry the operation after an initial operation was throttled. This will be populated when
|
||||
// : attribute 'x-ms-status-code' returns 429.
|
||||
// x-ms-activity-id : Represents a unique identifier for the operation. Commonly used for troubleshooting purposes.
|
||||
PrintStatusAttributes(e.StatusAttributes);
|
||||
Console.WriteLine($"\t[\"x-ms-retry-after-ms\"] : { GetValueAsString(e.StatusAttributes, "x-ms-retry-after-ms")}");
|
||||
Console.WriteLine($"\t[\"x-ms-activity-id\"] : { GetValueAsString(e.StatusAttributes, "x-ms-activity-id")}");
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintStatusAttributes(IReadOnlyDictionary<string, object> attributes)
|
||||
{
|
||||
Console.WriteLine($"\tStatusAttributes:");
|
||||
Console.WriteLine($"\t[\"x-ms-status-code\"] : { GetValueAsString(attributes, "x-ms-status-code")}");
|
||||
Console.WriteLine($"\t[\"x-ms-total-request-charge\"] : { GetValueAsString(attributes, "x-ms-total-request-charge")}");
|
||||
}
|
||||
|
||||
public static string GetValueAsString(IReadOnlyDictionary<string, object> dictionary, string key)
|
||||
{
|
||||
return JsonConvert.SerializeObject(GetValueOrDefault(dictionary, key));
|
||||
}
|
||||
|
||||
public static object GetValueOrDefault(IReadOnlyDictionary<string, object> dictionary, string key)
|
||||
{
|
||||
if (dictionary.ContainsKey(key))
|
||||
{
|
||||
return dictionary[key];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Uri GetStorageEndpoint()
|
||||
{
|
||||
return AzureTableDataUtilities.GetStorageAccount().TableEndpoint;
|
||||
}
|
||||
|
||||
public static async Task<List<EmailSearch>> RetrieveEmailsAsync()
|
||||
{
|
||||
List<EmailSearch> returnList = null;
|
||||
|
||||
var tagTable = AzureTableDataUtilities.GetTagTable();
|
||||
var tagQuery = new AzureTableTagQuery();
|
||||
returnList = await tagQuery.GetTaggedCommunicationsAsync(tagTable);
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public static void TransactGraphQueries(Dictionary<string, string> GremlinQueries, String Hostname, int Port, String AuthKey, String Database, String Collection, bool VerboseReporting = false)
|
||||
{
|
||||
var gremlinClient = CommunicationProcessingBusinessLogic.CreateGremlinClient(Hostname, Port, AuthKey, Database, Collection);
|
||||
foreach (var query in GremlinQueries)
|
||||
{
|
||||
Console.WriteLine(String.Format("Running this query: {0}: {1}", query.Key, query.Value));
|
||||
TransactGraphQuery(gremlinClient, query.Value, VerboseReporting);
|
||||
}
|
||||
}
|
||||
|
||||
public static ResultSet<dynamic> TransactGraphQuery(GremlinClient gremlinClient, string query, bool VerboseReporting = false)
|
||||
{
|
||||
//Console.WriteLine("Graph transaction: " + query);
|
||||
// Create async task to execute the Gremlin query.
|
||||
var resultSet = SubmitRequest(gremlinClient, query).Result;
|
||||
|
||||
if (VerboseReporting)
|
||||
{
|
||||
if (resultSet.Count > 0)
|
||||
{
|
||||
Console.WriteLine("\tResult:");
|
||||
foreach (var result in resultSet)
|
||||
{
|
||||
// The vertex results are formed as Dictionaries with a nested dictionary for their properties
|
||||
var output = JsonConvert.SerializeObject(result);
|
||||
Console.WriteLine($"\t{output}");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
// Print the status attributes for the result set.
|
||||
// This includes the following:
|
||||
// x-ms-status-code : This is the sub-status code which is specific to Cosmos DB.
|
||||
// x-ms-total-request-charge : The total request units charged for processing a request.
|
||||
PrintStatusAttributes(resultSet.StatusAttributes);
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
return resultSet;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
using CELA_Knowledge_Management_Data_Services.DataUtilities;
|
||||
using CELA_Knowledge_Management_Data_Services.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CELA_Knowledge_Management_Data_Services.BusinessLogic
|
||||
{
|
||||
public class GraphAnalysisBusinessLogic
|
||||
{
|
||||
public static List<TagRecipient> GetTopicRecipients(string Topic, IGraphConfiguration GraphConfiguration)
|
||||
{
|
||||
List<TagRecipient> tagRecipients = new List<TagRecipient>();
|
||||
using (var tagHiveClient = CommunicationProcessingBusinessLogic.CreateGremlinClient(GraphConfiguration))
|
||||
{
|
||||
//TODO Update this query to find most common recipients of the topic
|
||||
string query = string.Format("g.V(\"{0}\").outE(\"recipient\")", Topic);
|
||||
var results = CommunicationProcessingBusinessLogic.SubmitRequest(tagHiveClient, query).Result;
|
||||
if (results.Count > 0)
|
||||
{
|
||||
foreach (var item in results)
|
||||
{
|
||||
TagRecipient tagRecipient = JsonConvert.DeserializeObject<TagRecipient>(JsonConvert.SerializeObject(item));
|
||||
tagRecipients.Add(tagRecipient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tagRecipients;
|
||||
}
|
||||
|
||||
public static List<string> GetTopicSenders(string Topic, IGraphConfiguration GraphConfiguration)
|
||||
{
|
||||
List<string> tagSenders = new List<string>();
|
||||
using (var tagHiveClient = CommunicationProcessingBusinessLogic.CreateGremlinClient(GraphConfiguration))
|
||||
{
|
||||
string query = GraphQueryBusinessLogic.GetTopicSendersGraphQuery(Topic);
|
||||
var results = CommunicationProcessingBusinessLogic.SubmitRequest(tagHiveClient, query).Result;
|
||||
if (results.Count > 0)
|
||||
{
|
||||
foreach (var item in results)
|
||||
{
|
||||
//TagSender tagSender = JsonConvert.DeserializeObject<TagSender>(JsonConvert.SerializeObject(item));
|
||||
tagSenders.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tagSenders;
|
||||
}
|
||||
|
||||
public static DocumentGraphModelList GetDocumentsForTag(IGraphConfiguration GraphConfiguration, string Tag)
|
||||
{
|
||||
using (var tagHiveClient = CommunicationProcessingBusinessLogic.CreateGremlinClient(GraphConfiguration))
|
||||
{
|
||||
string query = GraphQueryBusinessLogic.GetDocumentsForTagGraphQuery(Tag);
|
||||
var results = CommunicationProcessingBusinessLogic.SubmitRequest(tagHiveClient, query).Result;
|
||||
|
||||
var jsonString = JsonConvert.SerializeObject(results);
|
||||
return JsonConvert.DeserializeObject<DocumentGraphModelList>(jsonString);
|
||||
}
|
||||
}
|
||||
|
||||
public static MatterGraphModel GetMatters(IGraphConfiguration GraphConfiguration)
|
||||
{
|
||||
using (var tagHiveClient = CommunicationProcessingBusinessLogic.CreateGremlinClient(GraphConfiguration))
|
||||
{
|
||||
string query = GraphQueryBusinessLogic.GetMattersGraphQuery();
|
||||
var results = CommunicationProcessingBusinessLogic.SubmitRequest(tagHiveClient, query).Result;
|
||||
|
||||
var jsonString = JsonConvert.SerializeObject(results);
|
||||
return JsonConvert.DeserializeObject<MatterGraphModel>(jsonString);
|
||||
}
|
||||
}
|
||||
|
||||
public static Dictionary<string, int> GetTopicSendersWithSentValues(string Topic, IGraphConfiguration GraphConfiguration)
|
||||
{
|
||||
Dictionary<string, int> tagSenders = new Dictionary<string, int>();
|
||||
using (var tagHiveClient = CommunicationProcessingBusinessLogic.CreateGremlinClient(GraphConfiguration))
|
||||
{
|
||||
string query = GraphQueryBusinessLogic.GetTopicSendersGraphQueryWithSentValues(Topic);
|
||||
var results = CommunicationProcessingBusinessLogic.SubmitRequest(tagHiveClient, query).Result;
|
||||
if (results.Count > 0)
|
||||
{
|
||||
foreach (var resultsetItem in results)
|
||||
{
|
||||
foreach (var item in resultsetItem)
|
||||
{
|
||||
tagSenders.Add(((KeyValuePair<string, object>)item).Key, int.Parse(((KeyValuePair<string, object>)item).Value.ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tagSenders;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CELA_Knowledge_Management_Data_Services.BusinessLogic
|
||||
{
|
||||
public class GraphQueryBusinessLogic
|
||||
{
|
||||
|
||||
public static string CreatePropertyClauseForGraphQuery(KeyValuePair<string, string> Property)
|
||||
{
|
||||
if (Int32.TryParse(Property.Value, out int intValue) || Double.TryParse(Property.Value, out double doubleValue))
|
||||
{
|
||||
return String.Format(".property('{0}', {1})", Property.Key, Property.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return String.Format(".property('{0}', '{1}')", Property.Key, ConformStringForQuery(Property.Value));
|
||||
}
|
||||
}
|
||||
|
||||
public static string ConformStringForQuery(string Value, bool MakeLowerCase = true, bool RemoveReservedCharacters = true, string ReplacementCharacters = "")
|
||||
{
|
||||
if (Value != null && Value.Length > 0)
|
||||
{
|
||||
if (MakeLowerCase)
|
||||
{
|
||||
Value = Value.ToLower();
|
||||
}
|
||||
if (RemoveReservedCharacters)
|
||||
{
|
||||
Value = Value.Replace("#", ReplacementCharacters);
|
||||
//Value = Value.Replace("/", ReplacementCharacters);
|
||||
Value = Value.Replace("'", ReplacementCharacters);
|
||||
Value = Value.Replace("?", ReplacementCharacters);
|
||||
Value = Value.Replace("$", ReplacementCharacters);
|
||||
Value = Value.Replace("&", ReplacementCharacters);
|
||||
}
|
||||
}
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
|
||||
public static string CreateVertexIfDoesNotExistGraphQuery(string VertexType, string Name, string GUID, Dictionary<string, string> Properties = null, string PartitionName = null)
|
||||
{
|
||||
// TODO Add code that cleans up the property values to remove problematic characters
|
||||
|
||||
var query = new StringBuilder();
|
||||
query.Append(String.Format("g.V().has('{0}', '{3}', '{1}').fold().coalesce(unfold(), addV('{0}').property('{3}', '{1}').property('{4}', '{2}')", VertexType, ConformStringForQuery(Name), GUID, CommunicationProcessingBusinessLogic.VertexNameProperty, CommunicationProcessingBusinessLogic.VertexIDProperty));
|
||||
|
||||
if (PartitionName != null && PartitionName.Length > 0)
|
||||
{
|
||||
if (Properties == null)
|
||||
{
|
||||
Properties = new Dictionary<string, string>();
|
||||
}
|
||||
Properties.Add(CommunicationProcessingBusinessLogic.GraphPartitionKeyProperty, ConformStringForQuery(PartitionName));
|
||||
}
|
||||
|
||||
if (Properties != null && Properties.Keys.Count > 0)
|
||||
{
|
||||
foreach (var Property in Properties)
|
||||
{
|
||||
query.Append(CreatePropertyClauseForGraphQuery(Property));
|
||||
}
|
||||
}
|
||||
|
||||
query.Append(")");
|
||||
return query.ToString();
|
||||
}
|
||||
|
||||
public static string CreateAddVertexGraphQuery(string Key, string VertexType, string GUID, string PartitionName)
|
||||
{
|
||||
var query = new StringBuilder();
|
||||
query.Append(String.Format("g.addV('{0}').property('id', '{1}').property('guid', '{2}')", VertexType, Key, GUID));
|
||||
|
||||
if (PartitionName != null && PartitionName.Length > 0)
|
||||
{
|
||||
query.Append(String.Format(".property('partitionKey', '{0}')", PartitionName));
|
||||
}
|
||||
|
||||
return query.ToString();
|
||||
}
|
||||
|
||||
public static string CreateAddEdgeGraphQuery(string FromVertexID, string ToVertexID, string EdgeLabel, Dictionary<string, string> Properties)
|
||||
{
|
||||
StringBuilder queryBuilder = new StringBuilder();
|
||||
queryBuilder.Append( string.Format("g.V('{0}').addE('{2}').to(g.V('{1}')", FromVertexID, ToVertexID, EdgeLabel));
|
||||
if (Properties != null && Properties.Count >0)
|
||||
{
|
||||
foreach (var property in Properties)
|
||||
{
|
||||
queryBuilder.Append(CreatePropertyClauseForGraphQuery(property));
|
||||
}
|
||||
}
|
||||
queryBuilder.Append(")");
|
||||
return queryBuilder.ToString();
|
||||
}
|
||||
|
||||
public static string CreateRetrieveVertexGraphQuery(string VertexLabel, string PropertyName, string PropertyValue)
|
||||
{
|
||||
return string.Format("g.V().haslabel('{0}').has('{1}', '{2}')", VertexLabel, PropertyName, PropertyValue);
|
||||
}
|
||||
|
||||
public static string CreateRetrieveEdgeGraphQuery(string FromVertexID, string ToVertexID, string EdgeLabel)
|
||||
{
|
||||
return string.Format("g.V().has('id', '{0}').outE().as ('e').has('label', '{2}').inV().has('id', '{1}').select('e')", FromVertexID, ToVertexID, EdgeLabel);
|
||||
}
|
||||
|
||||
public static string CreateUpdateEdgeGraphQuery(string FromVertexID, string ToVertexID, string EdgeLabel, Dictionary<string, string> Properties)
|
||||
{
|
||||
StringBuilder queryBuilder = new StringBuilder();
|
||||
queryBuilder.Append(CreateRetrieveEdgeGraphQuery(FromVertexID, ToVertexID, EdgeLabel));
|
||||
if (Properties != null && Properties.Count > 0)
|
||||
{
|
||||
foreach (var property in Properties)
|
||||
{
|
||||
queryBuilder.Append(CreatePropertyClauseForGraphQuery(property));
|
||||
}
|
||||
}
|
||||
queryBuilder.Append(".iterate()");
|
||||
return queryBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Creates the sender recipient graph query.</summary>
|
||||
/// <param name="SenderID">The sender identifier.</param>
|
||||
/// <param name="RecipientID">The recipient identifier.</param>
|
||||
/// <returns></returns>
|
||||
public static string CreateSenderRecipientEdgeGraphQuery(string SenderID, string RecipientID)
|
||||
{
|
||||
return string.Format("g.V('{0}').addE('sends').to(g.V('{1}'))", SenderID, RecipientID);
|
||||
}
|
||||
|
||||
/// <summary>Creates the sender tag graph query.</summary>
|
||||
/// <param name="SenderID">The sender identifier.</param>
|
||||
/// <param name="TagID">The tag identifier.</param>
|
||||
/// <returns></returns>
|
||||
public static string CreateSenderTagEdgeGraphQuery(string SenderID, string TagID)
|
||||
{
|
||||
return string.Format("g.V('{0}').addE('sends').to(g.V('{1}'))", SenderID, TagID);
|
||||
}
|
||||
|
||||
/// <summary>Creates the tag recipient graph query.</summary>
|
||||
/// <param name="TagID">The tag identifier.</param>
|
||||
/// <param name="RecipientID">The recipient identifier.</param>
|
||||
/// <returns></returns>
|
||||
public static string CreateTagRecipientEdgeGraphQuery(string TagID, string RecipientID)
|
||||
{
|
||||
return string.Format("g.V('{0}').addE('sends').to(g.V('{1}'))", TagID, RecipientID);
|
||||
}
|
||||
|
||||
/// <summary>Gets the topic senders graph query.</summary>
|
||||
/// <param name="topic">The topic.</param>
|
||||
/// <returns></returns>
|
||||
public static string GetTopicSendersGraphQuery(string topic)
|
||||
{
|
||||
return string.Format("g.V().has('name', '{0}').inE('relates to').outV().inE('sends').outV().project('a').by('name').select('a').dedup()", topic);
|
||||
|
||||
//return string.Format("g.V().has('name', '{0}').inE('relates to').outV().inE('sends').outV()", topic);
|
||||
//return string.Format("g.V('{0}').inE('sender').order().by('sent', decr)", topic);
|
||||
}
|
||||
|
||||
public static string GetTopicSendersGraphQueryWithSentValues(string topic)
|
||||
{
|
||||
return string.Format("g.V().has('name', '{0}').inE('relates to').outV().inE('sends').outV().project('a').by('name').select('a').groupCount()", topic);
|
||||
}
|
||||
|
||||
public static string GetMattersGraphQuery()
|
||||
{
|
||||
return string.Format("g.V().haslabel('{0}')", CommunicationProcessingBusinessLogic.MatterVertexLabel);
|
||||
}
|
||||
|
||||
public static string GetDocumentsForTagGraphQuery(string tag)
|
||||
{
|
||||
return string.Format("g.V().haslabel('{1}').has('{2}', '{0}').inE().has('label', '{3}').outV().outE().inV().haslabel('{4}')", tag, CommunicationProcessingBusinessLogic.TagVertexLabel, CommunicationProcessingBusinessLogic.VertexNameProperty, CommunicationProcessingBusinessLogic.CommunicationTagEdgeLabel, CommunicationProcessingBusinessLogic.DocumentVertexLabel);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<RootNamespace>CELA_Knowledge_Management_Data_Services</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Gremlin.Net" Version="3.4.0" />
|
||||
<PackageReference Include="Microsoft.Bot.Builder" Version="4.1.5" />
|
||||
<PackageReference Include="WindowsAzure.Storage" Version="9.3.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
Двоичные данные
CELA-Knowledge_Management_Data_Services/DataUtilities/AzureTableDataUtilities.cs
Normal file
Двоичные данные
CELA-Knowledge_Management_Data_Services/DataUtilities/AzureTableDataUtilities.cs
Normal file
Двоичный файл не отображается.
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CELA_Knowledge_Management_Data_Services.DataUtilities
|
||||
{
|
||||
public interface IGraphConfiguration
|
||||
{
|
||||
string GetGraphDatabaseHostname();
|
||||
string GetGraphDatabaseAccessKey();
|
||||
string GetGraphDatabaseCollectionName();
|
||||
string GetGraphDatabaseName();
|
||||
int GetGraphDatabasePort();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CELA_Knowledge_Management_Data_Services.DataUtilities
|
||||
{
|
||||
public interface ITableConfiguration
|
||||
{
|
||||
string GetTableAccessKey();
|
||||
string GetTableHostname();
|
||||
string GetTableName();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
using Microsoft.Bot.Builder;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CELA_Knowledge_Management_Data_Services.DataUtilities
|
||||
{
|
||||
public class LUISDataUtilities
|
||||
{
|
||||
// Based upon https://pauliom.com/2018/11/06/extracting-an-entity-from-luis-in-bot-framework/
|
||||
public static int GetNumberEntityAsInt(RecognizerResult luisResult, string entityKey, string valuePropertyName = "text")
|
||||
{
|
||||
int number = -1;
|
||||
if (luisResult != null)
|
||||
{
|
||||
var data = luisResult.Entities as IDictionary<string, JToken>;
|
||||
|
||||
if (data.TryGetValue("number", out JToken value))
|
||||
{
|
||||
int.TryParse(value.First.ToString(), out number);
|
||||
}
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
public static string GetEntityAsString(RecognizerResult luisResult, string ValuePropertyName = "text")
|
||||
{
|
||||
string returnValue = "";
|
||||
if (luisResult != null)
|
||||
{
|
||||
var data = luisResult.Entities as IDictionary<string, JToken>;
|
||||
|
||||
if (data.TryGetValue(ValuePropertyName, out JToken value))
|
||||
{
|
||||
if (value.First != null)
|
||||
{
|
||||
returnValue = value.First.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
using Microsoft.WindowsAzure.Storage.Table;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CELA_Knowledge_Management_Data_Services.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// An object that encapsulates the behaviors related to parsing an email for tag usage.
|
||||
/// </summary>
|
||||
public abstract class EmailSearch : TableEntity
|
||||
{
|
||||
private string emailSender;
|
||||
private string emailSentTime;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to exclude prior emails that may be in the text string from search function. Note that this only works on English emails because the parsing function is pretty simple, and breaks chunks on indicators like "From:".
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if exclude prior emails from search; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool ExcludePriorEmailsFromSearch { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to remove duplicate tags found from the response.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if remove duplicates; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool RemoveDuplicates { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether persist results server side, thus negating the need to persist results by the caller.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if persist results server side; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool PersistResultsServerSide { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email sender's email address.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email sender.
|
||||
/// </value>
|
||||
public string EmailSender
|
||||
{ get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email sent time (ZULU).
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email sent time.
|
||||
/// </value>
|
||||
public string EmailSentTime
|
||||
{ get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email To line recipients' email addresses.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email to recipients.
|
||||
/// </value>
|
||||
public string EmailToRecipients { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the email Cc line recipients's email addresses.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email cc recipients.
|
||||
/// </value>
|
||||
public string EmailCcRecipients { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email subject.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email subject.
|
||||
/// </value>
|
||||
public string EmailSubject { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email body text.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email body text.
|
||||
/// </value>
|
||||
public string EmailBodyText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email sender organization.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email sender organization.
|
||||
/// </value>
|
||||
public string EmailSenderOrganization { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email sender team.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email sender team.
|
||||
/// </value>
|
||||
public string EmailSenderTeam { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email sender group.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email sender group.
|
||||
/// </value>
|
||||
public string EmailSenderGroup { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email message identifier.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email message identifier.
|
||||
/// </value>
|
||||
public string EmailMessageId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email conversation identifier.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email conversation identifier.
|
||||
/// </value>
|
||||
public string EmailConversationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email tag cluster, a string with all of the tags used, each separated by a space.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The email tag cluster.
|
||||
/// </value>
|
||||
public string EmailTagCluster { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the API version recorded in the client tier.</summary>
|
||||
/// <value>The API version.</value>
|
||||
public string APIVersion { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the service API version.</summary>
|
||||
/// <value>The service API version.</value>
|
||||
public string ServiceAPIVersion { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the reference key used to correlate this with other knowledge management artifacts.</summary>
|
||||
/// <value>The reference key.</value>
|
||||
public string ReferenceKey { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the matter identifier.</summary>
|
||||
/// <value>The matter identifier.</value>
|
||||
public string MatterId { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the tag start token used to denote tag starts.</summary>
|
||||
/// <value>The tag start token.</value>
|
||||
public string TagStartToken { get; set; }
|
||||
}
|
||||
|
||||
public class TagSearchByDeclaredTag : EmailSearch
|
||||
{
|
||||
public TagSearchByDeclaredTag(string emailAddress, string emailSentTime)
|
||||
{
|
||||
this.PartitionKey = emailAddress;
|
||||
this.RowKey = emailSentTime;
|
||||
}
|
||||
|
||||
public string Tag { get; set; }
|
||||
}
|
||||
|
||||
public class TagsSearchByTagStartToken : EmailSearch
|
||||
{
|
||||
public TagsSearchByTagStartToken(string emailAddress, string emailSentTime)
|
||||
{
|
||||
this.PartitionKey = emailAddress;
|
||||
this.RowKey = emailSentTime;
|
||||
}
|
||||
|
||||
public bool OnlyReturnMatterTags { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>A custom subclass of EmailSearch used to enable ordinal searches of email text (sequenced tags).</summary>
|
||||
public class TagsSearchByTagStartTokenOrdinal : EmailSearch
|
||||
{
|
||||
public TagsSearchByTagStartTokenOrdinal()
|
||||
{
|
||||
}
|
||||
/// <summary>Initializes a new instance of the <see cref="TagsSearchByTagStartTokenOrdinal"/> class.</summary>
|
||||
/// <param name="emailAddress">The email address.</param>
|
||||
/// <param name="emailSentTime">The email sent time.</param>
|
||||
public TagsSearchByTagStartTokenOrdinal(string emailAddress, string emailSentTime)
|
||||
{
|
||||
this.PartitionKey = emailAddress;
|
||||
this.RowKey = emailSentTime;
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the size of the minimum tag set expected to be found.</summary>
|
||||
/// <value>The size of the tag set.</value>
|
||||
public string TagSetSize { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the ordinal email tag cluster found by the search.</summary>
|
||||
/// <value>The email tag cluster ordinal.</value>
|
||||
public string EmailTagClusterOrdinal { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
using CELA_Knowledge_Management_Data_Services.BusinessLogic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CELA_Knowledge_Management_Data_Services.Models
|
||||
{
|
||||
public class CommunicationGraphModel
|
||||
{
|
||||
public CommunicationGraphModel()
|
||||
{ }
|
||||
|
||||
public CommunicationGraphModel(EmailSearch Communication)
|
||||
{
|
||||
if (Communication.EmailSender != null && Communication.EmailSender.Length > 0)
|
||||
{
|
||||
CommunicationSender = Communication.EmailSender.ToLower();
|
||||
}
|
||||
if (Communication.EmailToRecipients != null && Communication.EmailToRecipients.Length > 0)
|
||||
{
|
||||
ToRecipients = CommunicationProcessingBusinessLogic.ParseConcatenatedString(Communication.EmailToRecipients, CommunicationAddressDelimiter);
|
||||
}
|
||||
if (Communication.EmailCcRecipients != null && Communication.EmailCcRecipients.Length > 0)
|
||||
{
|
||||
CcRecipients = CommunicationProcessingBusinessLogic.ParseConcatenatedString(Communication.EmailCcRecipients, CommunicationAddressDelimiter);
|
||||
}
|
||||
if (Communication.EmailTagCluster != null && Communication.EmailTagCluster.Length > 0)
|
||||
{
|
||||
Tags = CommunicationProcessingBusinessLogic.ParseConcatenatedString(Communication.EmailTagCluster, TagDelimiter);
|
||||
}
|
||||
}
|
||||
|
||||
public const string CommunicationAddressDelimiter = ";";
|
||||
public const string TagDelimiter = " ";
|
||||
|
||||
public string CommunicationSender { get; set; }
|
||||
public List<string> ToRecipients { get; set; }
|
||||
public List<string> CcRecipients { get; set; }
|
||||
public List<string> Tags { get; set; }
|
||||
}
|
||||
|
||||
public class TagRecipients
|
||||
{
|
||||
public TagRecipient[] Recipients { get; set; }
|
||||
}
|
||||
|
||||
public class TagRecipient
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string label { get; set; }
|
||||
public string type { get; set; }
|
||||
public string inVLabel { get; set; }
|
||||
public string outVLabel { get; set; }
|
||||
public string inV { get; set; }
|
||||
public string outV { get; set; }
|
||||
public TagRecipientProperties properties { get; set; }
|
||||
}
|
||||
|
||||
public class TagRecipientProperties
|
||||
{
|
||||
public int primaryrecipient { get; set; }
|
||||
public int secondaryrecipient { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class TagSenders
|
||||
{
|
||||
public TagSender[] Senders { get; set; }
|
||||
}
|
||||
|
||||
public class TagSender
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string label { get; set; }
|
||||
public string type { get; set; }
|
||||
public string inVLabel { get; set; }
|
||||
public string outVLabel { get; set; }
|
||||
public string inV { get; set; }
|
||||
public string outV { get; set; }
|
||||
public TagSenderProperties properties { get; set; }
|
||||
}
|
||||
|
||||
public class TagSenderProperties
|
||||
{
|
||||
public int sent { get; set; }
|
||||
}
|
||||
|
||||
public class Document
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string name { get; set; }
|
||||
public string type { get; set; }
|
||||
public string sharepointlibrary { get; set; }
|
||||
public string sharepointlibrarypath { get; set; }
|
||||
public string referenceKey { get; set; }
|
||||
public string matter { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CELA_Knowledge_Management_Data_Services.Models
|
||||
{
|
||||
public class DocumentGraphModelList : List<DocumentGraphModel>
|
||||
{
|
||||
}
|
||||
|
||||
//public class Rootobject
|
||||
//{
|
||||
// public Class1[] Property1 { get; set; }
|
||||
//}
|
||||
|
||||
public class DocumentGraphModel
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string label { get; set; }
|
||||
public string type { get; set; }
|
||||
public DocumentGraphModelProperties properties { get; set; }
|
||||
}
|
||||
|
||||
public class DocumentGraphModelProperties
|
||||
{
|
||||
public DocumentGraphModelName[] name { get; set; }
|
||||
public DocumentGraphModelType[] type { get; set; }
|
||||
public Library[] library { get; set; }
|
||||
public Path[] path { get; set; }
|
||||
public DocumentGraphModelKey[] key { get; set; }
|
||||
}
|
||||
|
||||
public class DocumentGraphModelName
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string value { get; set; }
|
||||
}
|
||||
|
||||
public class DocumentGraphModelType
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string value { get; set; }
|
||||
}
|
||||
|
||||
public class Library
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string value { get; set; }
|
||||
}
|
||||
|
||||
public class Path
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string value { get; set; }
|
||||
}
|
||||
|
||||
public class DocumentGraphModelKey
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string value { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CELA_Knowledge_Management_Data_Services.Models
|
||||
{
|
||||
|
||||
public class MatterGraphModel : List<Matter>
|
||||
{
|
||||
}
|
||||
|
||||
public class Matter
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string label { get; set; }
|
||||
public string type { get; set; }
|
||||
public Properties properties { get; set; }
|
||||
}
|
||||
|
||||
public class Properties
|
||||
{
|
||||
public Name[] name { get; set; }
|
||||
}
|
||||
|
||||
public class Name
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string value { get; set; }
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{A93C0E6A-6AFE-4F64-B735-0CF8119AD021}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>CELA_Knowledge_Management_Models</RootNamespace>
|
||||
<AssemblyName>CELA-Knowledge_Management_Models</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="KMArtifact.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CELA_Knowledge_Management_Models
|
||||
{
|
||||
class KMArtifact
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("CELA-Knowledge_Management_Models")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("CELA-Knowledge_Management_Models")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("a93c0e6a-6afe-4f64-b735-0cf8119ad021")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// 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("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CELA_Knowledge_Managment.BusinessLogic
|
||||
{
|
||||
public class MatterIdentificationBL
|
||||
{
|
||||
public const string MatterPrefix = "mid-";
|
||||
|
||||
public static bool ValidateMatterID(string TagStartToken,string MatterID)
|
||||
{
|
||||
//Example MID-04327-G4V9J7
|
||||
if (MatterID.ToLower().StartsWith(TagStartToken + MatterPrefix))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{4F7269FB-67B7-465F-BF25-7ECD70407896}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>CELA_Knowledge_Managment</RootNamespace>
|
||||
<AssemblyName>CELA-Knowledge_Managment</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BusinessLogic\MatterIdentificationBL.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("CELA-Knowledge_Managment")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("CELA-Knowledge_Managment")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("4f7269fb-67b7-465f-bf25-7ecd70407896")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// 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("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,85 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CELA-Tags_Service_Models", "CELA-Tags_Service_Models\CELA-Tags_Service_Models.csproj", "{8556D4E4-0D3B-4531-B80C-893B1217F839}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CELA-Tags_Parsing_Service", "CELA-Tags_Parsing_Service\CELA-Tags_Parsing_Service.csproj", "{78E19CDA-49E8-4233-9BB1-16D6E712D560}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CELA-Tags_Parsing_ServiceTests", "CELA-Tags_Parsing_ServiceTests\CELA-Tags_Parsing_ServiceTests.csproj", "{6A9BC29F-9B35-420A-92F4-A8DCEC9C64F0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CELA_Tags_Parsing_ServiceTestUtilities", "CELA_Tags_Parsing_ServiceTestUtilities\CELA_Tags_Parsing_ServiceTestUtilities.csproj", "{9B8DF1AA-85B1-4A60-8BC8-A66AEFE91C47}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CELA-Knowledge_Management_Models", "CELA-Knowledge_Management_Models\CELA-Knowledge_Management_Models.csproj", "{A93C0E6A-6AFE-4F64-B735-0CF8119AD021}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CELA-Knowledge_Managment", "CELA-Knowledge_Managment\CELA-Knowledge_Managment.csproj", "{4F7269FB-67B7-465F-BF25-7ECD70407896}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CELA-Knowledge_Management_Assistant", "CELA-Knowledge_Management_Assistant\CELA-Knowledge_Management_Assistant.csproj", "{8739C9C7-06D4-4053-A469-B4BF7C4BC556}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CELA_Tag_Hive_Graph_Data_Processing", "CELA-Tag_Hive_Data_Processing\CELA_Tag_Hive_Graph_Data_Processing.csproj", "{3AD4D3B7-7252-43DA-8D58-79A91ED8BFFE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CELA-Knowledge_Management_Data_Services", "CELA-Knowledge_Management_Data_Services\CELA-Knowledge_Management_Data_Services.csproj", "{6D8BC8A4-9750-4560-A544-7E53CD47948D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CELA-Knowledge_Management_Data_Servicestests", "CELA-Knowledge_Management_Data_Services.tests\CELA-Knowledge_Management_Data_Servicestests.csproj", "{C58D9225-E2A2-417C-8745-D78A091BAB72}"
|
||||
EndProject
|
||||
Project("{F5034706-568F-408A-B7B3-4D38C6DB8A32}") = "CELA-Tag_Parsing_Service_Configuration_Utilities", "CELA-Tag_Parsing_Service_Configuration_Utilities\CELA-Tag_Parsing_Service_Configuration_Utilities.pssproj", "{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{8556D4E4-0D3B-4531-B80C-893B1217F839}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8556D4E4-0D3B-4531-B80C-893B1217F839}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8556D4E4-0D3B-4531-B80C-893B1217F839}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8556D4E4-0D3B-4531-B80C-893B1217F839}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{78E19CDA-49E8-4233-9BB1-16D6E712D560}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{78E19CDA-49E8-4233-9BB1-16D6E712D560}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{78E19CDA-49E8-4233-9BB1-16D6E712D560}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{78E19CDA-49E8-4233-9BB1-16D6E712D560}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6A9BC29F-9B35-420A-92F4-A8DCEC9C64F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6A9BC29F-9B35-420A-92F4-A8DCEC9C64F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6A9BC29F-9B35-420A-92F4-A8DCEC9C64F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6A9BC29F-9B35-420A-92F4-A8DCEC9C64F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9B8DF1AA-85B1-4A60-8BC8-A66AEFE91C47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9B8DF1AA-85B1-4A60-8BC8-A66AEFE91C47}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9B8DF1AA-85B1-4A60-8BC8-A66AEFE91C47}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9B8DF1AA-85B1-4A60-8BC8-A66AEFE91C47}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A93C0E6A-6AFE-4F64-B735-0CF8119AD021}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A93C0E6A-6AFE-4F64-B735-0CF8119AD021}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A93C0E6A-6AFE-4F64-B735-0CF8119AD021}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A93C0E6A-6AFE-4F64-B735-0CF8119AD021}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4F7269FB-67B7-465F-BF25-7ECD70407896}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4F7269FB-67B7-465F-BF25-7ECD70407896}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4F7269FB-67B7-465F-BF25-7ECD70407896}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4F7269FB-67B7-465F-BF25-7ECD70407896}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8739C9C7-06D4-4053-A469-B4BF7C4BC556}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8739C9C7-06D4-4053-A469-B4BF7C4BC556}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8739C9C7-06D4-4053-A469-B4BF7C4BC556}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8739C9C7-06D4-4053-A469-B4BF7C4BC556}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3AD4D3B7-7252-43DA-8D58-79A91ED8BFFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3AD4D3B7-7252-43DA-8D58-79A91ED8BFFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3AD4D3B7-7252-43DA-8D58-79A91ED8BFFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3AD4D3B7-7252-43DA-8D58-79A91ED8BFFE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6D8BC8A4-9750-4560-A544-7E53CD47948D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6D8BC8A4-9750-4560-A544-7E53CD47948D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6D8BC8A4-9750-4560-A544-7E53CD47948D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6D8BC8A4-9750-4560-A544-7E53CD47948D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C58D9225-E2A2-417C-8745-D78A091BAB72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C58D9225-E2A2-417C-8745-D78A091BAB72}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C58D9225-E2A2-417C-8745-D78A091BAB72}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C58D9225-E2A2-417C-8745-D78A091BAB72}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6CAFC0C6-A428-4D30-A9F9-700E829FEA51}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {85904322-8A45-4773-8781-BC14400EB7FB}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
|
@ -0,0 +1,24 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Gremlin.Net" Version="3.4.0" />
|
||||
<PackageReference Include="Microsoft.Azure.CosmosDB.BulkExecutor" Version="1.4.0" />
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="WindowsAzure.Storage" Version="9.3.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CELA-Knowledge_Management_Data_Services\CELA-Knowledge_Management_Data_Services.csproj" />
|
||||
<ProjectReference Include="..\CELA-Tags_Parsing_Service\CELA-Tags_Parsing_Service.csproj" />
|
||||
<ProjectReference Include="..\CELA-Tags_Service_Models\CELA-Tags_Service_Models.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,57 @@
|
|||
https://github.com/tinkerpop/gremlin/wiki/Gremlin-Steps
|
||||
http://tinkerpop.apache.org/docs/3.1.0-incubating/tutorials-getting-started.html
|
||||
|
||||
// Get a vertex
|
||||
g.V('testemail@microsoft.com')
|
||||
|
||||
// Get all communicators
|
||||
g.V().hasLabel('communicator').values('id')
|
||||
|
||||
// Get all tags
|
||||
g.V().hasLabel('tag')
|
||||
|
||||
// Get all tags, only showing the id field
|
||||
g.V().hasLabel('tag').values('id')
|
||||
|
||||
// Get a specific tag
|
||||
g.V().hasLabel('tag').has('id', eq('tagulous'))
|
||||
|
||||
g.V('testemail@microsoft.com').outE('sends').inV().hasLabel('tag')
|
||||
|
||||
// Get the most commonly sent tags
|
||||
g.V().outE("sender").order().by('sent', decr)
|
||||
|
||||
|
||||
// Get all edges labeled recipient
|
||||
g.V().inE("recipient")
|
||||
|
||||
// Get all edges
|
||||
g.E()
|
||||
|
||||
// Get all of the communicators who have received a tag from the sender
|
||||
g.V('testemail@microsoft.com').out().hasLabel('tag').out().hasLabel('communicator')
|
||||
|
||||
|
||||
//Get the communicators who receive the most repeat tag exposure
|
||||
g.E().hasLabel('recipient').has('primary recipient', gt(1))
|
||||
|
||||
//Get the edges that branch off "diversity" vertex
|
||||
g.V("diversity").outE("recipient").has('primary recipient', gt(1))
|
||||
//Get the vertices that branch off "diversity" vertex
|
||||
g.V("diversity").outE("recipient").has('primary recipient', gt(1)).inV()
|
||||
|
||||
// Does not currently work
|
||||
|
||||
// Should get all of the recipients of the selected tag
|
||||
g.V().hasLabel('tag').has('id', eq('tagulous')).outE('primary recipient').inV().hasLabel('communicator')
|
||||
|
||||
//Graph Version 2
|
||||
|
||||
//Get the people who send emails containing the tag the most
|
||||
g.V().has('name', '{0}').inE('relates to').outV().inE('sends').outV().project('a').by('name').select('a').groupCount()
|
||||
|
||||
//Get the list of tags
|
||||
g.V().haslabel('tag').project('name').by('name')
|
||||
|
||||
//Group the conversations that are associated with a conversation id
|
||||
g.V().has('label', 'communication').project('a').by('conversation id').select('a').groupCount()
|
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CELA_Tag_Hive_Graph_Data_Processing
|
||||
{
|
||||
public class TagRecipients
|
||||
{
|
||||
public TagRecipient[] Recipients { get; set; }
|
||||
}
|
||||
|
||||
public class TagRecipient
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string label { get; set; }
|
||||
public string type { get; set; }
|
||||
public string inVLabel { get; set; }
|
||||
public string outVLabel { get; set; }
|
||||
public string inV { get; set; }
|
||||
public string outV { get; set; }
|
||||
public TagRecipientProperties properties { get; set; }
|
||||
}
|
||||
|
||||
public class TagRecipientProperties
|
||||
{
|
||||
public int primaryrecipient { get; set; }
|
||||
public int secondaryrecipient { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class TagSenders
|
||||
{
|
||||
public TagSender[] Senders { get; set; }
|
||||
}
|
||||
|
||||
public class TagSender
|
||||
{
|
||||
public string id { get; set; }
|
||||
public string label { get; set; }
|
||||
public string type { get; set; }
|
||||
public string inVLabel { get; set; }
|
||||
public string outVLabel { get; set; }
|
||||
public string inV { get; set; }
|
||||
public string outV { get; set; }
|
||||
public TagSenderProperties properties { get; set; }
|
||||
}
|
||||
|
||||
public class TagSenderProperties
|
||||
{
|
||||
public int sent { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
Двоичный файл не отображается.
|
@ -0,0 +1,33 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("GremlinNetSample")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("GremlinNetSample.Properties")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("9c5203da-7f12-4f74-a5e2-220cb9c79aa2")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,107 @@
|
|||
function GetDeployment($requestedConfiguration, $configurations)
|
||||
{
|
||||
#Iterate over the loaded configurations
|
||||
foreach ($configuration in $configurations.psobject.Properties)
|
||||
{
|
||||
#Return the configuration that matches the request
|
||||
if ($requestedConfiguration -eq $configuration.Value.ConfigurationDeploymentType)
|
||||
{
|
||||
return $configuration.Value
|
||||
}
|
||||
}
|
||||
$error = [string]::Concat('Could not find configuration of type "', $requestedConfiguration,'"')
|
||||
Write-Error $error
|
||||
return $null
|
||||
}
|
||||
|
||||
function ProcessStringReplacementsIntoFiles($files, $currentDeployment, $requestedDeployment, $verbose = $false)
|
||||
{
|
||||
#Set the filepath tokens to be excluded
|
||||
$filepathExclusions = @('CELA-Tag_Parsing_Service_Configuration_Utilities','.git','.vs','\bin','\obj','CELA_Tag_Services_Deployment_Configurations.json','CELA-Tagulous_Parsing_Service-Utils.ps1', 'HomeController.cs', 'TestRequest', 'TestEmails')
|
||||
$configurationPropertyTypeExclusions = @('ConfigurationDeploymentType','ConfigurationDeploymentTypeDescription')
|
||||
|
||||
foreach ($file in $files)
|
||||
{
|
||||
if ($verbose)
|
||||
{
|
||||
[string]::Concat('Processing ', $file.PSPath,'.')
|
||||
}
|
||||
|
||||
#Do not process files that should be excluded
|
||||
if ($null -eq ($filepathExclusions | ? { $file.PSPath -match [Regex]::Escape($_) }))
|
||||
{
|
||||
#[string]::Concat('Would change ', $file.PSPath,'.')
|
||||
|
||||
$content = Get-Content $file.PSPath
|
||||
#Only process files that have content
|
||||
if (![string]::IsNullOrEmpty($content))
|
||||
{
|
||||
$fileUpdatesAvailable = $false
|
||||
#Iterate over each property in the deployment descriptors
|
||||
foreach ($property in $currentDeployment.psobject.Properties)
|
||||
{
|
||||
#Skip the properties that are metadata, and not values to be replaced
|
||||
if ($null -eq ($configurationPropertyTypeExclusions | ? { $property.Name -match $_ }))
|
||||
{
|
||||
#Get the old property values (to find) and new property values (to be replaced)
|
||||
$oldValue = $currentDeployment | Select -ExpandProperty $property.Name
|
||||
$newValue = $requestedDeployment | Select -ExpandProperty $property.Name
|
||||
$match = $content -match [Regex]::Escape($oldValue)
|
||||
if (![string]::IsNullOrEmpty($match))
|
||||
{
|
||||
if ($verbose)
|
||||
{
|
||||
[string]::Concat("`tFrom: ", $oldValue)
|
||||
[string]::Concat("`tTo: ", $newValue)
|
||||
[string]::Concat("`tContext: ",$match)
|
||||
''
|
||||
}
|
||||
$content = $content.replace($oldValue, $newValue)
|
||||
$fileUpdatesAvailable = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
#Only update the file if changes are available
|
||||
if ($fileUpdatesAvailable)
|
||||
{
|
||||
[string]::Concat("Updating file: ", $file.PSPath)
|
||||
$content | Out-File -filepath $file.PSPath
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$fileTypesToUpdate = @('*.bot','*.config','*.cs','*.json','*.resx')
|
||||
|
||||
'Welcome to CELA Tagulous Parsing Service Utilities.'
|
||||
[string]::Concat('This application will update the files of type ', $fileTypesToUpdate,' for the specified deployment type.')
|
||||
|
||||
#Note that you must customize your own copy of CELA_Tag_Services_Deployment_Configurations_(template).json
|
||||
$deploymentConfigurationFileName = 'CELA_Tag_Services_Deployment_Configurations.json'
|
||||
$deploymentConfigurationFileNameDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$deploymentConfigurationSearchDirectory = Split-Path -Path $deploymentConfigurationFileNameDirectory -Parent
|
||||
$deploymentConfigurationFilePath = Join-Path $deploymentConfigurationFileNameDirectory $deploymentConfigurationFileName
|
||||
$deploymentConfigurations = Get-Content $deploymentConfigurationFilePath | ConvertFrom-Json
|
||||
|
||||
'Loaded configurations include:'
|
||||
"`tType`tDescription"
|
||||
|
||||
foreach ($property in $deploymentConfigurations.psobject.Properties)
|
||||
{
|
||||
[string]::Concat("`t",$property.Value.ConfigurationDeploymentType, "`t", $property.Value.ConfigurationDeploymentTypeDescription)
|
||||
}
|
||||
|
||||
$deploymentConfigurationTypeCurrent = Read-Host -Prompt 'Please enter the current configuration type of your project (current state)'
|
||||
$deploymentConfigurationTypeRequested = Read-Host -Prompt 'Please enter the configuration type you want to apply to your project (desired future state)'
|
||||
|
||||
$deploymentConfigurationCurrent = GetDeployment $deploymentConfigurationTypeCurrent $deploymentConfigurations
|
||||
$deploymentConfigurationRequested = GetDeployment $deploymentConfigurationTypeRequested $deploymentConfigurations
|
||||
|
||||
if ($deploymentConfigurationCurrent -ne $null -and $deploymentConfigurationRequested -ne $null)
|
||||
{
|
||||
$files = Get-ChildItem -Path $deploymentConfigurationSearchDirectory -Recurse -Include $fileTypesToUpdate
|
||||
ProcessStringReplacementsIntoFiles $files $deploymentConfigurationCurrent $deploymentConfigurationRequested
|
||||
}
|
||||
|
||||
Write-Warning 'You should clean your solution after running this script.'
|
|
@ -0,0 +1,37 @@
|
|||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>6CAFC0C6-A428-4d30-A9F9-700E829FEA51</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>MyApplication</RootNamespace>
|
||||
<AssemblyName>MyApplication</AssemblyName>
|
||||
<Name>CELA-Tag_Parsing_Service_Configuration_Utilities</Name>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="CELA_Tag_Services_Deployment_Configurations_%28template%29.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CELA-Tag_Parsing_Service_Configuration_Utilities.ps1" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Target Name="Build" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\PowerShell Tools for Visual Studio\PowerShellTools.targets" Condition="Exists('$(MSBuildExtensionsPath)\PowerShell Tools for Visual Studio\PowerShellTools.targets')" />
|
||||
</Project>
|
|
@ -0,0 +1,86 @@
|
|||
{
|
||||
"NoneConfiguration": {
|
||||
"ConfigurationDeploymentType": "none",
|
||||
"ConfigurationDeploymentTypeDescription": "Configures the build to point to replacement tokens for future replacement with other configurations.",
|
||||
"BotAppPassword": "[BOT_APP_PASSWORD]",
|
||||
"BotSecret": "[BOT_SECRET]",
|
||||
"BotFileSecret": "[BOT_SECRET]",
|
||||
"BotLUISServiceIdentifier": "tagulous-luis",
|
||||
"BotLUISAppID": "[BOT_LUIS_APP_ID]",
|
||||
"BotLUISAuthoringKey": "[BOT_LUIS_AUTHORING_KEY]",
|
||||
"BotLUISSubscriptionKey": "[BOT_LUIS_SUBSCRIPTION_KEY]",
|
||||
"GraphDatabaseHostname": "[GRAPH_HOSTNAME]",
|
||||
"GraphDatabasePort": 443,
|
||||
"GraphDatabaseName": "[GRAPH_NAME]",
|
||||
"GraphDatabaseCollection": "[GRAPH_COLLECTION]",
|
||||
"GraphDatabaseAuthorizationKey": "[GRAPH_KEY]",
|
||||
"TableHostname": "[TABLE_HOSTNAME]",
|
||||
"TableName": "[TABLE_NAME]",
|
||||
"TableAccessKey": "[TABLE_KEY]"
|
||||
},
|
||||
"ProdConfiguration": {
|
||||
"ConfigurationDeploymentType": "prod",
|
||||
"ConfigurationDeploymentTypeDescription": "Configures the build to point to production resources.",
|
||||
"BotAppPassword": "[BOT_APP_PASSWORD]",
|
||||
"BotSecret": "[BOT_SECRET]",
|
||||
"BotFileSecret": "[BOT_SECRET]",
|
||||
"BotLUISServiceIdentifier": "tagulous-luis",
|
||||
"BotLUISAppID": "[BOT_LUIS_APP_ID]",
|
||||
"BotLUISAuthoringKey": "[BOT_LUIS_AUTHORING_KEY]",
|
||||
"BotLUISSubscriptionKey": "[BOT_LUIS_SUBSCRIPTION_KEY]",
|
||||
"GraphDatabaseHostname": "tagulous.gremlin.cosmosdb.azure.com",
|
||||
"GraphDatabasePort": 443,
|
||||
"GraphDatabaseName": "tagulous-database",
|
||||
"GraphDatabaseCollection": "tagulous-graph",
|
||||
"GraphDatabaseAuthorizationKey": "[GRAPH_KEY]",
|
||||
"TableHostname": "tagulous",
|
||||
"TableName": "tagulous",
|
||||
"TableAccessKey": "[TABLE_KEY]"
|
||||
},
|
||||
"TestConfiguration": {
|
||||
"ConfigurationDeploymentType": "test",
|
||||
"ConfigurationDeploymentTypeDescription": "Configures the build to point to testing resources.",
|
||||
"GraphDatabaseHostname": "taguloustest.gremlin.cosmosdb.azure.com",
|
||||
"GraphDatabasePort": 443,
|
||||
"GraphDatabaseName": "tagulous-database",
|
||||
"GraphDatabaseCollection": "tagulous-graph",
|
||||
"GraphDatabaseAuthorizationKey": "[GRAPH_KEY]",
|
||||
"TableHostname": "taguloustest",
|
||||
"TableName": "tagulous",
|
||||
"TableAccessKey": "[TABLE_KEY]",
|
||||
"BotSecret": "[BOT_SECRET]",
|
||||
"BotLUISServiceIdentifier": "tagulous-luis",
|
||||
"BotLUISAppID": "[BOT_LUIS_APP_ID]",
|
||||
"BotLUISAuthoringKey": "[BOT_LUIS_AUTHORING_KEY]",
|
||||
"BotLUISSubscriptionKey": "[BOT_LUIS_SUBSCRIPTION_KEY]"
|
||||
},
|
||||
"DemoConfiguration": {
|
||||
"ConfigurationDeploymentType": "demo",
|
||||
"ConfigurationDeploymentTypeDescription": "Configures the build to point to demonstration resources.",
|
||||
"BotAppPassword": "[BOT_APP_PASSWORD]",
|
||||
"BotSecret": "[BOT_SECRET]",
|
||||
"BotFileSecret": "[BOT_SECRET]",
|
||||
"BotLUISServiceIdentifier": "tagulous-luis",
|
||||
"BotLUISAppID": "[BOT_LUIS_APP_ID]",
|
||||
"BotLUISAuthoringKey": "[BOT_LUIS_AUTHORING_KEY]",
|
||||
"BotLUISSubscriptionKey": "[BOT_LUIS_SUBSCRIPTION_KEY]",
|
||||
"GraphDatabaseHostname": "tagulousdemo.gremlin.cosmosdb.azure.com",
|
||||
"GraphDatabasePort": 443,
|
||||
"GraphDatabaseName": "tagulous-database",
|
||||
"GraphDatabaseCollection": "tagulous-graph",
|
||||
"GraphDatabaseAuthorizationKey": "[GRAPH_KEY]",
|
||||
"TableHostname": "tagulousdemo",
|
||||
"TableName": "tagulous",
|
||||
"TableAccessKey": "[TABLE_KEY]",
|
||||
},
|
||||
"BotLocalConfiguration": {
|
||||
"ConfigurationDeploymentType": "botl",
|
||||
"ConfigurationDeploymentTypeDescription": "Configures the build for local bot deployment for testing.",
|
||||
"BotServiceEndpoint": "http://localhost/api/messages"
|
||||
},
|
||||
"BotRemoteConfiguration": {
|
||||
"ConfigurationDeploymentType": "botr",
|
||||
"ConfigurationDeploymentTypeDescription": "Configures the build for remote bot deployment for production and remote testing.",
|
||||
"BotServiceEndpoint": "http://[UPDATETHIS].azurewebsites.net/api/messages"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using System.Web;
|
||||
using System.Web.Optimization;
|
||||
|
||||
namespace CELA_Tags_Parsing_Service
|
||||
{
|
||||
public class BundleConfig
|
||||
{
|
||||
// For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862
|
||||
public static void RegisterBundles(BundleCollection bundles)
|
||||
{
|
||||
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
|
||||
"~/Scripts/jquery-{version}.js"));
|
||||
|
||||
// Use the development version of Modernizr to develop with and learn from. Then, when you're
|
||||
// ready for production, use the build tool at https://modernizr.com to pick only the tests you need.
|
||||
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
|
||||
"~/Scripts/modernizr-*"));
|
||||
|
||||
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
|
||||
"~/Scripts/bootstrap.js",
|
||||
"~/Scripts/respond.js"));
|
||||
|
||||
bundles.Add(new StyleBundle("~/Content/css").Include(
|
||||
"~/Content/bootstrap.css",
|
||||
"~/Content/site.css"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace CELA_Tags_Parsing_Service
|
||||
{
|
||||
public class FilterConfig
|
||||
{
|
||||
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
|
||||
{
|
||||
filters.Add(new ErrorHandler.AiHandleErrorAttribute());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
|
||||
namespace CELA_Tags_Parsing_Service
|
||||
{
|
||||
public class RouteConfig
|
||||
{
|
||||
public static void RegisterRoutes(RouteCollection routes)
|
||||
{
|
||||
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
|
||||
|
||||
routes.MapRoute(
|
||||
name: "Default",
|
||||
url: "{controller}/{action}/{id}",
|
||||
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
using System.Web.Http;
|
||||
using WebActivatorEx;
|
||||
using CELA_Tags_Parsing_Service;
|
||||
using Swashbuckle.Application;
|
||||
|
||||
[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
|
||||
|
||||
namespace CELA_Tags_Parsing_Service
|
||||
{
|
||||
public class SwaggerConfig
|
||||
{
|
||||
public static void Register()
|
||||
{
|
||||
var thisAssembly = typeof(SwaggerConfig).Assembly;
|
||||
|
||||
GlobalConfiguration.Configuration
|
||||
.EnableSwagger(c =>
|
||||
{
|
||||
// By default, the service root url is inferred from the request used to access the docs.
|
||||
// However, there may be situations (e.g. proxy and load-balanced environments) where this does not
|
||||
// resolve correctly. You can workaround this by providing your own code to determine the root URL.
|
||||
//
|
||||
//c.RootUrl(req => GetRootUrlFromAppConfig());
|
||||
|
||||
// If schemes are not explicitly provided in a Swagger 2.0 document, then the scheme used to access
|
||||
// the docs is taken as the default. If your API supports multiple schemes and you want to be explicit
|
||||
// about them, you can use the "Schemes" option as shown below.
|
||||
//
|
||||
//c.Schemes(new[] { "http", "https" });
|
||||
|
||||
// Use "SingleApiVersion" to describe a single version API. Swagger 2.0 includes an "Info" object to
|
||||
// hold additional metadata for an API. Version and title are required but you can also provide
|
||||
// additional fields by chaining methods off SingleApiVersion.
|
||||
//
|
||||
c.SingleApiVersion("v1", "CELA_Tags_Parsing_Service");
|
||||
|
||||
// If you want the output Swagger docs to be indented properly, enable the "PrettyPrint" option.
|
||||
//
|
||||
//c.PrettyPrint();
|
||||
|
||||
// If your API has multiple versions, use "MultipleApiVersions" instead of "SingleApiVersion".
|
||||
// In this case, you must provide a lambda that tells Swashbuckle which actions should be
|
||||
// included in the docs for a given API version. Like "SingleApiVersion", each call to "Version"
|
||||
// returns an "Info" builder so you can provide additional metadata per API version.
|
||||
//
|
||||
//c.MultipleApiVersions(
|
||||
// (apiDesc, targetApiVersion) => ResolveVersionSupportByRouteConstraint(apiDesc, targetApiVersion),
|
||||
// (vc) =>
|
||||
// {
|
||||
// vc.Version("v2", "Swashbuckle Dummy API V2");
|
||||
// vc.Version("v1", "Swashbuckle Dummy API V1");
|
||||
// });
|
||||
|
||||
// You can use "BasicAuth", "ApiKey" or "OAuth2" options to describe security schemes for the API.
|
||||
// See https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md for more details.
|
||||
// NOTE: These only define the schemes and need to be coupled with a corresponding "security" property
|
||||
// at the document or operation level to indicate which schemes are required for an operation. To do this,
|
||||
// you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
|
||||
// according to your specific authorization implementation
|
||||
//
|
||||
//c.BasicAuth("basic")
|
||||
// .Description("Basic HTTP Authentication");
|
||||
//
|
||||
// NOTE: You must also configure 'EnableApiKeySupport' below in the SwaggerUI section
|
||||
//c.ApiKey("apiKey")
|
||||
// .Description("API Key Authentication")
|
||||
// .Name("apiKey")
|
||||
// .In("header");
|
||||
//
|
||||
//c.OAuth2("oauth2")
|
||||
// .Description("OAuth2 Implicit Grant")
|
||||
// .Flow("implicit")
|
||||
// .AuthorizationUrl("http://petstore.swagger.wordnik.com/api/oauth/dialog")
|
||||
// //.TokenUrl("https://tempuri.org/token")
|
||||
// .Scopes(scopes =>
|
||||
// {
|
||||
// scopes.Add("read", "Read access to protected resources");
|
||||
// scopes.Add("write", "Write access to protected resources");
|
||||
// });
|
||||
|
||||
// Set this flag to omit descriptions for any actions decorated with the Obsolete attribute
|
||||
//c.IgnoreObsoleteActions();
|
||||
|
||||
// Each operation be assigned one or more tags which are then used by consumers for various reasons.
|
||||
// For example, the swagger-ui groups operations according to the first tag of each operation.
|
||||
// By default, this will be controller name but you can use the "GroupActionsBy" option to
|
||||
// override with any value.
|
||||
//
|
||||
//c.GroupActionsBy(apiDesc => apiDesc.HttpMethod.ToString());
|
||||
|
||||
// You can also specify a custom sort order for groups (as defined by "GroupActionsBy") to dictate
|
||||
// the order in which operations are listed. For example, if the default grouping is in place
|
||||
// (controller name) and you specify a descending alphabetic sort order, then actions from a
|
||||
// ProductsController will be listed before those from a CustomersController. This is typically
|
||||
// used to customize the order of groupings in the swagger-ui.
|
||||
//
|
||||
//c.OrderActionGroupsBy(new DescendingAlphabeticComparer());
|
||||
|
||||
// If you annotate Controllers and API Types with
|
||||
// Xml comments (http://msdn.microsoft.com/en-us/library/b2s063f7(v=vs.110).aspx), you can incorporate
|
||||
// those comments into the generated docs and UI. You can enable this by providing the path to one or
|
||||
// more Xml comment files.
|
||||
//
|
||||
c.IncludeXmlComments(string.Format(@"{0}\bin\CELA-Tags_Parsing_Service.xml", System.AppDomain.CurrentDomain.BaseDirectory));
|
||||
|
||||
// Swashbuckle makes a best attempt at generating Swagger compliant JSON schemas for the various types
|
||||
// exposed in your API. However, there may be occasions when more control of the output is needed.
|
||||
// This is supported through the "MapType" and "SchemaFilter" options:
|
||||
//
|
||||
// Use the "MapType" option to override the Schema generation for a specific type.
|
||||
// It should be noted that the resulting Schema will be placed "inline" for any applicable Operations.
|
||||
// While Swagger 2.0 supports inline definitions for "all" Schema types, the swagger-ui tool does not.
|
||||
// It expects "complex" Schemas to be defined separately and referenced. For this reason, you should only
|
||||
// use the "MapType" option when the resulting Schema is a primitive or array type. If you need to alter a
|
||||
// complex Schema, use a Schema filter.
|
||||
//
|
||||
//c.MapType<ProductType>(() => new Schema { type = "integer", format = "int32" });
|
||||
|
||||
// If you want to post-modify "complex" Schemas once they've been generated, across the board or for a
|
||||
// specific type, you can wire up one or more Schema filters.
|
||||
//
|
||||
//c.SchemaFilter<ApplySchemaVendorExtensions>();
|
||||
|
||||
// In a Swagger 2.0 document, complex types are typically declared globally and referenced by unique
|
||||
// Schema Id. By default, Swashbuckle does NOT use the full type name in Schema Ids. In most cases, this
|
||||
// works well because it prevents the "implementation detail" of type namespaces from leaking into your
|
||||
// Swagger docs and UI. However, if you have multiple types in your API with the same class name, you'll
|
||||
// need to opt out of this behavior to avoid Schema Id conflicts.
|
||||
//
|
||||
//c.UseFullTypeNameInSchemaIds();
|
||||
|
||||
// Alternatively, you can provide your own custom strategy for inferring SchemaId's for
|
||||
// describing "complex" types in your API.
|
||||
//
|
||||
//c.SchemaId(t => t.FullName.Contains('`') ? t.FullName.Substring(0, t.FullName.IndexOf('`')) : t.FullName);
|
||||
|
||||
// Set this flag to omit schema property descriptions for any type properties decorated with the
|
||||
// Obsolete attribute
|
||||
//c.IgnoreObsoleteProperties();
|
||||
|
||||
// In accordance with the built in JsonSerializer, Swashbuckle will, by default, describe enums as integers.
|
||||
// You can change the serializer behavior by configuring the StringToEnumConverter globally or for a given
|
||||
// enum type. Swashbuckle will honor this change out-of-the-box. However, if you use a different
|
||||
// approach to serialize enums as strings, you can also force Swashbuckle to describe them as strings.
|
||||
//
|
||||
//c.DescribeAllEnumsAsStrings();
|
||||
|
||||
// Similar to Schema filters, Swashbuckle also supports Operation and Document filters:
|
||||
//
|
||||
// Post-modify Operation descriptions once they've been generated by wiring up one or more
|
||||
// Operation filters.
|
||||
//
|
||||
//c.OperationFilter<AddDefaultResponse>();
|
||||
//
|
||||
// If you've defined an OAuth2 flow as described above, you could use a custom filter
|
||||
// to inspect some attribute on each action and infer which (if any) OAuth2 scopes are required
|
||||
// to execute the operation
|
||||
//
|
||||
//c.OperationFilter<AssignOAuth2SecurityRequirements>();
|
||||
|
||||
// Post-modify the entire Swagger document by wiring up one or more Document filters.
|
||||
// This gives full control to modify the final SwaggerDocument. You should have a good understanding of
|
||||
// the Swagger 2.0 spec. - https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md
|
||||
// before using this option.
|
||||
//
|
||||
//c.DocumentFilter<ApplyDocumentVendorExtensions>();
|
||||
|
||||
// In contrast to WebApi, Swagger 2.0 does not include the query string component when mapping a URL
|
||||
// to an action. As a result, Swashbuckle will raise an exception if it encounters multiple actions
|
||||
// with the same path (sans query string) and HTTP method. You can workaround this by providing a
|
||||
// custom strategy to pick a winner or merge the descriptions for the purposes of the Swagger docs
|
||||
//
|
||||
//c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
|
||||
|
||||
// Wrap the default SwaggerGenerator with additional behavior (e.g. caching) or provide an
|
||||
// alternative implementation for ISwaggerProvider with the CustomProvider option.
|
||||
//
|
||||
//c.CustomProvider((defaultProvider) => new CachingSwaggerProvider(defaultProvider));
|
||||
})
|
||||
.EnableSwaggerUi(c =>
|
||||
{
|
||||
// Use the "DocumentTitle" option to change the Document title.
|
||||
// Very helpful when you have multiple Swagger pages open, to tell them apart.
|
||||
//
|
||||
//c.DocumentTitle("My Swagger UI");
|
||||
|
||||
// Use the "InjectStylesheet" option to enrich the UI with one or more additional CSS stylesheets.
|
||||
// The file must be included in your project as an "Embedded Resource", and then the resource's
|
||||
// "Logical Name" is passed to the method as shown below.
|
||||
//
|
||||
//c.InjectStylesheet(containingAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css");
|
||||
|
||||
// Use the "InjectJavaScript" option to invoke one or more custom JavaScripts after the swagger-ui
|
||||
// has loaded. The file must be included in your project as an "Embedded Resource", and then the resource's
|
||||
// "Logical Name" is passed to the method as shown above.
|
||||
//
|
||||
//c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js");
|
||||
|
||||
// The swagger-ui renders boolean data types as a dropdown. By default, it provides "true" and "false"
|
||||
// strings as the possible choices. You can use this option to change these to something else,
|
||||
// for example 0 and 1.
|
||||
//
|
||||
//c.BooleanValues(new[] { "0", "1" });
|
||||
|
||||
// By default, swagger-ui will validate specs against swagger.io's online validator and display the result
|
||||
// in a badge at the bottom of the page. Use these options to set a different validator URL or to disable the
|
||||
// feature entirely.
|
||||
//c.SetValidatorUrl("http://localhost/validator");
|
||||
//c.DisableValidator();
|
||||
|
||||
// Use this option to control how the Operation listing is displayed.
|
||||
// It can be set to "None" (default), "List" (shows operations for each resource),
|
||||
// or "Full" (fully expanded: shows operations and their details).
|
||||
//
|
||||
//c.DocExpansion(DocExpansion.List);
|
||||
|
||||
// Specify which HTTP operations will have the 'Try it out!' option. An empty paramter list disables
|
||||
// it for all operations.
|
||||
//
|
||||
//c.SupportedSubmitMethods("GET", "HEAD");
|
||||
|
||||
// Use the CustomAsset option to provide your own version of assets used in the swagger-ui.
|
||||
// It's typically used to instruct Swashbuckle to return your version instead of the default
|
||||
// when a request is made for "index.html". As with all custom content, the file must be included
|
||||
// in your project as an "Embedded Resource", and then the resource's "Logical Name" is passed to
|
||||
// the method as shown below.
|
||||
//
|
||||
//c.CustomAsset("index", containingAssembly, "YourWebApiProject.SwaggerExtensions.index.html");
|
||||
|
||||
// If your API has multiple versions and you've applied the MultipleApiVersions setting
|
||||
// as described above, you can also enable a select box in the swagger-ui, that displays
|
||||
// a discovery URL for each version. This provides a convenient way for users to browse documentation
|
||||
// for different API versions.
|
||||
//
|
||||
//c.EnableDiscoveryUrlSelector();
|
||||
|
||||
// If your API supports the OAuth2 Implicit flow, and you've described it correctly, according to
|
||||
// the Swagger 2.0 specification, you can enable UI support as shown below.
|
||||
//
|
||||
//c.EnableOAuth2Support(
|
||||
// clientId: "test-client-id",
|
||||
// clientSecret: null,
|
||||
// realm: "test-realm",
|
||||
// appName: "Swagger UI"
|
||||
// //additionalQueryStringParams: new Dictionary<string, string>() { { "foo", "bar" } }
|
||||
//);
|
||||
|
||||
// If your API supports ApiKey, you can override the default values.
|
||||
// "apiKeyIn" can either be "query" or "header"
|
||||
//
|
||||
//c.EnableApiKeySupport("apiKey", "header");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Http;
|
||||
|
||||
namespace CELA_Tags_Parsing_Service
|
||||
{
|
||||
public static class WebApiConfig
|
||||
{
|
||||
public static void Register(HttpConfiguration config)
|
||||
{
|
||||
// Web API configuration and services
|
||||
//See https://stackoverflow.com/questions/44920319/the-request-entitys-media-type-text-plain-is-not-supported-for-this-resource for explanation
|
||||
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/plain"));
|
||||
// Web API routes
|
||||
config.MapHttpAttributeRoutes();
|
||||
|
||||
config.Routes.MapHttpRoute(
|
||||
name: "DefaultApi",
|
||||
routeTemplate: "api/{controller}/{id}",
|
||||
defaults: new { id = RouteParameter.Optional }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ApplicationInsights xmlns="http://schemas.microsoft.com/ApplicationInsights/2013/Settings">
|
||||
|
||||
<InstrumentationKey>56916d08-a5e4-463b-9acc-c0d75d1b18c3</InstrumentationKey>
|
||||
<TelemetryInitializers>
|
||||
<Add Type="Microsoft.ApplicationInsights.DependencyCollector.HttpDependenciesParsingTelemetryInitializer, Microsoft.AI.DependencyCollector"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.WindowsServer.AzureRoleEnvironmentTelemetryInitializer, Microsoft.AI.WindowsServer"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.WindowsServer.AzureWebAppRoleEnvironmentTelemetryInitializer, Microsoft.AI.WindowsServer"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.WindowsServer.BuildInfoConfigComponentVersionTelemetryInitializer, Microsoft.AI.WindowsServer"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.Web.WebTestTelemetryInitializer, Microsoft.AI.Web"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.Web.SyntheticUserAgentTelemetryInitializer, Microsoft.AI.Web">
|
||||
<!-- Extended list of bots:
|
||||
search|spider|crawl|Bot|Monitor|BrowserMob|BingPreview|PagePeeker|WebThumb|URL2PNG|ZooShot|GomezA|Google SketchUp|Read Later|KTXN|KHTE|Keynote|Pingdom|AlwaysOn|zao|borg|oegp|silk|Xenu|zeal|NING|htdig|lycos|slurp|teoma|voila|yahoo|Sogou|CiBra|Nutch|Java|JNLP|Daumoa|Genieo|ichiro|larbin|pompos|Scrapy|snappy|speedy|vortex|favicon|indexer|Riddler|scooter|scraper|scrubby|WhatWeb|WinHTTP|voyager|archiver|Icarus6j|mogimogi|Netvibes|altavista|charlotte|findlinks|Retreiver|TLSProber|WordPress|wsr-agent|http client|Python-urllib|AppEngine-Google|semanticdiscovery|facebookexternalhit|web/snippet|Google-HTTP-Java-Client-->
|
||||
<Filters>search|spider|crawl|Bot|Monitor|AlwaysOn</Filters>
|
||||
</Add>
|
||||
<Add Type="Microsoft.ApplicationInsights.Web.ClientIpHeaderTelemetryInitializer, Microsoft.AI.Web"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.Web.OperationNameTelemetryInitializer, Microsoft.AI.Web"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.Web.OperationCorrelationTelemetryInitializer, Microsoft.AI.Web"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.Web.UserTelemetryInitializer, Microsoft.AI.Web"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.Web.AuthenticatedUserIdTelemetryInitializer, Microsoft.AI.Web"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.Web.AccountIdTelemetryInitializer, Microsoft.AI.Web"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.Web.SessionTelemetryInitializer, Microsoft.AI.Web"/>
|
||||
</TelemetryInitializers>
|
||||
<TelemetryModules>
|
||||
<Add Type="Microsoft.ApplicationInsights.DependencyCollector.DependencyTrackingTelemetryModule, Microsoft.AI.DependencyCollector">
|
||||
<ExcludeComponentCorrelationHttpHeadersOnDomains>
|
||||
<!--
|
||||
Requests to the following hostnames will not be modified by adding correlation headers.
|
||||
Add entries here to exclude additional hostnames.
|
||||
NOTE: this configuration will be lost upon NuGet upgrade.
|
||||
-->
|
||||
<Add>core.windows.net</Add>
|
||||
<Add>core.chinacloudapi.cn</Add>
|
||||
<Add>core.cloudapi.de</Add>
|
||||
<Add>core.usgovcloudapi.net</Add>
|
||||
<Add>localhost</Add>
|
||||
<Add>127.0.0.1</Add>
|
||||
</ExcludeComponentCorrelationHttpHeadersOnDomains>
|
||||
<IncludeDiagnosticSourceActivities>
|
||||
<Add>Microsoft.Azure.EventHubs</Add>
|
||||
<Add>Microsoft.Azure.ServiceBus</Add>
|
||||
</IncludeDiagnosticSourceActivities>
|
||||
</Add>
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.PerformanceCollectorModule, Microsoft.AI.PerfCounterCollector">
|
||||
<!--
|
||||
Use the following syntax here to collect additional performance counters:
|
||||
|
||||
<Counters>
|
||||
<Add PerformanceCounter="\Process(??APP_WIN32_PROC??)\Handle Count" ReportAs="Process handle count" />
|
||||
...
|
||||
</Counters>
|
||||
|
||||
PerformanceCounter must be either \CategoryName(InstanceName)\CounterName or \CategoryName\CounterName
|
||||
|
||||
NOTE: performance counters configuration will be lost upon NuGet upgrade.
|
||||
|
||||
The following placeholders are supported as InstanceName:
|
||||
??APP_WIN32_PROC?? - instance name of the application process for Win32 counters.
|
||||
??APP_W3SVC_PROC?? - instance name of the application IIS worker process for IIS/ASP.NET counters.
|
||||
??APP_CLR_PROC?? - instance name of the application CLR process for .NET counters.
|
||||
-->
|
||||
</Add>
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse.QuickPulseTelemetryModule, Microsoft.AI.PerfCounterCollector"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.WindowsServer.AppServicesHeartbeatTelemetryModule, Microsoft.AI.WindowsServer"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.WindowsServer.AzureInstanceMetadataTelemetryModule, Microsoft.AI.WindowsServer">
|
||||
<!--
|
||||
Remove individual fields collected here by adding them to the ApplicationInsighs.HeartbeatProvider
|
||||
with the following syntax:
|
||||
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing.DiagnosticsTelemetryModule, Microsoft.ApplicationInsights">
|
||||
<ExcludedHeartbeatProperties>
|
||||
<Add>osType</Add>
|
||||
<Add>location</Add>
|
||||
<Add>name</Add>
|
||||
<Add>offer</Add>
|
||||
<Add>platformFaultDomain</Add>
|
||||
<Add>platformUpdateDomain</Add>
|
||||
<Add>publisher</Add>
|
||||
<Add>sku</Add>
|
||||
<Add>version</Add>
|
||||
<Add>vmId</Add>
|
||||
<Add>vmSize</Add>
|
||||
<Add>subscriptionId</Add>
|
||||
<Add>resourceGroupName</Add>
|
||||
<Add>placementGroupId</Add>
|
||||
<Add>tags</Add>
|
||||
<Add>vmScaleSetName</Add>
|
||||
</ExcludedHeartbeatProperties>
|
||||
</Add>
|
||||
|
||||
NOTE: exclusions will be lost upon upgrade.
|
||||
-->
|
||||
</Add>
|
||||
<Add Type="Microsoft.ApplicationInsights.WindowsServer.DeveloperModeWithDebuggerAttachedTelemetryModule, Microsoft.AI.WindowsServer"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.WindowsServer.UnhandledExceptionTelemetryModule, Microsoft.AI.WindowsServer"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.WindowsServer.UnobservedExceptionTelemetryModule, Microsoft.AI.WindowsServer">
|
||||
<!--</Add>
|
||||
<Add Type="Microsoft.ApplicationInsights.WindowsServer.FirstChanceExceptionStatisticsTelemetryModule, Microsoft.AI.WindowsServer">-->
|
||||
</Add>
|
||||
<Add Type="Microsoft.ApplicationInsights.Web.RequestTrackingTelemetryModule, Microsoft.AI.Web">
|
||||
<Handlers>
|
||||
<!--
|
||||
Add entries here to filter out additional handlers:
|
||||
|
||||
NOTE: handler configuration will be lost upon NuGet upgrade.
|
||||
-->
|
||||
<Add>Microsoft.VisualStudio.Web.PageInspector.Runtime.Tracing.RequestDataHttpHandler</Add>
|
||||
<Add>System.Web.StaticFileHandler</Add>
|
||||
<Add>System.Web.Handlers.AssemblyResourceLoader</Add>
|
||||
<Add>System.Web.Optimization.BundleHandler</Add>
|
||||
<Add>System.Web.Script.Services.ScriptHandlerFactory</Add>
|
||||
<Add>System.Web.Handlers.TraceHandler</Add>
|
||||
<Add>System.Web.Services.Discovery.DiscoveryRequestHandler</Add>
|
||||
<Add>System.Web.HttpDebugHandler</Add>
|
||||
</Handlers>
|
||||
</Add>
|
||||
<Add Type="Microsoft.ApplicationInsights.Web.ExceptionTrackingTelemetryModule, Microsoft.AI.Web"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.Web.AspNetDiagnosticTelemetryModule, Microsoft.AI.Web"/>
|
||||
</TelemetryModules>
|
||||
<ApplicationIdProvider Type="Microsoft.ApplicationInsights.Extensibility.Implementation.ApplicationId.ApplicationInsightsApplicationIdProvider, Microsoft.ApplicationInsights"/>
|
||||
<TelemetrySinks>
|
||||
<Add Name="default">
|
||||
<TelemetryProcessors>
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse.QuickPulseTelemetryProcessor, Microsoft.AI.PerfCounterCollector"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.Extensibility.AutocollectedMetricsExtractor, Microsoft.ApplicationInsights"/>
|
||||
<Add Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.AdaptiveSamplingTelemetryProcessor, Microsoft.AI.ServerTelemetryChannel">
|
||||
<MaxTelemetryItemsPerSecond>5</MaxTelemetryItemsPerSecond>
|
||||
<ExcludedTypes>Event</ExcludedTypes>
|
||||
</Add>
|
||||
<Add Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.AdaptiveSamplingTelemetryProcessor, Microsoft.AI.ServerTelemetryChannel">
|
||||
<MaxTelemetryItemsPerSecond>5</MaxTelemetryItemsPerSecond>
|
||||
<IncludedTypes>Event</IncludedTypes>
|
||||
</Add>
|
||||
</TelemetryProcessors>
|
||||
<TelemetryChannel Type="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.ServerTelemetryChannel, Microsoft.AI.ServerTelemetryChannel"/>
|
||||
</Add>
|
||||
</TelemetrySinks>
|
||||
<!--
|
||||
Learn more about Application Insights configuration with ApplicationInsights.config here:
|
||||
http://go.microsoft.com/fwlink/?LinkID=513840
|
||||
|
||||
Note: If not present, please add <InstrumentationKey>Your Key</InstrumentationKey> to the top of this file.
|
||||
--></ApplicationInsights>
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Http.Description;
|
||||
|
||||
namespace CELA_Tags_Parsing_Service.Areas.HelpPage
|
||||
{
|
||||
public static class ApiDescriptionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates an URI-friendly ID for the <see cref="ApiDescription"/>. E.g. "Get-Values-id_name" instead of "GetValues/{id}?name={name}"
|
||||
/// </summary>
|
||||
/// <param name="description">The <see cref="ApiDescription"/>.</param>
|
||||
/// <returns>The ID as a string.</returns>
|
||||
public static string GetFriendlyId(this ApiDescription description)
|
||||
{
|
||||
string path = description.RelativePath;
|
||||
string[] urlParts = path.Split('?');
|
||||
string localPath = urlParts[0];
|
||||
string queryKeyString = null;
|
||||
if (urlParts.Length > 1)
|
||||
{
|
||||
string query = urlParts[1];
|
||||
string[] queryKeys = HttpUtility.ParseQueryString(query).AllKeys;
|
||||
queryKeyString = String.Join("_", queryKeys);
|
||||
}
|
||||
|
||||
StringBuilder friendlyPath = new StringBuilder();
|
||||
friendlyPath.AppendFormat("{0}-{1}",
|
||||
description.HttpMethod.Method,
|
||||
localPath.Replace("/", "-").Replace("{", String.Empty).Replace("}", String.Empty));
|
||||
if (queryKeyString != null)
|
||||
{
|
||||
friendlyPath.AppendFormat("_{0}", queryKeyString.Replace('.', '-'));
|
||||
}
|
||||
return friendlyPath.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
// Uncomment the following to provide samples for PageResult<T>. Must also add the Microsoft.AspNet.WebApi.OData
|
||||
// package to your project.
|
||||
////#define Handle_PageResultOfT
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Web;
|
||||
using System.Web.Http;
|
||||
#if Handle_PageResultOfT
|
||||
using System.Web.Http.OData;
|
||||
#endif
|
||||
|
||||
namespace CELA_Tags_Parsing_Service.Areas.HelpPage
|
||||
{
|
||||
/// <summary>
|
||||
/// Use this class to customize the Help Page.
|
||||
/// For example you can set a custom <see cref="System.Web.Http.Description.IDocumentationProvider"/> to supply the documentation
|
||||
/// or you can provide the samples for the requests/responses.
|
||||
/// </summary>
|
||||
public static class HelpPageConfig
|
||||
{
|
||||
[SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters",
|
||||
MessageId = "CELA_Tags_Parsing_Service.Areas.HelpPage.TextSample.#ctor(System.String)",
|
||||
Justification = "End users may choose to merge this string with existing localized resources.")]
|
||||
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly",
|
||||
MessageId = "bsonspec",
|
||||
Justification = "Part of a URI.")]
|
||||
public static void Register(HttpConfiguration config)
|
||||
{
|
||||
//// Uncomment the following to use the documentation from XML documentation file.
|
||||
//config.SetDocumentationProvider(new XmlDocumentationProvider(HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));
|
||||
|
||||
//// Uncomment the following to use "sample string" as the sample for all actions that have string as the body parameter or return type.
|
||||
//// Also, the string arrays will be used for IEnumerable<string>. The sample objects will be serialized into different media type
|
||||
//// formats by the available formatters.
|
||||
//config.SetSampleObjects(new Dictionary<Type, object>
|
||||
//{
|
||||
// {typeof(string), "sample string"},
|
||||
// {typeof(IEnumerable<string>), new string[]{"sample 1", "sample 2"}}
|
||||
//});
|
||||
|
||||
// Extend the following to provide factories for types not handled automatically (those lacking parameterless
|
||||
// constructors) or for which you prefer to use non-default property values. Line below provides a fallback
|
||||
// since automatic handling will fail and GeneratePageResult handles only a single type.
|
||||
#if Handle_PageResultOfT
|
||||
config.GetHelpPageSampleGenerator().SampleObjectFactories.Add(GeneratePageResult);
|
||||
#endif
|
||||
|
||||
// Extend the following to use a preset object directly as the sample for all actions that support a media
|
||||
// type, regardless of the body parameter or return type. The lines below avoid display of binary content.
|
||||
// The BsonMediaTypeFormatter (if available) is not used to serialize the TextSample object.
|
||||
config.SetSampleForMediaType(
|
||||
new TextSample("Binary JSON content. See http://bsonspec.org for details."),
|
||||
new MediaTypeHeaderValue("application/bson"));
|
||||
|
||||
//// Uncomment the following to use "[0]=foo&[1]=bar" directly as the sample for all actions that support form URL encoded format
|
||||
//// and have IEnumerable<string> as the body parameter or return type.
|
||||
//config.SetSampleForType("[0]=foo&[1]=bar", new MediaTypeHeaderValue("application/x-www-form-urlencoded"), typeof(IEnumerable<string>));
|
||||
|
||||
//// Uncomment the following to use "1234" directly as the request sample for media type "text/plain" on the controller named "Values"
|
||||
//// and action named "Put".
|
||||
//config.SetSampleRequest("1234", new MediaTypeHeaderValue("text/plain"), "Values", "Put");
|
||||
|
||||
//// Uncomment the following to use the image on "../images/aspNetHome.png" directly as the response sample for media type "image/png"
|
||||
//// on the controller named "Values" and action named "Get" with parameter "id".
|
||||
//config.SetSampleResponse(new ImageSample("../images/aspNetHome.png"), new MediaTypeHeaderValue("image/png"), "Values", "Get", "id");
|
||||
|
||||
//// Uncomment the following to correct the sample request when the action expects an HttpRequestMessage with ObjectContent<string>.
|
||||
//// The sample will be generated as if the controller named "Values" and action named "Get" were having string as the body parameter.
|
||||
//config.SetActualRequestType(typeof(string), "Values", "Get");
|
||||
|
||||
//// Uncomment the following to correct the sample response when the action returns an HttpResponseMessage with ObjectContent<string>.
|
||||
//// The sample will be generated as if the controller named "Values" and action named "Post" were returning a string.
|
||||
//config.SetActualResponseType(typeof(string), "Values", "Post");
|
||||
}
|
||||
|
||||
#if Handle_PageResultOfT
|
||||
private static object GeneratePageResult(HelpPageSampleGenerator sampleGenerator, Type type)
|
||||
{
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
Type openGenericType = type.GetGenericTypeDefinition();
|
||||
if (openGenericType == typeof(PageResult<>))
|
||||
{
|
||||
// Get the T in PageResult<T>
|
||||
Type[] typeParameters = type.GetGenericArguments();
|
||||
Debug.Assert(typeParameters.Length == 1);
|
||||
|
||||
// Create an enumeration to pass as the first parameter to the PageResult<T> constuctor
|
||||
Type itemsType = typeof(List<>).MakeGenericType(typeParameters);
|
||||
object items = sampleGenerator.GetSampleObject(itemsType);
|
||||
|
||||
// Fill in the other information needed to invoke the PageResult<T> constuctor
|
||||
Type[] parameterTypes = new Type[] { itemsType, typeof(Uri), typeof(long?), };
|
||||
object[] parameters = new object[] { items, null, (long)ObjectGenerator.DefaultCollectionSize, };
|
||||
|
||||
// Call PageResult(IEnumerable<T> items, Uri nextPageLink, long? count) constructor
|
||||
ConstructorInfo constructor = type.GetConstructor(parameterTypes);
|
||||
return constructor.Invoke(parameters);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Web.Http;
|
||||
using System.Web.Mvc;
|
||||
using CELA_Tags_Parsing_Service.Areas.HelpPage.ModelDescriptions;
|
||||
using CELA_Tags_Parsing_Service.Areas.HelpPage.Models;
|
||||
|
||||
namespace CELA_Tags_Parsing_Service.Areas.HelpPage.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// The controller that will handle requests for the help page.
|
||||
/// </summary>
|
||||
public class HelpController : Controller
|
||||
{
|
||||
private const string ErrorViewName = "Error";
|
||||
|
||||
public HelpController()
|
||||
: this(GlobalConfiguration.Configuration)
|
||||
{
|
||||
}
|
||||
|
||||
public HelpController(HttpConfiguration config)
|
||||
{
|
||||
Configuration = config;
|
||||
}
|
||||
|
||||
public HttpConfiguration Configuration { get; private set; }
|
||||
|
||||
public ActionResult Index()
|
||||
{
|
||||
ViewBag.DocumentationProvider = Configuration.Services.GetDocumentationProvider();
|
||||
return View(Configuration.Services.GetApiExplorer().ApiDescriptions);
|
||||
}
|
||||
|
||||
public ActionResult Api(string apiId)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(apiId))
|
||||
{
|
||||
HelpPageApiModel apiModel = Configuration.GetHelpPageApiModel(apiId);
|
||||
if (apiModel != null)
|
||||
{
|
||||
return View(apiModel);
|
||||
}
|
||||
}
|
||||
|
||||
return View(ErrorViewName);
|
||||
}
|
||||
|
||||
public ActionResult ResourceModel(string modelName)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(modelName))
|
||||
{
|
||||
ModelDescriptionGenerator modelDescriptionGenerator = Configuration.GetModelDescriptionGenerator();
|
||||
ModelDescription modelDescription;
|
||||
if (modelDescriptionGenerator.GeneratedModels.TryGetValue(modelName, out modelDescription))
|
||||
{
|
||||
return View(modelDescription);
|
||||
}
|
||||
}
|
||||
|
||||
return View(ErrorViewName);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
.help-page h1,
|
||||
.help-page .h1,
|
||||
.help-page h2,
|
||||
.help-page .h2,
|
||||
.help-page h3,
|
||||
.help-page .h3,
|
||||
#body.help-page,
|
||||
.help-page-table th,
|
||||
.help-page-table pre,
|
||||
.help-page-table p {
|
||||
font-family: "Segoe UI Light", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif;
|
||||
}
|
||||
|
||||
.help-page pre.wrapped {
|
||||
white-space: -moz-pre-wrap;
|
||||
white-space: -pre-wrap;
|
||||
white-space: -o-pre-wrap;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.help-page .warning-message-container {
|
||||
margin-top: 20px;
|
||||
padding: 0 10px;
|
||||
color: #525252;
|
||||
background: #EFDCA9;
|
||||
border: 1px solid #CCCCCC;
|
||||
}
|
||||
|
||||
.help-page-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
text-align: left;
|
||||
margin: 0px 0px 20px 0px;
|
||||
border-top: 1px solid #D4D4D4;
|
||||
}
|
||||
|
||||
.help-page-table th {
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #D4D4D4;
|
||||
padding: 5px 6px 5px 6px;
|
||||
}
|
||||
|
||||
.help-page-table td {
|
||||
border-bottom: 1px solid #D4D4D4;
|
||||
padding: 10px 8px 10px 8px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.help-page-table pre,
|
||||
.help-page-table p {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
font-family: inherit;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.help-page-table tbody tr:hover td {
|
||||
background-color: #F3F3F3;
|
||||
}
|
||||
|
||||
.help-page a:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.help-page .sample-header {
|
||||
border: 2px solid #D4D4D4;
|
||||
background: #00497E;
|
||||
color: #FFFFFF;
|
||||
padding: 8px 15px;
|
||||
border-bottom: none;
|
||||
display: inline-block;
|
||||
margin: 10px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.help-page .sample-content {
|
||||
display: block;
|
||||
border-width: 0;
|
||||
padding: 15px 20px;
|
||||
background: #FFFFFF;
|
||||
border: 2px solid #D4D4D4;
|
||||
margin: 0px 0px 10px 0px;
|
||||
}
|
||||
|
||||
.help-page .api-name {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.help-page .api-documentation {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.help-page .parameter-name {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.help-page .parameter-documentation {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.help-page .parameter-type {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.help-page .parameter-annotations {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.help-page h1,
|
||||
.help-page .h1 {
|
||||
font-size: 36px;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.help-page h2,
|
||||
.help-page .h2 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.help-page h3,
|
||||
.help-page .h3 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#body.help-page {
|
||||
font-size: 14px;
|
||||
line-height: 143%;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.help-page a {
|
||||
color: #0000EE;
|
||||
text-decoration: none;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using System.Web.Http;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace CELA_Tags_Parsing_Service.Areas.HelpPage
|
||||
{
|
||||
public class HelpPageAreaRegistration : AreaRegistration
|
||||
{
|
||||
public override string AreaName
|
||||
{
|
||||
get
|
||||
{
|
||||
return "HelpPage";
|
||||
}
|
||||
}
|
||||
|
||||
public override void RegisterArea(AreaRegistrationContext context)
|
||||
{
|
||||
context.MapRoute(
|
||||
"HelpPage_Default",
|
||||
"Help/{action}/{apiId}",
|
||||
new { controller = "Help", action = "Index", apiId = UrlParameter.Optional });
|
||||
|
||||
HelpPageConfig.Register(GlobalConfiguration.Configuration);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,467 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Web.Http;
|
||||
using System.Web.Http.Controllers;
|
||||
using System.Web.Http.Description;
|
||||
using CELA_Tags_Parsing_Service.Areas.HelpPage.ModelDescriptions;
|
||||
using CELA_Tags_Parsing_Service.Areas.HelpPage.Models;
|
||||
|
||||
namespace CELA_Tags_Parsing_Service.Areas.HelpPage
|
||||
{
|
||||
public static class HelpPageConfigurationExtensions
|
||||
{
|
||||
private const string ApiModelPrefix = "MS_HelpPageApiModel_";
|
||||
|
||||
/// <summary>
|
||||
/// Sets the documentation provider for help page.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="documentationProvider">The documentation provider.</param>
|
||||
public static void SetDocumentationProvider(this HttpConfiguration config, IDocumentationProvider documentationProvider)
|
||||
{
|
||||
config.Services.Replace(typeof(IDocumentationProvider), documentationProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the objects that will be used by the formatters to produce sample requests/responses.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="sampleObjects">The sample objects.</param>
|
||||
public static void SetSampleObjects(this HttpConfiguration config, IDictionary<Type, object> sampleObjects)
|
||||
{
|
||||
config.GetHelpPageSampleGenerator().SampleObjects = sampleObjects;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the sample request directly for the specified media type and action.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="sample">The sample request.</param>
|
||||
/// <param name="mediaType">The media type.</param>
|
||||
/// <param name="controllerName">Name of the controller.</param>
|
||||
/// <param name="actionName">Name of the action.</param>
|
||||
public static void SetSampleRequest(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName)
|
||||
{
|
||||
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Request, controllerName, actionName, new[] { "*" }), sample);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the sample request directly for the specified media type and action with parameters.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="sample">The sample request.</param>
|
||||
/// <param name="mediaType">The media type.</param>
|
||||
/// <param name="controllerName">Name of the controller.</param>
|
||||
/// <param name="actionName">Name of the action.</param>
|
||||
/// <param name="parameterNames">The parameter names.</param>
|
||||
public static void SetSampleRequest(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName, params string[] parameterNames)
|
||||
{
|
||||
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Request, controllerName, actionName, parameterNames), sample);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the sample request directly for the specified media type of the action.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="sample">The sample response.</param>
|
||||
/// <param name="mediaType">The media type.</param>
|
||||
/// <param name="controllerName">Name of the controller.</param>
|
||||
/// <param name="actionName">Name of the action.</param>
|
||||
public static void SetSampleResponse(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName)
|
||||
{
|
||||
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Response, controllerName, actionName, new[] { "*" }), sample);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the sample response directly for the specified media type of the action with specific parameters.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="sample">The sample response.</param>
|
||||
/// <param name="mediaType">The media type.</param>
|
||||
/// <param name="controllerName">Name of the controller.</param>
|
||||
/// <param name="actionName">Name of the action.</param>
|
||||
/// <param name="parameterNames">The parameter names.</param>
|
||||
public static void SetSampleResponse(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, string controllerName, string actionName, params string[] parameterNames)
|
||||
{
|
||||
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, SampleDirection.Response, controllerName, actionName, parameterNames), sample);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the sample directly for all actions with the specified media type.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="sample">The sample.</param>
|
||||
/// <param name="mediaType">The media type.</param>
|
||||
public static void SetSampleForMediaType(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType)
|
||||
{
|
||||
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType), sample);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the sample directly for all actions with the specified type and media type.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="sample">The sample.</param>
|
||||
/// <param name="mediaType">The media type.</param>
|
||||
/// <param name="type">The parameter type or return type of an action.</param>
|
||||
public static void SetSampleForType(this HttpConfiguration config, object sample, MediaTypeHeaderValue mediaType, Type type)
|
||||
{
|
||||
config.GetHelpPageSampleGenerator().ActionSamples.Add(new HelpPageSampleKey(mediaType, type), sample);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> passed to the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
|
||||
/// The help page will use this information to produce more accurate request samples.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="controllerName">Name of the controller.</param>
|
||||
/// <param name="actionName">Name of the action.</param>
|
||||
public static void SetActualRequestType(this HttpConfiguration config, Type type, string controllerName, string actionName)
|
||||
{
|
||||
config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Request, controllerName, actionName, new[] { "*" }), type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> passed to the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
|
||||
/// The help page will use this information to produce more accurate request samples.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="controllerName">Name of the controller.</param>
|
||||
/// <param name="actionName">Name of the action.</param>
|
||||
/// <param name="parameterNames">The parameter names.</param>
|
||||
public static void SetActualRequestType(this HttpConfiguration config, Type type, string controllerName, string actionName, params string[] parameterNames)
|
||||
{
|
||||
config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Request, controllerName, actionName, parameterNames), type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> returned as part of the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
|
||||
/// The help page will use this information to produce more accurate response samples.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="controllerName">Name of the controller.</param>
|
||||
/// <param name="actionName">Name of the action.</param>
|
||||
public static void SetActualResponseType(this HttpConfiguration config, Type type, string controllerName, string actionName)
|
||||
{
|
||||
config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Response, controllerName, actionName, new[] { "*" }), type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the actual type of <see cref="System.Net.Http.ObjectContent{T}"/> returned as part of the <see cref="System.Net.Http.HttpRequestMessage"/> in an action.
|
||||
/// The help page will use this information to produce more accurate response samples.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="controllerName">Name of the controller.</param>
|
||||
/// <param name="actionName">Name of the action.</param>
|
||||
/// <param name="parameterNames">The parameter names.</param>
|
||||
public static void SetActualResponseType(this HttpConfiguration config, Type type, string controllerName, string actionName, params string[] parameterNames)
|
||||
{
|
||||
config.GetHelpPageSampleGenerator().ActualHttpMessageTypes.Add(new HelpPageSampleKey(SampleDirection.Response, controllerName, actionName, parameterNames), type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the help page sample generator.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <returns>The help page sample generator.</returns>
|
||||
public static HelpPageSampleGenerator GetHelpPageSampleGenerator(this HttpConfiguration config)
|
||||
{
|
||||
return (HelpPageSampleGenerator)config.Properties.GetOrAdd(
|
||||
typeof(HelpPageSampleGenerator),
|
||||
k => new HelpPageSampleGenerator());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the help page sample generator.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="sampleGenerator">The help page sample generator.</param>
|
||||
public static void SetHelpPageSampleGenerator(this HttpConfiguration config, HelpPageSampleGenerator sampleGenerator)
|
||||
{
|
||||
config.Properties.AddOrUpdate(
|
||||
typeof(HelpPageSampleGenerator),
|
||||
k => sampleGenerator,
|
||||
(k, o) => sampleGenerator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the model description generator.
|
||||
/// </summary>
|
||||
/// <param name="config">The configuration.</param>
|
||||
/// <returns>The <see cref="ModelDescriptionGenerator"/></returns>
|
||||
public static ModelDescriptionGenerator GetModelDescriptionGenerator(this HttpConfiguration config)
|
||||
{
|
||||
return (ModelDescriptionGenerator)config.Properties.GetOrAdd(
|
||||
typeof(ModelDescriptionGenerator),
|
||||
k => InitializeModelDescriptionGenerator(config));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the model that represents an API displayed on the help page. The model is initialized on the first call and cached for subsequent calls.
|
||||
/// </summary>
|
||||
/// <param name="config">The <see cref="HttpConfiguration"/>.</param>
|
||||
/// <param name="apiDescriptionId">The <see cref="ApiDescription"/> ID.</param>
|
||||
/// <returns>
|
||||
/// An <see cref="HelpPageApiModel"/>
|
||||
/// </returns>
|
||||
public static HelpPageApiModel GetHelpPageApiModel(this HttpConfiguration config, string apiDescriptionId)
|
||||
{
|
||||
object model;
|
||||
string modelId = ApiModelPrefix + apiDescriptionId;
|
||||
if (!config.Properties.TryGetValue(modelId, out model))
|
||||
{
|
||||
Collection<ApiDescription> apiDescriptions = config.Services.GetApiExplorer().ApiDescriptions;
|
||||
ApiDescription apiDescription = apiDescriptions.FirstOrDefault(api => String.Equals(api.GetFriendlyId(), apiDescriptionId, StringComparison.OrdinalIgnoreCase));
|
||||
if (apiDescription != null)
|
||||
{
|
||||
model = GenerateApiModel(apiDescription, config);
|
||||
config.Properties.TryAdd(modelId, model);
|
||||
}
|
||||
}
|
||||
|
||||
return (HelpPageApiModel)model;
|
||||
}
|
||||
|
||||
private static HelpPageApiModel GenerateApiModel(ApiDescription apiDescription, HttpConfiguration config)
|
||||
{
|
||||
HelpPageApiModel apiModel = new HelpPageApiModel()
|
||||
{
|
||||
ApiDescription = apiDescription,
|
||||
};
|
||||
|
||||
ModelDescriptionGenerator modelGenerator = config.GetModelDescriptionGenerator();
|
||||
HelpPageSampleGenerator sampleGenerator = config.GetHelpPageSampleGenerator();
|
||||
GenerateUriParameters(apiModel, modelGenerator);
|
||||
GenerateRequestModelDescription(apiModel, modelGenerator, sampleGenerator);
|
||||
GenerateResourceDescription(apiModel, modelGenerator);
|
||||
GenerateSamples(apiModel, sampleGenerator);
|
||||
|
||||
return apiModel;
|
||||
}
|
||||
|
||||
private static void GenerateUriParameters(HelpPageApiModel apiModel, ModelDescriptionGenerator modelGenerator)
|
||||
{
|
||||
ApiDescription apiDescription = apiModel.ApiDescription;
|
||||
foreach (ApiParameterDescription apiParameter in apiDescription.ParameterDescriptions)
|
||||
{
|
||||
if (apiParameter.Source == ApiParameterSource.FromUri)
|
||||
{
|
||||
HttpParameterDescriptor parameterDescriptor = apiParameter.ParameterDescriptor;
|
||||
Type parameterType = null;
|
||||
ModelDescription typeDescription = null;
|
||||
ComplexTypeModelDescription complexTypeDescription = null;
|
||||
if (parameterDescriptor != null)
|
||||
{
|
||||
parameterType = parameterDescriptor.ParameterType;
|
||||
typeDescription = modelGenerator.GetOrCreateModelDescription(parameterType);
|
||||
complexTypeDescription = typeDescription as ComplexTypeModelDescription;
|
||||
}
|
||||
|
||||
// Example:
|
||||
// [TypeConverter(typeof(PointConverter))]
|
||||
// public class Point
|
||||
// {
|
||||
// public Point(int x, int y)
|
||||
// {
|
||||
// X = x;
|
||||
// Y = y;
|
||||
// }
|
||||
// public int X { get; set; }
|
||||
// public int Y { get; set; }
|
||||
// }
|
||||
// Class Point is bindable with a TypeConverter, so Point will be added to UriParameters collection.
|
||||
//
|
||||
// public class Point
|
||||
// {
|
||||
// public int X { get; set; }
|
||||
// public int Y { get; set; }
|
||||
// }
|
||||
// Regular complex class Point will have properties X and Y added to UriParameters collection.
|
||||
if (complexTypeDescription != null
|
||||
&& !IsBindableWithTypeConverter(parameterType))
|
||||
{
|
||||
foreach (ParameterDescription uriParameter in complexTypeDescription.Properties)
|
||||
{
|
||||
apiModel.UriParameters.Add(uriParameter);
|
||||
}
|
||||
}
|
||||
else if (parameterDescriptor != null)
|
||||
{
|
||||
ParameterDescription uriParameter =
|
||||
AddParameterDescription(apiModel, apiParameter, typeDescription);
|
||||
|
||||
if (!parameterDescriptor.IsOptional)
|
||||
{
|
||||
uriParameter.Annotations.Add(new ParameterAnnotation() { Documentation = "Required" });
|
||||
}
|
||||
|
||||
object defaultValue = parameterDescriptor.DefaultValue;
|
||||
if (defaultValue != null)
|
||||
{
|
||||
uriParameter.Annotations.Add(new ParameterAnnotation() { Documentation = "Default value is " + Convert.ToString(defaultValue, CultureInfo.InvariantCulture) });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Assert(parameterDescriptor == null);
|
||||
|
||||
// If parameterDescriptor is null, this is an undeclared route parameter which only occurs
|
||||
// when source is FromUri. Ignored in request model and among resource parameters but listed
|
||||
// as a simple string here.
|
||||
ModelDescription modelDescription = modelGenerator.GetOrCreateModelDescription(typeof(string));
|
||||
AddParameterDescription(apiModel, apiParameter, modelDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsBindableWithTypeConverter(Type parameterType)
|
||||
{
|
||||
if (parameterType == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return TypeDescriptor.GetConverter(parameterType).CanConvertFrom(typeof(string));
|
||||
}
|
||||
|
||||
private static ParameterDescription AddParameterDescription(HelpPageApiModel apiModel,
|
||||
ApiParameterDescription apiParameter, ModelDescription typeDescription)
|
||||
{
|
||||
ParameterDescription parameterDescription = new ParameterDescription
|
||||
{
|
||||
Name = apiParameter.Name,
|
||||
Documentation = apiParameter.Documentation,
|
||||
TypeDescription = typeDescription,
|
||||
};
|
||||
|
||||
apiModel.UriParameters.Add(parameterDescription);
|
||||
return parameterDescription;
|
||||
}
|
||||
|
||||
private static void GenerateRequestModelDescription(HelpPageApiModel apiModel, ModelDescriptionGenerator modelGenerator, HelpPageSampleGenerator sampleGenerator)
|
||||
{
|
||||
ApiDescription apiDescription = apiModel.ApiDescription;
|
||||
foreach (ApiParameterDescription apiParameter in apiDescription.ParameterDescriptions)
|
||||
{
|
||||
if (apiParameter.Source == ApiParameterSource.FromBody)
|
||||
{
|
||||
Type parameterType = apiParameter.ParameterDescriptor.ParameterType;
|
||||
apiModel.RequestModelDescription = modelGenerator.GetOrCreateModelDescription(parameterType);
|
||||
apiModel.RequestDocumentation = apiParameter.Documentation;
|
||||
}
|
||||
else if (apiParameter.ParameterDescriptor != null &&
|
||||
apiParameter.ParameterDescriptor.ParameterType == typeof(HttpRequestMessage))
|
||||
{
|
||||
Type parameterType = sampleGenerator.ResolveHttpRequestMessageType(apiDescription);
|
||||
|
||||
if (parameterType != null)
|
||||
{
|
||||
apiModel.RequestModelDescription = modelGenerator.GetOrCreateModelDescription(parameterType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateResourceDescription(HelpPageApiModel apiModel, ModelDescriptionGenerator modelGenerator)
|
||||
{
|
||||
ResponseDescription response = apiModel.ApiDescription.ResponseDescription;
|
||||
Type responseType = response.ResponseType ?? response.DeclaredType;
|
||||
if (responseType != null && responseType != typeof(void))
|
||||
{
|
||||
apiModel.ResourceDescription = modelGenerator.GetOrCreateModelDescription(responseType);
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The exception is recorded as ErrorMessages.")]
|
||||
private static void GenerateSamples(HelpPageApiModel apiModel, HelpPageSampleGenerator sampleGenerator)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var item in sampleGenerator.GetSampleRequests(apiModel.ApiDescription))
|
||||
{
|
||||
apiModel.SampleRequests.Add(item.Key, item.Value);
|
||||
LogInvalidSampleAsError(apiModel, item.Value);
|
||||
}
|
||||
|
||||
foreach (var item in sampleGenerator.GetSampleResponses(apiModel.ApiDescription))
|
||||
{
|
||||
apiModel.SampleResponses.Add(item.Key, item.Value);
|
||||
LogInvalidSampleAsError(apiModel, item.Value);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
apiModel.ErrorMessages.Add(String.Format(CultureInfo.CurrentCulture,
|
||||
"An exception has occurred while generating the sample. Exception message: {0}",
|
||||
HelpPageSampleGenerator.UnwrapException(e).Message));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryGetResourceParameter(ApiDescription apiDescription, HttpConfiguration config, out ApiParameterDescription parameterDescription, out Type resourceType)
|
||||
{
|
||||
parameterDescription = apiDescription.ParameterDescriptions.FirstOrDefault(
|
||||
p => p.Source == ApiParameterSource.FromBody ||
|
||||
(p.ParameterDescriptor != null && p.ParameterDescriptor.ParameterType == typeof(HttpRequestMessage)));
|
||||
|
||||
if (parameterDescription == null)
|
||||
{
|
||||
resourceType = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
resourceType = parameterDescription.ParameterDescriptor.ParameterType;
|
||||
|
||||
if (resourceType == typeof(HttpRequestMessage))
|
||||
{
|
||||
HelpPageSampleGenerator sampleGenerator = config.GetHelpPageSampleGenerator();
|
||||
resourceType = sampleGenerator.ResolveHttpRequestMessageType(apiDescription);
|
||||
}
|
||||
|
||||
if (resourceType == null)
|
||||
{
|
||||
parameterDescription = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static ModelDescriptionGenerator InitializeModelDescriptionGenerator(HttpConfiguration config)
|
||||
{
|
||||
ModelDescriptionGenerator modelGenerator = new ModelDescriptionGenerator(config);
|
||||
Collection<ApiDescription> apis = config.Services.GetApiExplorer().ApiDescriptions;
|
||||
foreach (ApiDescription api in apis)
|
||||
{
|
||||
ApiParameterDescription parameterDescription;
|
||||
Type parameterType;
|
||||
if (TryGetResourceParameter(api, config, out parameterDescription, out parameterType))
|
||||
{
|
||||
modelGenerator.GetOrCreateModelDescription(parameterType);
|
||||
}
|
||||
}
|
||||
return modelGenerator;
|
||||
}
|
||||
|
||||
private static void LogInvalidSampleAsError(HelpPageApiModel apiModel, object sample)
|
||||
{
|
||||
InvalidSample invalidSample = sample as InvalidSample;
|
||||
if (invalidSample != null)
|
||||
{
|
||||
apiModel.ErrorMessages.Add(invalidSample.ErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
namespace CELA_Tags_Parsing_Service.Areas.HelpPage.ModelDescriptions
|
||||
{
|
||||
public class CollectionModelDescription : ModelDescription
|
||||
{
|
||||
public ModelDescription ElementDescription { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace CELA_Tags_Parsing_Service.Areas.HelpPage.ModelDescriptions
|
||||
{
|
||||
public class ComplexTypeModelDescription : ModelDescription
|
||||
{
|
||||
public ComplexTypeModelDescription()
|
||||
{
|
||||
Properties = new Collection<ParameterDescription>();
|
||||
}
|
||||
|
||||
public Collection<ParameterDescription> Properties { get; private set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
namespace CELA_Tags_Parsing_Service.Areas.HelpPage.ModelDescriptions
|
||||
{
|
||||
public class DictionaryModelDescription : KeyValuePairModelDescription
|
||||
{
|
||||
}
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче