diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1ff0c42
--- /dev/null
+++ b/.gitattributes
@@ -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
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2897a19
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,409 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+/Manifest/pilot/pilot.zip
+/Manifest/askhr/askhr.zip
+
+
+
+# https://github.com/angular/angular/blob/master/.gitignore
+.DS_STORE
+
+/dist/
+/bazel-out
+/integration/bazel/bazel-*
+e2e_test.*
+*.log
+node_modules
+tools/gulp-tasks/cldr/cldr-data/
+
+# Include when developing application packages.
+pubspec.lock
+.c9
+.idea/
+.devcontainer/*
+!.devcontainer/recommended-devcontainer.json
+!.devcontainer/recommended-Dockerfile
+.settings/
+.vscode/launch.json
+.vscode/settings.json
+*.swo
+modules/.settings
+modules/.vscode
+.vimrc
+.nvimrc
+
+# Don't check in secret files
+*secret.js
+*.secret.config
+
+# Ignore npm/yarn debug log
+npm-debug.log
+yarn-error.log
+
+# build-analytics
+.build-analytics
+
+# rollup-test output
+/modules/rollup-test/dist/
+
+# User specific bazel settings
+.bazelrc.user
+
+.notes.md
+baseline.json
+/Source/DashboardTabApp/wwwroot
+/Source/QuestionsTabApp/wwwroot
+/Source/DashboardTabApp/Properties/launchSettings.json
+/Source/DashboardTabApp/Properties
+/Manifest/azureDeploy/azureDeploy.zip
diff --git a/.tfignore b/.tfignore
new file mode 100644
index 0000000..38b87bf
--- /dev/null
+++ b/.tfignore
@@ -0,0 +1,2 @@
+\packages
+!\packages\repositories.config
\ No newline at end of file
diff --git a/Documentation/2019-12-18 14_14_54-Bot Channels Registration - Microsoft Azure.png b/Documentation/2019-12-18 14_14_54-Bot Channels Registration - Microsoft Azure.png
new file mode 100644
index 0000000..61ad572
Binary files /dev/null and b/Documentation/2019-12-18 14_14_54-Bot Channels Registration - Microsoft Azure.png differ
diff --git a/Documentation/2019-12-18 16_21_54-Register an application - Microsoft Azure.png b/Documentation/2019-12-18 16_21_54-Register an application - Microsoft Azure.png
new file mode 100644
index 0000000..7756ba3
Binary files /dev/null and b/Documentation/2019-12-18 16_21_54-Register an application - Microsoft Azure.png differ
diff --git a/Documentation/app-reg-permissions.png b/Documentation/app-reg-permissions.png
new file mode 100644
index 0000000..e602e49
Binary files /dev/null and b/Documentation/app-reg-permissions.png differ
diff --git a/Documentation/bot-channel-registration-settings.png b/Documentation/bot-channel-registration-settings.png
new file mode 100644
index 0000000..817bcb1
Binary files /dev/null and b/Documentation/bot-channel-registration-settings.png differ
diff --git a/Documentation/bot-reg-teams-channel.png b/Documentation/bot-reg-teams-channel.png
new file mode 100644
index 0000000..b567147
Binary files /dev/null and b/Documentation/bot-reg-teams-channel.png differ
diff --git a/Documentation/dashboard-tab-add-student.png b/Documentation/dashboard-tab-add-student.png
new file mode 100644
index 0000000..8bb1ccb
Binary files /dev/null and b/Documentation/dashboard-tab-add-student.png differ
diff --git a/Documentation/datamodel.png b/Documentation/datamodel.png
new file mode 100644
index 0000000..de5cad3
Binary files /dev/null and b/Documentation/datamodel.png differ
diff --git a/Documentation/overview.png b/Documentation/overview.png
new file mode 100644
index 0000000..acd0824
Binary files /dev/null and b/Documentation/overview.png differ
diff --git a/Documentation/qna-configure.png b/Documentation/qna-configure.png
new file mode 100644
index 0000000..ed160ce
Binary files /dev/null and b/Documentation/qna-configure.png differ
diff --git a/Documentation/qna-deploy.png b/Documentation/qna-deploy.png
new file mode 100644
index 0000000..9030e42
Binary files /dev/null and b/Documentation/qna-deploy.png differ
diff --git a/Documentation/setup.md b/Documentation/setup.md
new file mode 100644
index 0000000..e572255
--- /dev/null
+++ b/Documentation/setup.md
@@ -0,0 +1,421 @@
+# QBot Setup
+## Azure Resources
+Here is a summary of all Azure resources that need to be created
+|#|Resource Type|Description|
+|:-|:-|:-|:-|
+|1|Resource Group|Logical container to place all QBot related Azure resources|
+|2|Bot Channels Registration|QBot Bot Channels Registration|
+|3|Cognitive Services|Cognitive Services to host QnA KBs|
+|4|Search Service|Part of Cognitive Services for QnA KBs|
+|5|QnA Knowledge Base|The backing QnA KB where QBot will get answers from. You are required to have one QnA KB per Course|
+|6|SQL Database|Stores QBot related processing data|
+|8|App Service|Hosts the [QBot API Web Service]()|
+|9|App Service|Hosts the [Dashboard Tab App](#dashboard-tab-web-app) Angular site|
+|10|App Service|Hosts the [Questions Tab App](#questions-tab-web-app) Angular site|
+|11|App Registration|To support the Bot Channels Registration|
+|11|App Registration|To support the QBot API authentication|
+|12|App Registration|To support Graph API access|
+
+
+---
+
+### QBot Resource Group
+Create new Azure *Resource Group* as a logical container to place all resources provisioned
+This can help you monitor costs more easily.
+
+### QBot API Web App
+Create a new **Web App** with the following values
+
+|Setting|Value|
+|:-|:-|
+|Name|Something easily identifiable as QBot API Example: `qbot-api.azurewebsites.net`|
+|Runtime Stack|ASP.NET V4.7|
+
+> Please note the following settings for later:
+> The QBot API Web App URL
+> eg: `https://qbot-api.azurewebsites.net`
+
+### Dashboard Tab Web App
+Create a new **Web App** with the following values
+
+|Setting|Value|
+|:-|:-|
+|Name|Something easily identifiable as Dashboard Tab Example: `qbot-dashboard-tab.azurewebsites.net`|
+|Runtime Stack|.NET Core 2.2|
+
+> Please note the following settings for later:
+> The Dashboard Tab Web App URL
+> eg: `https://qbot-dashboard-tab.azurewebsites.net`
+
+### Questions Tab Web App
+Create a new **Web App** with the following values
+
+|Setting|Value|
+|:-|:-|
+|Name|Something easily identifiable as Question Tab Example: `qbot-questions-tab.azurewebsites.net`|
+|Runtime Stack|.NET Core 2.2|
+
+> Please note the following settings for later:
+> The Question Tab Web App URL
+> eg: `https://qbot-questions-tab.azurewebsites.net`
+
+### SQL Server
+Create a new **SQL Database** with the following values
+|Setting|Value|
+|:-|:-|
+|Collation|SQL_Latin1_General_CP1_CI_AS|
+
+> Please note the following settings for later:
+> The Azure SQL Server connection string
+> eg: `data source=qbot-azure-sql-server;initial catalog=qbot-db;user id=sql-user;password=*****;MultipleActiveResultSets=True;App=EntityFramework"`
+
+
+#### Bot Channels App Registration
+Create a new Azure *App Registration* for the purpose of Bot Channels Registration.
+You will need to be an Application Administrator on your tenant
+
+|Setting|Value|
+|:-|:-|
+|Account Type|*Accounts in any organizational directory (Any Azure AD directory - Multitenant)*|
+
+> Please note the following settings for later: **Application (client) ID**
+
+#### QBot API Auth App Registration
+The custom Teams tabs are Angular apps that call the QBot API service (.NET Web API). This App Registration is used to authenticate these API calls.
+
+Create a new **App Registration** for the purpose of QBot API Authentication.
+You will need to be an Application Administrator on your tenant
+
+|Setting|Value|
+|:-|:-|
+|Account Type|*Accounts in any organizational directory (Any Azure AD directory - Multitenant)*|
+|Authentication Redirect URIs|https://qbot-dashboard-tab.azurewebsites.net/app-silent-end https://qbot-questions-tab.azurewebsites.net/app-silent-end Note: These are the same URLs where you deployed the [Dashboard Tab](#dashboard-tab-web-app) and the [Questions Tab](#questions-tab-web-app)
+
+> Please note the following settings for later:
+> **Application (client) ID**
+> **Directory (tenant) ID**
+
+#### Graph API Access App Registration
+The QBot API service in turn calls Graph API to retrieve information like the questions asked, and conversations within a channel. This App Registration is used to authenticate these Graph API calls.
+
+Create a new **App Registration** to allow Graph API access.
+You will need to be an Application Administrator on your tenant.
+
+|Setting|Value|
+|:-|:-|
+|Account Type|*Accounts in any organizational directory (Any Azure AD directory - Multitenant)*|
+|API Permissions|Add the following API permissions: Name: **Reports.ReadAll** Type: **Application** Consent: **Required**
+
+> Please note the following settings for later: **Application (Client) ID**
+
+### Bot Channels Registration
+Create a new **Bot Channels Registration** resource with the following values:
+
+|Setting|Value|
+|:-|:-|
+|Bot handle|Any unique identifier, you can change the bot display name later|
+|Pricing Tier|Pick an appropriate pricing tier for your needs|
+|Messaging EndPoint|(QBot API URL)`/api/messages` Example If QBot API will be deployed to `https://qbot-api.azurewebsites.net` then enter in `https://qbot-api.azurewebsites.net/api/messages`|
+|Microsoft App ID and password|Auto create App ID and password|
+
+When finished, go into the newly created Bot Channels Registration, under **Settings** tab:
+
+> Please note the following settings for later:
+> * Note down the **Microsoft App ID**
+> * Click **Manage**
+> * Note down a secret
+
+Click on Channels setting, and add *Microsoft Teams* as a featured channel
+
+![](bot-reg-teams-channel.png)
+
+
+### QnA Maker
+QBot uses QnA maker as it's knowlege base of questions and answers. Each course in QBot will require a back-end QnA KB provisioned, and this relationship is 1-1, ie. One QnA KB required per QBot Course.
+
+https://www.qnamaker.ai/Create
+
+1. Create a new QnA Service. Select an appropriate pricing tier to store all KBs for all required courses
+2. Create the KB, and take note of the KB Name
+3. (Optional) Populate your KB with initial data or add a chit-chat persona.
+4. Publish the KB
+
+
+> Please take note of the following settings for later:
+> ![](qna-deploy.png)
+> 1. **QnA Service Host** - The full Host header
+> 2. **QnA Knowledge Base ID** - The GUID part of the POST URL
+> 3. **QnA Endpoint Key** - The GUID part of the Authorization header
+> ![](qna-configure.png)
+> 4. **QnA HTTP Endpoint**
+> 5. **QnA HTTP Key**
+
+
+
+## QBot Application Build & Deployment
+After your Azure resources are setup, next step is to Build QBot from source control. Grab the latest copy of all source code from the Git repo.
+
+
+### QBot API
+QBot API project is called `Microsoft.Teams.Apps.QBot.Bot` and is a .NET 4.5 Web API
+
+#### Updates to web.config
+The following values need to be updated, depending on the environment and installation details. `Web.config` separates it's secrets in 2 external files: `appSettings.secret.config` and `connectionStrings.secret.config`
+
+``` xml
+
+
+```
+
+``` xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+|Key|Description|Value|
+|:-|:-|:-|
+|BotId|The Bot ID|`Question`|
+|BaseUrl|The root URL where the [QBot API Web App](#qbot-api-web-app) was deployed|`https://qbot-api.au.ngrok.io`|
+|MicrosoftAppId|Bot Channels Registration Microsoft App ID|Refer to steps in [Bot Registration](https://)|
+|MicrosoftAppPassword|Bot Channels Registration Secret|Refer to steps in [Bot Registration](https://)|
+|AADAuthority|Graph API target resource identifier|`https://login.microsoftonline.com/(tenantId)`|
+|AADServiceName|QBot service account. Must be a valid Teams account|svc_qbot@unsw.edu.au|
+|AADServicePassword|Encrypted password of the above QBot service account|Use the encryption project to encrypt the password|
+|AADClientId|Client ID of the Azure App Registration that uses Graph API to access Teams conversations and replies|Refer to steps in [Graph API App Registration](https://)|
+|ida:ClientId|Client ID of the Azure App Registration reuired to authenticate the QBot API|Refer to steps in [QBot API Authentication App Registration](https://)|
+|ida:TenantId|QBot API Auth Azure App Registration - Tenant ID|Refer to steps in [QBot API Authentication App Registration](https://)|
+|ida:Audience|QBot API Auth Azure App Registration - Application ID|api://5e55f7ba-8453-41b2-a274-75b6a71e4473|
+
+``` xml
+
+
+
+
+
+
+```
+
+Finally Right-click and publish to your [QBot API](#qbot) web site
+
+### Angular apps - Dashboard Tab & Questions Tab
+There are 2 Teams tabs, developed as Angular applications. They are in the projects: `DashboardTabApp` and `QuestionsTabApp`. Both are built and deployed in the same way.
+
+
+Open up `Source\DashboardTabApp\src\environments\environment.ts` and make the following changes
+``` typescript
+export const environment = {
+ production: false,
+ apiBaseUrl: "https://qbot-api.azurewebsites.net/api/Request/",
+
+ authConfig: {
+ instance: "https://login.microsoftonline.com/",
+ tenantId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
+ clientId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
+ redirectUri: "/app-silent-end",
+ cacheLocation: "localStorage",
+ navigateToLoginRequestUrl: false,
+ extraQueryParameters: "",
+ popUp: true,
+ popUpUri: "/app-silent-start",
+ popUpWidth: 600,
+ popUpHeight: 535
+ },
+
+ // do not populate the following:
+ upn: "",
+ tid: "",
+};
+```
+Key|Value
+:-|:-
+apiBaseUrl|The URL where the [QBot API Web App](#qbot-api-web-app) is deployed, with `/api/Request/` appended
+tenantId|The Directory (tenant) ID of the [QBot API Auth App Registration](#qbot-api-auth-app-registration)
+clientId|The Application (client) ID of the [QBot API Auth App Registration](#qbot-api-auth-app-registration)
+
+
+Open up `Source\QuestionTabApp\src\environments\environment.ts` and make the following changes
+``` typescript
+export const environment = {
+ production: false,
+ apiBaseUrl: "https://qbot-api.azurewebsites.net/api/Request/",
+ selfUrl: "",
+
+ authConfig: {
+ instance: "https://login.microsoftonline.com/",
+ tenantId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
+ clientId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
+ redirectUri: "/app-silent-end",
+ cacheLocation: "localStorage",
+ navigateToLoginRequestUrl: false,
+ extraQueryParameters: "",
+ popUp: true,
+ popUpUri: "/app-silent-start",
+ popUpWidth: 600,
+ popUpHeight: 535
+ },
+
+ // do not populate the following:
+ upn: "",
+ tid: "",
+ gid: "",
+ cname: ""
+};
+```
+Key|Value
+:-|:-
+apiBaseUrl|The URL where the [QBot API Web App](#qbot-api-web-app) is deployed, with `/api/Request/` appended
+tenantId|The Directory (tenant) ID of the [QBot API Auth App Registration](#qbot-api-auth-app-registration)
+clientId|The Application (client) ID of the [QBot API Auth App Registration](#qbot-api-auth-app-registration)
+
+Run the following commands to restore packages and build
+```
+npm install
+ng-build
+```
+
+The output dist files will be generated in their respective `wwwroot` folder.
+
+For the Angular `DashboardTabApp` application, copy these files to the [Dashboard Tab Web App]() application.
+For the Angular `QuestionsTabApp` application, copy these files to the [Questions Tab Web App]() application.
+
+
+### SQL Database configuration
+Run the included SSDT package to create the initial SQL database structure to the [SQL Server]()
+
+
+### Deploy the Bot to Teams
+#### Prepare the manifest file
+Edit the `manifest.json` file, and replace the following values:
+
+``` json
+{
+ "$schema": "https://statics.teams.microsoft.com/sdk/v1.2/manifest/MicrosoftTeams.schema.json",
+ "manifestVersion": "1.2",
+ "version": "1.0.0",
+ "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
+ "packageName": "qbot",
+ "developer": {
+ "name": "UNSW Sydney",
+ "websiteUrl": "https://www.unsw.edu.au/",
+ "privacyUrl": "https://www.unsw.edu.au/",
+ "termsOfUseUrl": "https://www.unsw.edu.au/"
+ },
+ "icons": {
+ "outline": "qbot.png",
+ "color": "qbot.png"
+ },
+ "name": {
+ "short": "Question",
+ "full": "Question"
+ },
+ "description": {
+ "short": "QBot",
+ "full": "QBot keeps track of answered and unanswered questions, sends notifications to tutors and teachers in charge, and dynamically constructs its own knowledge database on the subject to help suggest answers in future. Just tag @question in the conversations tab of your class Team."
+ },
+ "accentColor": "#3F487F",
+ "composeExtensions": [
+ {
+ "botId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
+ "canUpdateConfiguration": true,
+ "commands": [
+ {
+ "id": "SelectAnswer",
+ "description": "Select an answer",
+ "title": "Select answer",
+ "type": "action",
+ "context": [ "message" ],
+ "fetchTask": true,
+ "parameters": [ { "name": "SelectAnswer", "title": "Select Answer" } ]
+ }
+ ]
+ }
+ ],
+ "configurableTabs": [
+ {
+ "configurationUrl": "https://qbot-questions-tab.azurewebsites.net/#/config?upn={upn}&tid={tid}&gid={gid}&cname={channelName}",
+ "canUpdateConfiguration": true,
+ "scopes": [
+ "team"
+ ]
+ }
+ ],
+ "bots": [
+ {
+ "botId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
+ "scopes": [
+ "team",
+ "personal"
+ ]
+ }
+ ],
+ "staticTabs": [
+ {
+ "entityId": "DashboardTab",
+ "name": "Dashboard",
+ "contentUrl": "https://qbot-dashboard-tab.azurewebsites.net/#/home?upn={upn}&tid={tid}&gid={groupId}&uid={userObjectId}",
+ "scopes": [ "personal" ]
+ }
+ ],
+ "permissions": [
+ "identity",
+ "messageTeamMembers"
+ ],
+ "validDomains": [ "qbot-dashboard-tab.azurewebsites.net", "qbot-questions-tab.azurewebsites.net", "qbot-api.azurewebsites.net" ]
+}
+```
+
+|Key|Value|
+|:-|:-|
+id|Microsoft AppID (GUID) from the [Bot Channel Registration](#bot-channels-registration)
+botId|Microsoft AppID (GUID) from the [Bot Channel Registration](#bot-channels-registration). Remember to replace **both instances** in the `manifest.json`
+configurationUrl|URL of the deployed [Question Tab Angular web application](#questions-tab-web-app) with `/#/config?upn={upn}&tid={tid}&gid={gid}&cname={channelName}` appended.
+contentUrl|URL of the deployed [Dashboard Tab Angular web application](#dashboard-tab-web-app) with `/#/home?upn={upn}&tid={tid}&gid={groupId}&uid={userObjectId}` appended.
+validDomains|Array of three strings representing the domains of the [Bot API Web App](#qbot-api-web-app), [Question Tab](#questions-tab-web-app) and [Dashboard Tab](#dashboard-tab-web-app)
+
+
+So now, within Manifest` folder there will be 2 files
+* `manifest.json` - Manifest file, which we just updated in steps above
+* `bot_blue.png` - Starter bot icon
+
+Zip up into a new package file (eg. `qbot-manifest.zip`) ready for upload into Teams
+
+### Add QBot app into Teams
+1. You must be a team owner
+2. In Teams, go to the Team the Bot will be deployed to and click on the ‘+’ symbol under the Team title at the top of the window.
+3. In the popup click on *Manage apps* at the bottom right corner which will navigate to the Apps page for that team.
+4. At the bottom right corner click on *Upload a custom app* and select the .zip file created earlier which will add the bot to the Team.
+
+
+## QBot Setup
+Congratulations, you have succesfully built the QBot solution, and added the App into Teams. Final step is to set up the different courses
+
+1. Go to the dashboard tab (initiate a personal coversation with the Bot)
+2. Create a new course
+3. Fill in the following values:
+
+|Setting| Value|
+|:-|:-|
+|CourseName|Dropdown will show all Teams that you are a owner of. Select the Team to use as your course|
+|[PredictiveQnAServiceHost]|Host property + “/” when the QnA maker is published.1 |
+|[PredictiveQnAKnowledgeBaseId]|GUID part of the POST command.2 |
+|[PredictiveQnAEndpointKey]|GUID part of Authorization.3 |
+|[PredictiveQnAHttpKey]|Key of the Cognitive Service.4 |
+|[PredictiveQnAHttpEndpoint]|Endpoint of the Cognitive Service.5 |
+|[PredictiveQnAKnowledgeBaseName]|Name of knowledgebase for the course on QnA Maker|
+|[PredictiveQnAConfidenceThreshold]|Integer that should be from 0-100 that reflects the confidence percentage an answer from QnA Maker must be if it is to be supplied as an answer to a question.|
+
+4. Create the required Tutorial Groups
+5. Assign and Map Users. Click the *Synchronise from Teams* button and assign their roles and any necessary tutorial groups
diff --git a/Documentation/web.config.png b/Documentation/web.config.png
new file mode 100644
index 0000000..3e3b642
Binary files /dev/null and b/Documentation/web.config.png differ
diff --git a/Manifest/manifest.json b/Manifest/manifest.json
new file mode 100644
index 0000000..d8361e8
--- /dev/null
+++ b/Manifest/manifest.json
@@ -0,0 +1,79 @@
+{
+ "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json",
+ "manifestVersion": "1.5",
+ "version": "1.0",
+ "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
+ "packageName": "your-qbot-package-name",
+ "developer": {
+ "name": "Anything unique",
+ "websiteUrl": "https://github.com/unsw-edu-au/QBot",
+ "privacyUrl": "https://github.com/unsw-edu-au/QBot",
+ "termsOfUseUrl": "https://github.com/unsw-edu-au/QBot"
+ },
+ "icons": {
+ "outline": "qbot.png",
+ "color": "qbot.png"
+ },
+ "name": {
+ "short": "Question",
+ "full": "Question"
+ },
+ "description": {
+ "short": "QBot",
+ "full": "QBot keeps track of answered and unanswered questions, sends notifications to tutors and teachers in charge, and dynamically constructs its own knowledge database on the subject to help suggest answers in future. Just tag @question in the conversations tab of your class Team."
+ },
+ "accentColor": "#3F487F",
+ "composeExtensions": [
+ {
+ "botId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
+ "canUpdateConfiguration": true,
+ "commands": [
+ {
+ "id": "SelectAnswer",
+ "description": "Select an answer",
+ "title": "Select answer",
+ "type": "action",
+ "context": [ "message" ],
+ "fetchTask": true,
+ "parameters": [
+ {
+ "name": "SelectAnswer",
+ "title": "Select Answer"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "configurableTabs": [
+ {
+ "configurationUrl": "https://qbot-questions-tab.azurewebsites.net/#/config?upn={upn}&tid={tid}&gid={gid}&cname={channelName}",
+ "canUpdateConfiguration": true,
+ "scopes": [
+ "team"
+ ]
+ }
+ ],
+ "bots": [
+ {
+ "botId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
+ "scopes": [
+ "team",
+ "personal"
+ ]
+ }
+ ],
+ "staticTabs": [
+ {
+ "entityId": "DashboardTab",
+ "name": "Dashboard",
+ "contentUrl": "https://qbot-dashboard-tab.azurewebsites.net/#/home?upn={upn}&tid={tid}&gid={groupId}&uid={userObjectId}",
+ "scopes": [ "personal" ]
+ }
+ ],
+ "permissions": [
+ "identity",
+ "messageTeamMembers"
+ ],
+ "validDomains": [ "qbot-dashboard-tab.azurewebsites.net", "qbot-questions-tab.azurewebsites.net", "qbot-api.azurewebsites.net" ]
+}
\ No newline at end of file
diff --git a/Manifest/qbot.png b/Manifest/qbot.png
new file mode 100644
index 0000000..70d5f94
Binary files /dev/null and b/Manifest/qbot.png differ
diff --git a/Readme.md b/Readme.md
new file mode 100644
index 0000000..05b5f80
--- /dev/null
+++ b/Readme.md
@@ -0,0 +1,136 @@
+# Microsoft Teams QBot
+
+## [Overview](#overview)
+QBot is a solution designed for classroom teaching scenarios which allow teachers, tutors and students to intelligently answer each other's questions within the Microsoft Teams collaboration platform. It leverages the power of Azure Cognitive Services, in particular QnA Maker to achieve this.
+
+The solution was originally developed, and is currently deployed for the School of Mechanical and Manufacturing Engineering at the University of New South Wales (UNSW) in Sydney, Australia.
+
+## [How It Works](#how-it-works)
+Once QBot is deployed to a Microsoft Team channel, a student can ask a question on the channel by @tagging QBot. QBot can be tagged or used contextually: for example, a student may write “I have a @question regarding the units used to measure force?”, or “I don’t know how to differentiate the function for bending moment for @question 2.14 of the tutorial problems”
+
+QBot interprets the message, and checks QnA Maker knowledge base for the answer. If an answer is found, QBot will notify the student and respond to the original conversation thread with with an adaptive card.
+
+Otherwise, QBot will record the question as "unanswered", whilst @tagging a tutor within the course. The tutor visits a custom "Questions" tab deployed to the Teams Channel, and inputs their answer. Note that other students can also collaborate and try to answer this question from their fellow classmates, however only the original poster, tutor or lecturer can "accept" the answer.
+
+Once "accepted", QBot takes the answer and trains the QnA Maker knowledge base for future reference. This aims to progressively build a knowledge database of high quality successfully answered questions.
+
+The QBot solution also deploys additional custom tabs within the Team to help with management of courses, students and questions:
+
+**Questions Tab** - Displays the consolidated list of answered and unanswered questions posted within the channel. Can be accessed by all students and tutors.
+
+**Dashboard Tab** - Allows management and configuration of courses, students, roles and other general QBot cognitive services settings. Can only be accessed by course administrators.
+* For “student” role, view all questions they asked or answered, filterable by topic.
+* For “demonstrator” role, view all questions for each tutorial group they oversee.
+* For “lecturer” role, view all questions for each tutorial group as well as access to QBot configuration.
+
+
+QBot also supports usage with multiple courses. Each course is run within it's own Microsoft Team.
+
+## [Deployment Architecture](#architecture)
+
+![overview](Documentation\overview.png)
+
+#### [Teams](#teams)
+The QBot solution bot manifest file is uploaded to each course run within a Microsoft Team. This enables the bot itself, as well as additional tabs to support QBot functionality.
+
+#### [Question Bot Connector](#bot-connector)
+A Microsoft Bot Channels Registration. The messaging endpoint will be point to the [Question Bot App Service](#question-bot-app-service) and must enable connection to a Microsoft Teams channel.
+
+
+#### [Question Bot App Service](#question-bot-app-service)
+This is an .NET Web API hosted within an Azure App Service.
+It handles the bot conversation and workflow logic using the Microsoft Bot Framework V3 SDK. In addition, it also provides API method calls to support management of QBot application used by the [Question](#question-tab) and [Dashboard](#dashboard-tab) tabs.
+
+This API also connects to
+* Azure SQL Server Database using Entity Framework 6.0
+* Graph API
+
+
+#### [Question Tab](#question-tab)
+This is an Angular 6 application deployed to an Azure App Service. Within the QBot solution, it is hosted within a Microsoft Teams tab. It displays a summary of all questions asked by users within the channel (both answered and unanswered).
+
+
+#### [Dashboard Tab](#dashboard-tab)
+This is an Angular 6 application deployed to an Azure App Service. Within the QBot solution, it is hosted within a Microsoft Teams static tab. It faciliates administrative functions used to manage the QBot solution within the team.
+
+#### [QnA Maker Service](#qnamaker)
+The QnA Maker knowledge base drives all answering and learning aspects of the QBot.
+
+#### [SQL Server Database](#sql-server)
+Stores the list of users, roles, tutorial groups, user-tutorial mappings, assessments, questions, attachments and QR code references, and the configuration settings.
+
+#### [Graph API](#graph-api)
+RESTful Http API calls from the Bot to get the replies within a conversation thread.
+Authenticated using service account (username/password) for delegate permissions
+
+
+## [Setup Instructions](#setup)
+Check out the [full instructions](Documentation\setup.md) on how to provision and configure the QBot solution.
+
+## [Data Model](#data)
+The QBot solution uses a SQL Server database to :
+* Store users and their roles
+* Manage courses and Tutorials
+* Manage technical configuration for each course (such as End)
+* Manage the list of unanswered questions and their originating conversations
+
+The schema is:
+
+![datamodel](Documentation\datamodel.png)
+
+
+## [Solution Walkthrough](#code)
+
+The solution deploys a single .NET Web API project, and 2x Angular 6 projects. This section gives an overview on all projects included in the solution source code
+
+
+### Microsoft.Teams.Apps.Qbot
+
+This is a .NET WebAPI project with 2 controllers:
+
+**MessagesController** - Handles interactions and message processing for the Bot itself. Implementation is based on the Microsoft Bot Builder Framework v3.
+
+The main `Post([FromBody]Microsoft.Bot.Connector.Activity activity)` method has the following workflow:
+* Processes each activity from Teams based on the 'Microsoft.Bot.Connector.ActivityTypes' type
+* If type is `ActivityTypes.Message`, the Controller will query QnA Maker for an answer, or tag a tutor/lecturer if it cannot find one. The logic and creation of the response is focused in the `RootDialog.cs` file.
+* If it is an `ActivityTypes.Invoke`, this means the user has selected an answer. The Controller will update the questions list within SQL Server. It will also train QnA Maker by calling `generateAnswer` as well as Patch (to add new Q&A pairs), then re-publishing the knowledge base.
+
+**RequestController** - Handles additional functions to support Qbot administrative functions.
+Main methods:
+
+
+
+|API Method|Controller Method|Description|
+|:-|:-|:-|
+|api/Request/GetTeamGroupIdsWithQuestions|`GetTeamGroupIdsWithQuestions(string tenantId, string upn)`|Gets list of Team IDs for which at least one question has been asked|
+|api/Request/GetTeamGroupDetail|`GetTeamGroupDetail(string groupId)`|Queries Graph API to get details of a Team based on the ID|
+|api/Request/GetUserByUpn|`GetUserByUpn(string upn)`|Retrieves user details including role and tutorial membership|
+
+
+Key functionality includes methods to:
+* Mark question as answered
+* Retrieve and maintain list of courses in the system
+* Retrieve and maintain list of users and their roles in the system
+* Graph API to get the list of Teams
+
+These will be used by the 2x Angular front-end apps - `DashboardTabApp` and `QuestionsTabApp`.
+
+
+### Microsoft.Teams.Apps.QBot.Data
+The Qbot solution uses a SQL Server to store application related data and Entity Framework (EF) as the ORM.
+This project contains the EF entities and some "adapter" helper methods to facilitate database communications.
+A "Database First" approach to generate entities.
+
+
+### Microsoft.Teams.Apps.QBot.Models
+This project contains data models that faciliate messaging between `Microsoft.Teams.Apps.QBot` WebAPI and the
+
+
+### DashboardTabApp
+This is an Angular 6 web application that is deployed as a static teams tab (accessed via bot one-to-one chat. It handles general bot configuration and is intended to be used by course administrators only.
+[Technical details about how this is created]
+
+
+### QuestionsTabApp
+This is an Angular 6 web application deployed as a configurable teams tab (can be added per channel). It displays the consolidated list of answered and unanswered questions posted within the channel, and is intended to be used by both students and tutors.
+[Technical details about how this is created]
diff --git a/Source/DashboardTabApp/.editorconfig b/Source/DashboardTabApp/.editorconfig
new file mode 100644
index 0000000..9b73521
--- /dev/null
+++ b/Source/DashboardTabApp/.editorconfig
@@ -0,0 +1,13 @@
+# Editor configuration, see http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 4
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/Source/DashboardTabApp/.gitignore b/Source/DashboardTabApp/.gitignore
new file mode 100644
index 0000000..6d34722
--- /dev/null
+++ b/Source/DashboardTabApp/.gitignore
@@ -0,0 +1,40 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# compiled output
+/dist
+/tmp
+/out-tsc
+
+# dependencies
+/node_modules
+
+# IDEs and editors
+/.idea
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+/Properties/launchSettings.json
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+
+# misc
+/.sass-cache
+/connect.lock
+/coverage
+/libpeerconnection.log
+npm-debug.log
+yarn-error.log
+testem.log
+/typings
+
+# System Files
+.DS_Store
+Thumbs.db
diff --git a/Source/DashboardTabApp/DashboardTabApp.csproj b/Source/DashboardTabApp/DashboardTabApp.csproj
new file mode 100644
index 0000000..8905656
--- /dev/null
+++ b/Source/DashboardTabApp/DashboardTabApp.csproj
@@ -0,0 +1,57 @@
+
+
+
+ SAK
+ SAK
+ SAK
+ SAK
+ 3.1
+ Debug;Release;Release.CQU
+
+
+
+ netcoreapp2.1
+ true
+ ng build --aot
+ 9758154d-5763-4d11-9572-166c88d6e5b9
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/DashboardTabApp/Program.cs b/Source/DashboardTabApp/Program.cs
new file mode 100644
index 0000000..7305c93
--- /dev/null
+++ b/Source/DashboardTabApp/Program.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+namespace DashboardTabApp
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ }
+ }
+}
diff --git a/Source/DashboardTabApp/README.md b/Source/DashboardTabApp/README.md
new file mode 100644
index 0000000..d468f57
--- /dev/null
+++ b/Source/DashboardTabApp/README.md
@@ -0,0 +1,27 @@
+# DashboardTabApp
+
+This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.0.8.
+
+## Development server
+
+Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
+
+## Code scaffolding
+
+Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
+
+## Build
+
+Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
+
+## Running unit tests
+
+Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
+
+## Running end-to-end tests
+
+Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
+
+## Further help
+
+To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
diff --git a/Source/DashboardTabApp/angular.json b/Source/DashboardTabApp/angular.json
new file mode 100644
index 0000000..db3e7cf
--- /dev/null
+++ b/Source/DashboardTabApp/angular.json
@@ -0,0 +1,141 @@
+{
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
+ "version": 1,
+ "newProjectRoot": "projects",
+ "projects": {
+ "DashboardTabApp": {
+ "root": "",
+ "sourceRoot": "src",
+ "projectType": "application",
+ "prefix": "app",
+ "schematics": {},
+ "architect": {
+ "build": {
+ "builder": "@angular-devkit/build-angular:browser",
+ "options": {
+ "outputPath": "wwwroot",
+ "index": "src/index.html",
+ "main": "src/main.ts",
+ "polyfills": "src/polyfills.ts",
+ "tsConfig": "src/tsconfig.app.json",
+ "assets": [
+ "src/favicon.ico",
+ "src/assets",
+ "src/web.config"
+ ],
+ "styles": [
+ "node_modules/bootstrap/dist/css/bootstrap.min.css",
+ "src/styles.css"
+ ],
+ "scripts": [
+ "node_modules/jquery/dist/jquery.min.js",
+ "node_modules/bootstrap/dist/js/bootstrap.min.js"
+ ]
+ },
+ "configurations": {
+ "production": {
+ "fileReplacements": [
+ {
+ "replace": "src/environments/environment.ts",
+ "with": "src/environments/environment.prod.ts"
+ }
+ ],
+ "optimization": true,
+ "outputHashing": "all",
+ "sourceMap": false,
+ "extractCss": true,
+ "namedChunks": false,
+ "aot": true,
+ "extractLicenses": true,
+ "vendorChunk": false,
+ "buildOptimizer": true
+ }
+ }
+ },
+ "serve": {
+ "builder": "@angular-devkit/build-angular:dev-server",
+ "options": {
+ "browserTarget": "DashboardTabApp:build"
+ },
+ "configurations": {
+ "production": {
+ "browserTarget": "DashboardTabApp:build:production"
+ }
+ }
+ },
+ "extract-i18n": {
+ "builder": "@angular-devkit/build-angular:extract-i18n",
+ "options": {
+ "browserTarget": "DashboardTabApp:build"
+ }
+ },
+ "test": {
+ "builder": "@angular-devkit/build-angular:karma",
+ "options": {
+ "main": "src/test.ts",
+ "polyfills": "src/polyfills.ts",
+ "tsConfig": "src/tsconfig.spec.json",
+ "karmaConfig": "src/karma.conf.js",
+ "styles": [
+ "node_modules/bootstrap/dist/css/bootstrap.min.css",
+ "src/styles.css"
+ ],
+ "scripts": [
+ "node_modules/jquery/dist/jquery.min.js",
+ "node_modules/bootstrap/dist/js/bootstrap.min.js"
+ ],
+ "assets": [
+ "src/favicon.ico",
+ "src/assets"
+ ]
+ }
+ },
+ "lint": {
+ "builder": "@angular-devkit/build-angular:tslint",
+ "options": {
+ "tsConfig": [
+ "src/tsconfig.app.json",
+ "src/tsconfig.spec.json"
+ ],
+ "exclude": [
+ "**/node_modules/**"
+ ]
+ }
+ }
+ }
+ },
+ "DashboardTabApp-e2e": {
+ "root": "e2e/",
+ "projectType": "application",
+ "architect": {
+ "e2e": {
+ "builder": "@angular-devkit/build-angular:protractor",
+ "options": {
+ "protractorConfig": "e2e/protractor.conf.js",
+ "devServerTarget": "DashboardTabApp:serve"
+ },
+ "configurations": {
+ "production": {
+ "devServerTarget": "DashboardTabApp:serve:production"
+ }
+ }
+ },
+ "lint": {
+ "builder": "@angular-devkit/build-angular:tslint",
+ "options": {
+ "tsConfig": "e2e/tsconfig.e2e.json",
+ "exclude": [
+ "**/node_modules/**"
+ ]
+ }
+ }
+ }
+ }
+ },
+ "defaultProject": "DashboardTabApp",
+ "schematics": {
+ "@schematics/angular:component": {
+ "styleext": "scss"
+ }
+ }
+}
diff --git a/Source/DashboardTabApp/appsettings.Development.json b/Source/DashboardTabApp/appsettings.Development.json
new file mode 100644
index 0000000..e203e94
--- /dev/null
+++ b/Source/DashboardTabApp/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Debug",
+ "System": "Information",
+ "Microsoft": "Information"
+ }
+ }
+}
diff --git a/Source/DashboardTabApp/appsettings.json b/Source/DashboardTabApp/appsettings.json
new file mode 100644
index 0000000..def9159
--- /dev/null
+++ b/Source/DashboardTabApp/appsettings.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/Source/DashboardTabApp/package-lock.json b/Source/DashboardTabApp/package-lock.json
new file mode 100644
index 0000000..6fa4770
--- /dev/null
+++ b/Source/DashboardTabApp/package-lock.json
@@ -0,0 +1,16444 @@
+{
+ "name": "dashboard-tab-app",
+ "version": "0.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@angular-devkit/architect": {
+ "version": "0.803.4",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.803.4.tgz",
+ "integrity": "sha512-Ek+xb9GfzHLbD+ATmupbzTSNFGddkH6dbb36cB6gme+vnlBVfXP0dxOg5lRKZoUIFJyREl9jSrA5zUhVwXaoVg==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "8.3.4",
+ "rxjs": "6.4.0"
+ },
+ "dependencies": {
+ "rxjs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
+ "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ }
+ }
+ },
+ "@angular-devkit/build-angular": {
+ "version": "0.803.4",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.803.4.tgz",
+ "integrity": "sha512-tL0MdAPtUjqG+F6Hc0xhaKb2gk8g55AeBjSZognlJkqPRS+b+gF1qDmyW0n5HXbyDk+zIGZyvYpzkBBL8VI6bg==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/architect": "0.803.4",
+ "@angular-devkit/build-optimizer": "0.803.4",
+ "@angular-devkit/build-webpack": "0.803.4",
+ "@angular-devkit/core": "8.3.4",
+ "@babel/core": "7.5.5",
+ "@babel/preset-env": "7.5.5",
+ "@ngtools/webpack": "8.3.4",
+ "ajv": "6.10.2",
+ "autoprefixer": "9.6.1",
+ "browserslist": "4.6.6",
+ "cacache": "12.0.2",
+ "caniuse-lite": "1.0.30000989",
+ "circular-dependency-plugin": "5.2.0",
+ "clean-css": "4.2.1",
+ "copy-webpack-plugin": "5.0.4",
+ "core-js": "3.2.1",
+ "file-loader": "4.2.0",
+ "find-cache-dir": "3.0.0",
+ "glob": "7.1.4",
+ "istanbul-instrumenter-loader": "3.0.1",
+ "karma-source-map-support": "1.4.0",
+ "less": "3.9.0",
+ "less-loader": "5.0.0",
+ "license-webpack-plugin": "2.1.2",
+ "loader-utils": "1.2.3",
+ "mini-css-extract-plugin": "0.8.0",
+ "minimatch": "3.0.4",
+ "open": "6.4.0",
+ "parse5": "4.0.0",
+ "postcss": "7.0.17",
+ "postcss-import": "12.0.1",
+ "postcss-loader": "3.0.0",
+ "raw-loader": "3.1.0",
+ "regenerator-runtime": "0.13.3",
+ "rxjs": "6.4.0",
+ "sass": "1.22.9",
+ "sass-loader": "7.2.0",
+ "semver": "6.3.0",
+ "source-map": "0.7.3",
+ "source-map-loader": "0.2.4",
+ "source-map-support": "0.5.13",
+ "speed-measure-webpack-plugin": "1.3.1",
+ "style-loader": "1.0.0",
+ "stylus": "0.54.5",
+ "stylus-loader": "3.0.2",
+ "terser": "4.1.4",
+ "terser-webpack-plugin": "1.4.1",
+ "tree-kill": "1.2.1",
+ "webpack": "4.39.2",
+ "webpack-dev-middleware": "3.7.0",
+ "webpack-dev-server": "3.8.0",
+ "webpack-merge": "4.2.1",
+ "webpack-sources": "1.4.3",
+ "webpack-subresource-integrity": "1.1.0-rc.6",
+ "worker-farm": "1.7.0",
+ "worker-plugin": "3.2.0"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "rxjs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
+ "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true
+ }
+ }
+ },
+ "@angular-devkit/build-optimizer": {
+ "version": "0.803.4",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.803.4.tgz",
+ "integrity": "sha512-VGkHCyU/OC0BoTeoERb0cFG00Ippjhtx2du+7JgwGNU1GF+g2H6Ka1NJRQf/TrwgH5ATmagvlTKQRDOMo51jqg==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "1.2.3",
+ "source-map": "0.7.3",
+ "tslib": "1.10.0",
+ "typescript": "3.5.3",
+ "webpack-sources": "1.4.3"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true
+ },
+ "tslib": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
+ "dev": true
+ },
+ "typescript": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz",
+ "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==",
+ "dev": true
+ }
+ }
+ },
+ "@angular-devkit/build-webpack": {
+ "version": "0.803.4",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.803.4.tgz",
+ "integrity": "sha512-IbXoKyhdfaza+K8orCwDx3r7C/8qaTwiXUlarW/adoH5XBwzAtYGGsMmmWRffBnBiZtI2LT3VK21QAostklNxg==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/architect": "0.803.4",
+ "@angular-devkit/core": "8.3.4",
+ "rxjs": "6.4.0",
+ "webpack-merge": "4.2.1"
+ },
+ "dependencies": {
+ "rxjs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
+ "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ }
+ }
+ },
+ "@angular-devkit/core": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.4.tgz",
+ "integrity": "sha512-QjUN9EakpQ+sFYeMfBMecxVhgI4Vdg0k20h6PZDjZ9lqYNXjpaQVtBo7qiPYHh5kQeJEvdrzca6yeYuCP3TvZw==",
+ "dev": true,
+ "requires": {
+ "ajv": "6.10.2",
+ "fast-json-stable-stringify": "2.0.0",
+ "magic-string": "0.25.3",
+ "rxjs": "6.4.0",
+ "source-map": "0.7.3"
+ },
+ "dependencies": {
+ "rxjs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
+ "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true
+ }
+ }
+ },
+ "@angular-devkit/schematics": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.3.4.tgz",
+ "integrity": "sha512-+QXhrAEcReQJL4fn+35NbcdW5d1vawqSZUokqga8E971YUVUk55mHpIQ39Vpj3S9jhTRYwxsHl+7v9N7UaREmg==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "8.3.4",
+ "rxjs": "6.4.0"
+ },
+ "dependencies": {
+ "@angular-devkit/core": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.4.tgz",
+ "integrity": "sha512-QjUN9EakpQ+sFYeMfBMecxVhgI4Vdg0k20h6PZDjZ9lqYNXjpaQVtBo7qiPYHh5kQeJEvdrzca6yeYuCP3TvZw==",
+ "dev": true,
+ "requires": {
+ "ajv": "6.10.2",
+ "fast-json-stable-stringify": "2.0.0",
+ "magic-string": "0.25.3",
+ "rxjs": "6.4.0",
+ "source-map": "0.7.3"
+ }
+ },
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "rxjs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
+ "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ }
+ }
+ },
+ "@angular/animations": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-8.2.6.tgz",
+ "integrity": "sha512-beakpSjzF+bP2jCDmeGHwSim04u9x1Uf3dCFAj1CqRwJGb8POpUA1KlnGrEm2pzWzHKVqQH6VQ+8uGPLl17PFA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/cdk": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-8.2.0.tgz",
+ "integrity": "sha512-vsjKiUirICP9fTxnBT3jjqW14ipZLJPkyT3dKZQETKcml1fTY1L9QVXclvLTeUliuPSl490anuBvpQpfMeJDhQ==",
+ "requires": {
+ "parse5": "^5.0.0",
+ "tslib": "^1.7.1"
+ },
+ "dependencies": {
+ "parse5": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz",
+ "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
+ "optional": true
+ }
+ }
+ },
+ "@angular/cli": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.3.4.tgz",
+ "integrity": "sha512-5Jp7a1/Yepm2JkrMHY2Q7nO1FxlNvGp1Zc3m9dp4ydH08qO6/Z8WO0HF+/BxAsHZzB+XV91E1ZzbLR0RdsM8ag==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/architect": "0.803.4",
+ "@angular-devkit/core": "8.3.4",
+ "@angular-devkit/schematics": "8.3.4",
+ "@schematics/angular": "8.3.4",
+ "@schematics/update": "0.803.4",
+ "@yarnpkg/lockfile": "1.1.0",
+ "ansi-colors": "4.1.1",
+ "debug": "^4.1.1",
+ "ini": "1.3.5",
+ "inquirer": "6.5.1",
+ "npm-package-arg": "6.1.0",
+ "open": "6.4.0",
+ "pacote": "9.5.5",
+ "read-package-tree": "5.3.1",
+ "semver": "6.3.0",
+ "symbol-observable": "1.2.0",
+ "universal-analytics": "^0.4.20",
+ "uuid": "^3.3.2"
+ },
+ "dependencies": {
+ "@angular-devkit/architect": {
+ "version": "0.803.4",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.803.4.tgz",
+ "integrity": "sha512-Ek+xb9GfzHLbD+ATmupbzTSNFGddkH6dbb36cB6gme+vnlBVfXP0dxOg5lRKZoUIFJyREl9jSrA5zUhVwXaoVg==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "8.3.4",
+ "rxjs": "6.4.0"
+ }
+ },
+ "@angular-devkit/core": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.4.tgz",
+ "integrity": "sha512-QjUN9EakpQ+sFYeMfBMecxVhgI4Vdg0k20h6PZDjZ9lqYNXjpaQVtBo7qiPYHh5kQeJEvdrzca6yeYuCP3TvZw==",
+ "dev": true,
+ "requires": {
+ "ajv": "6.10.2",
+ "fast-json-stable-stringify": "2.0.0",
+ "magic-string": "0.25.3",
+ "rxjs": "6.4.0",
+ "source-map": "0.7.3"
+ }
+ },
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "rxjs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
+ "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ }
+ }
+ },
+ "@angular/common": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/common/-/common-8.2.6.tgz",
+ "integrity": "sha512-OlU3LCPShHJEsOHS+qczY52P0kWtjJD8N7NDHaGMB6Xp8GMgItjQIeeO6yf8DJyaCIC4qk4G7jPdnQk6IE1SbQ==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/compiler": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.2.6.tgz",
+ "integrity": "sha512-NdTY2n0XNRmKixbKDWB++9tEDLFwN0/Bp/1lXJ4qF/8V5Wju6IJ/UZZKjR5C4uiKtF17T3GzubhXgghumt5UVA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/compiler-cli": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-8.2.6.tgz",
+ "integrity": "sha512-WLlBO/oGcQBKE8rYcENZQ4HgkbrmMqSNJXHLK/HnZpvbot2+mPiDXykI/p5rKdpAei/lgTU8g8GskoiDeLXsgw==",
+ "dev": true,
+ "requires": {
+ "canonical-path": "1.0.0",
+ "chokidar": "^2.1.1",
+ "convert-source-map": "^1.5.1",
+ "dependency-graph": "^0.7.2",
+ "magic-string": "^0.25.0",
+ "minimist": "^1.2.0",
+ "reflect-metadata": "^0.1.2",
+ "source-map": "^0.6.1",
+ "tslib": "^1.9.0",
+ "yargs": "13.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "dev": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "cliui": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ },
+ "dependencies": {
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ }
+ }
+ },
+ "emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "fsevents": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
+ "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "nan": "^2.12.1",
+ "node-pre-gyp": "^0.12.0"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chownr": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "fs-minipass": {
+ "version": "1.2.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true,
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "dev": true
+ },
+ "minipass": {
+ "version": "2.3.5",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.2.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "needle": {
+ "version": "2.3.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.12.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "npm-packlist": {
+ "version": "1.4.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "bundled": true,
+ "dev": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "semver": {
+ "version": "5.7.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "4.4.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.3.4",
+ "minizlib": "^1.1.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.2"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "bundled": true,
+ "dev": true
+ }
+ }
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true
+ },
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "dev": true,
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
+ "dev": true,
+ "optional": true
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
+ "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ },
+ "upath": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
+ "dev": true
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "13.1.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.1.0.tgz",
+ "integrity": "sha512-1UhJbXfzHiPqkfXNHYhiz79qM/kZqjTE8yGlEjZa85Q+3+OwcV6NRkV7XOV1W2Eom2bzILeUn55pQYffjVOLAg==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^2.0.1",
+ "os-locale": "^3.1.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^13.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "13.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
+ "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
+ "@angular/core": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/core/-/core-8.2.6.tgz",
+ "integrity": "sha512-l+BrvPGwtPUh/rQyB9mjtonMsFEAoRHgDYWeQu/QukIZbItNdFqrhewn2zQ8Skx75BpwFLAVIVXp9ioDyvP2eQ==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/forms": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-8.2.6.tgz",
+ "integrity": "sha512-sYUspJYJGq0OaBuxgdUXPf0TwYyED9OVWNCl9jDJCW//2NAbrZG8BSujvV54Dtg2emY1Uc7EFyQ8Wc8yxS7KSg==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/http": {
+ "version": "7.2.15",
+ "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.2.15.tgz",
+ "integrity": "sha512-TR7PEdmLWNIre3Zn8lvyb4lSrvPUJhKLystLnp4hBMcWsJqq5iK8S3bnlR4viZ9HMlf7bW7+Hm4SI6aB3tdUtw==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/language-service": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-8.2.6.tgz",
+ "integrity": "sha512-43h8WFJsk0wK5v1AaTjvDppb0y1ReKEuOkvlcBffb+IIYM8pwuiIvMYGnjstV1jvOd80HPO5wQ8gXhutY52fpQ==",
+ "dev": true
+ },
+ "@angular/material": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/@angular/material/-/material-8.2.0.tgz",
+ "integrity": "sha512-4EY3QilEXS09+10WYwkunEltReuPDByb2ulWw2FLG3wpmMpCp4p6AKY9v9xS3sGvb708S0b9vlfLG4FbepmBbA==",
+ "requires": {
+ "tslib": "^1.7.1"
+ }
+ },
+ "@angular/platform-browser": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.2.6.tgz",
+ "integrity": "sha512-wUgcdTXItforNA+6qykPL9SDmV1uSIUQcEZrm3YCoVt7CuwMav3dq9Lg1zZ7HKv0A8It0fAKpXBkamzpRxvZEw==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/platform-browser-dynamic": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-8.2.6.tgz",
+ "integrity": "sha512-4azHzNBYYeyzIsktN2P+d0stCisOvYfxU7U0oD+FaGalxg2Ch1mGjnZA+5UcmbMZOOXo4TMcKmzpB6VcLGe+Hw==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@angular/router": {
+ "version": "8.2.6",
+ "resolved": "https://registry.npmjs.org/@angular/router/-/router-8.2.6.tgz",
+ "integrity": "sha512-XAqhrPbU+z/ztf2b0VxFytHPJRpWfhnhCJ2qf9Tie1Cov6zOlgIKInOSF+WtsFEUZAnwSbAfGk4KSXrwBWw8zA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@azure/msal-angular": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/@azure/msal-angular/-/msal-angular-0.1.4.tgz",
+ "integrity": "sha512-VLSmFWH+9LUTMxxK2sBSLYBzfezm5p3ae+XE/o2hEtp4jKBCLrm7NzprthswweYrDbIDYooBl1GJRFbTKY1LiA==",
+ "requires": {
+ "msal": "0.2.2",
+ "tslib": "1.7.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.7.1.tgz",
+ "integrity": "sha1-vIAEFkaRkjp5/oN4u+s9ogF1OOw="
+ }
+ }
+ },
+ "@babel/code-frame": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
+ "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.0.0"
+ }
+ },
+ "@babel/core": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz",
+ "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.5.5",
+ "@babel/generator": "^7.5.5",
+ "@babel/helpers": "^7.5.5",
+ "@babel/parser": "^7.5.5",
+ "@babel/template": "^7.4.4",
+ "@babel/traverse": "^7.5.5",
+ "@babel/types": "^7.5.5",
+ "convert-source-map": "^1.1.0",
+ "debug": "^4.1.0",
+ "json5": "^2.1.0",
+ "lodash": "^4.17.13",
+ "resolve": "^1.3.2",
+ "semver": "^5.4.1",
+ "source-map": "^0.5.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "json5": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz",
+ "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/generator": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.0.tgz",
+ "integrity": "sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.6.0",
+ "jsesc": "^2.5.1",
+ "lodash": "^4.17.13",
+ "source-map": "^0.5.0",
+ "trim-right": "^1.0.1"
+ }
+ },
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz",
+ "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz",
+ "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-explode-assignable-expression": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-call-delegate": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz",
+ "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-hoist-variables": "^7.4.4",
+ "@babel/traverse": "^7.4.4",
+ "@babel/types": "^7.4.4"
+ }
+ },
+ "@babel/helper-define-map": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz",
+ "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/types": "^7.5.5",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/helper-explode-assignable-expression": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz",
+ "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==",
+ "dev": true,
+ "requires": {
+ "@babel/traverse": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
+ "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-get-function-arity": "^7.0.0",
+ "@babel/template": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-get-function-arity": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz",
+ "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz",
+ "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.4.4"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz",
+ "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.5.5"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz",
+ "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz",
+ "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/helper-simple-access": "^7.1.0",
+ "@babel/helper-split-export-declaration": "^7.4.4",
+ "@babel/template": "^7.4.4",
+ "@babel/types": "^7.5.5",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz",
+ "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz",
+ "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==",
+ "dev": true
+ },
+ "@babel/helper-regex": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz",
+ "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/helper-remap-async-to-generator": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz",
+ "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.0.0",
+ "@babel/helper-wrap-function": "^7.1.0",
+ "@babel/template": "^7.1.0",
+ "@babel/traverse": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz",
+ "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-member-expression-to-functions": "^7.5.5",
+ "@babel/helper-optimise-call-expression": "^7.0.0",
+ "@babel/traverse": "^7.5.5",
+ "@babel/types": "^7.5.5"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz",
+ "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz",
+ "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.4.4"
+ }
+ },
+ "@babel/helper-wrap-function": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz",
+ "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/template": "^7.1.0",
+ "@babel/traverse": "^7.1.0",
+ "@babel/types": "^7.2.0"
+ }
+ },
+ "@babel/helpers": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.6.0.tgz",
+ "integrity": "sha512-W9kao7OBleOjfXtFGgArGRX6eCP0UEcA2ZWEWNkJdRZnHhW4eEbeswbG3EwaRsnQUAEGWYgMq1HsIXuNNNy2eQ==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.6.0",
+ "@babel/traverse": "^7.6.0",
+ "@babel/types": "^7.6.0"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz",
+ "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.0",
+ "esutils": "^2.0.2",
+ "js-tokens": "^4.0.0"
+ }
+ },
+ "@babel/parser": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.0.tgz",
+ "integrity": "sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ==",
+ "dev": true
+ },
+ "@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz",
+ "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-remap-async-to-generator": "^7.1.0",
+ "@babel/plugin-syntax-async-generators": "^7.2.0"
+ }
+ },
+ "@babel/plugin-proposal-dynamic-import": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz",
+ "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-dynamic-import": "^7.2.0"
+ }
+ },
+ "@babel/plugin-proposal-json-strings": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz",
+ "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-json-strings": "^7.2.0"
+ }
+ },
+ "@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz",
+ "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-object-rest-spread": "^7.2.0"
+ }
+ },
+ "@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz",
+ "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.2.0"
+ }
+ },
+ "@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz",
+ "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-regex": "^7.4.4",
+ "regexpu-core": "^4.5.4"
+ }
+ },
+ "@babel/plugin-syntax-async-generators": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz",
+ "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-syntax-dynamic-import": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz",
+ "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-syntax-json-strings": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz",
+ "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz",
+ "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz",
+ "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-arrow-functions": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz",
+ "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-async-to-generator": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz",
+ "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-remap-async-to-generator": "^7.1.0"
+ }
+ },
+ "@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz",
+ "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-block-scoping": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.0.tgz",
+ "integrity": "sha512-tIt4E23+kw6TgL/edACZwP1OUKrjOTyMrFMLoT5IOFrfMRabCgekjqFd5o6PaAMildBu46oFkekIdMuGkkPEpA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "lodash": "^4.17.13"
+ }
+ },
+ "@babel/plugin-transform-classes": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz",
+ "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.0.0",
+ "@babel/helper-define-map": "^7.5.5",
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/helper-optimise-call-expression": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-replace-supers": "^7.5.5",
+ "@babel/helper-split-export-declaration": "^7.4.4",
+ "globals": "^11.1.0"
+ }
+ },
+ "@babel/plugin-transform-computed-properties": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz",
+ "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-destructuring": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz",
+ "integrity": "sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-dotall-regex": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz",
+ "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-regex": "^7.4.4",
+ "regexpu-core": "^4.5.4"
+ }
+ },
+ "@babel/plugin-transform-duplicate-keys": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz",
+ "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz",
+ "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-for-of": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz",
+ "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-function-name": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz",
+ "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-literals": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz",
+ "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-member-expression-literals": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz",
+ "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-modules-amd": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz",
+ "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.1.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "babel-plugin-dynamic-import-node": "^2.3.0"
+ }
+ },
+ "@babel/plugin-transform-modules-commonjs": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.6.0.tgz",
+ "integrity": "sha512-Ma93Ix95PNSEngqomy5LSBMAQvYKVe3dy+JlVJSHEXZR5ASL9lQBedMiCyVtmTLraIDVRE3ZjTZvmXXD2Ozw3g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.4.4",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-simple-access": "^7.1.0",
+ "babel-plugin-dynamic-import-node": "^2.3.0"
+ }
+ },
+ "@babel/plugin-transform-modules-systemjs": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.5.0.tgz",
+ "integrity": "sha512-Q2m56tyoQWmuNGxEtUyeEkm6qJYFqs4c+XyXH5RAuYxObRNz9Zgj/1g2GMnjYp2EUyEy7YTrxliGCXzecl/vJg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-hoist-variables": "^7.4.4",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "babel-plugin-dynamic-import-node": "^2.3.0"
+ }
+ },
+ "@babel/plugin-transform-modules-umd": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz",
+ "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.1.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.6.0.tgz",
+ "integrity": "sha512-jem7uytlmrRl3iCAuQyw8BpB4c4LWvSpvIeXKpMb+7j84lkx4m4mYr5ErAcmN5KM7B6BqrAvRGjBIbbzqCczew==",
+ "dev": true,
+ "requires": {
+ "regexp-tree": "^0.1.13"
+ }
+ },
+ "@babel/plugin-transform-new-target": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz",
+ "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-object-super": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz",
+ "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-replace-supers": "^7.5.5"
+ }
+ },
+ "@babel/plugin-transform-parameters": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz",
+ "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-call-delegate": "^7.4.4",
+ "@babel/helper-get-function-arity": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-property-literals": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz",
+ "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-regenerator": {
+ "version": "7.4.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz",
+ "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==",
+ "dev": true,
+ "requires": {
+ "regenerator-transform": "^0.14.0"
+ }
+ },
+ "@babel/plugin-transform-reserved-words": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz",
+ "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-shorthand-properties": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz",
+ "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-spread": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz",
+ "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-sticky-regex": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz",
+ "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-regex": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-template-literals": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz",
+ "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-typeof-symbol": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz",
+ "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0"
+ }
+ },
+ "@babel/plugin-transform-unicode-regex": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz",
+ "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/helper-regex": "^7.4.4",
+ "regexpu-core": "^4.5.4"
+ }
+ },
+ "@babel/preset-env": {
+ "version": "7.5.5",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.5.5.tgz",
+ "integrity": "sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-proposal-async-generator-functions": "^7.2.0",
+ "@babel/plugin-proposal-dynamic-import": "^7.5.0",
+ "@babel/plugin-proposal-json-strings": "^7.2.0",
+ "@babel/plugin-proposal-object-rest-spread": "^7.5.5",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.2.0",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+ "@babel/plugin-syntax-async-generators": "^7.2.0",
+ "@babel/plugin-syntax-dynamic-import": "^7.2.0",
+ "@babel/plugin-syntax-json-strings": "^7.2.0",
+ "@babel/plugin-syntax-object-rest-spread": "^7.2.0",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.2.0",
+ "@babel/plugin-transform-arrow-functions": "^7.2.0",
+ "@babel/plugin-transform-async-to-generator": "^7.5.0",
+ "@babel/plugin-transform-block-scoped-functions": "^7.2.0",
+ "@babel/plugin-transform-block-scoping": "^7.5.5",
+ "@babel/plugin-transform-classes": "^7.5.5",
+ "@babel/plugin-transform-computed-properties": "^7.2.0",
+ "@babel/plugin-transform-destructuring": "^7.5.0",
+ "@babel/plugin-transform-dotall-regex": "^7.4.4",
+ "@babel/plugin-transform-duplicate-keys": "^7.5.0",
+ "@babel/plugin-transform-exponentiation-operator": "^7.2.0",
+ "@babel/plugin-transform-for-of": "^7.4.4",
+ "@babel/plugin-transform-function-name": "^7.4.4",
+ "@babel/plugin-transform-literals": "^7.2.0",
+ "@babel/plugin-transform-member-expression-literals": "^7.2.0",
+ "@babel/plugin-transform-modules-amd": "^7.5.0",
+ "@babel/plugin-transform-modules-commonjs": "^7.5.0",
+ "@babel/plugin-transform-modules-systemjs": "^7.5.0",
+ "@babel/plugin-transform-modules-umd": "^7.2.0",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5",
+ "@babel/plugin-transform-new-target": "^7.4.4",
+ "@babel/plugin-transform-object-super": "^7.5.5",
+ "@babel/plugin-transform-parameters": "^7.4.4",
+ "@babel/plugin-transform-property-literals": "^7.2.0",
+ "@babel/plugin-transform-regenerator": "^7.4.5",
+ "@babel/plugin-transform-reserved-words": "^7.2.0",
+ "@babel/plugin-transform-shorthand-properties": "^7.2.0",
+ "@babel/plugin-transform-spread": "^7.2.0",
+ "@babel/plugin-transform-sticky-regex": "^7.2.0",
+ "@babel/plugin-transform-template-literals": "^7.4.4",
+ "@babel/plugin-transform-typeof-symbol": "^7.2.0",
+ "@babel/plugin-transform-unicode-regex": "^7.4.4",
+ "@babel/types": "^7.5.5",
+ "browserslist": "^4.6.0",
+ "core-js-compat": "^3.1.1",
+ "invariant": "^2.2.2",
+ "js-levenshtein": "^1.1.3",
+ "semver": "^5.5.0"
+ }
+ },
+ "@babel/template": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.6.0.tgz",
+ "integrity": "sha512-5AEH2EXD8euCk446b7edmgFdub/qfH1SN6Nii3+fyXP807QRx9Q73A2N5hNwRRslC2H9sNzaFhsPubkS4L8oNQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "@babel/parser": "^7.6.0",
+ "@babel/types": "^7.6.0"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.6.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.0.tgz",
+ "integrity": "sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.5.5",
+ "@babel/generator": "^7.6.0",
+ "@babel/helper-function-name": "^7.1.0",
+ "@babel/helper-split-export-declaration": "^7.4.4",
+ "@babel/parser": "^7.6.0",
+ "@babel/types": "^7.6.0",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0",
+ "lodash": "^4.17.13"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/types": {
+ "version": "7.6.1",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz",
+ "integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2",
+ "lodash": "^4.17.13",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@fortawesome/angular-fontawesome": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-0.5.0.tgz",
+ "integrity": "sha512-5IR/jNMddiEpgApcqSMfp7l5kZqOtxQYzkSLW6iZ4MZHbQQ+Kc9tu9qi2hro6VFSk/sPxeYEzkzGZUNrMYiwOg==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@fortawesome/fontawesome-common-types": {
+ "version": "0.2.24",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.24.tgz",
+ "integrity": "sha512-IPBT/1LdUVQpHcqdrh8uI2/86Fbu7933hkA/HweiCmP5QgF/8PecFM00gYvykxf0RZud8bg8zu+YfggDFUc1Kw=="
+ },
+ "@fortawesome/fontawesome-svg-core": {
+ "version": "1.2.24",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.24.tgz",
+ "integrity": "sha512-9uVGOEZwviZKbkOVX8nn8cErVqOHBAd1Fqd2OH7Iwu0vxGWdb3fFOMhaAyMXUHZpq1u5C9/HClCV49ci4WmJAg==",
+ "requires": {
+ "@fortawesome/fontawesome-common-types": "^0.2.24"
+ }
+ },
+ "@fortawesome/free-solid-svg-icons": {
+ "version": "5.11.1",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.11.1.tgz",
+ "integrity": "sha512-bB3hXON1K6mVOetTTg5VXZ4CAHg866p7MqenDkJ/eVcbWbGQRE45ojHEwkf37tWx3E8z6lcEameRwU9r5tGwjg==",
+ "requires": {
+ "@fortawesome/fontawesome-common-types": "^0.2.24"
+ }
+ },
+ "@microsoft/teams-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/@microsoft/teams-js/-/teams-js-1.5.1.tgz",
+ "integrity": "sha512-YRIB2JC4FSh2zg3kBpQaAQ7luxnhRP+Vw9QHj0lIztSyWp6Wt37/mpyqicT6fKHyXnbYRULbsjwSGcVenGQyHA=="
+ },
+ "@ngtools/webpack": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.3.4.tgz",
+ "integrity": "sha512-hNikQ6cjvCmA/bK8dor+oijPKF9sQAcM29FCPn3t0l3ucoVSOvbFpvtMYqlIHN5pw6WitZpImnkk2OW3o1JaDA==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "8.3.4",
+ "enhanced-resolve": "4.1.0",
+ "rxjs": "6.4.0",
+ "tree-kill": "1.2.1",
+ "webpack-sources": "1.4.3"
+ },
+ "dependencies": {
+ "rxjs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
+ "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ }
+ }
+ },
+ "@schematics/angular": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.4.tgz",
+ "integrity": "sha512-/HO6vZosULsJnwZLG9JLePyaR2g4MePrk27c3H/WbFNN4ajBePe1Mj34q6HCzje30NduLV8B3SykPnG1CoNy5Q==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "8.3.4",
+ "@angular-devkit/schematics": "8.3.4"
+ },
+ "dependencies": {
+ "@angular-devkit/core": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.4.tgz",
+ "integrity": "sha512-QjUN9EakpQ+sFYeMfBMecxVhgI4Vdg0k20h6PZDjZ9lqYNXjpaQVtBo7qiPYHh5kQeJEvdrzca6yeYuCP3TvZw==",
+ "dev": true,
+ "requires": {
+ "ajv": "6.10.2",
+ "fast-json-stable-stringify": "2.0.0",
+ "magic-string": "0.25.3",
+ "rxjs": "6.4.0",
+ "source-map": "0.7.3"
+ }
+ },
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "rxjs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
+ "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ }
+ }
+ },
+ "@schematics/update": {
+ "version": "0.803.4",
+ "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.803.4.tgz",
+ "integrity": "sha512-ZLCUR7VpUkv3zjeOmcny3UAtwHbQLeBeDsoLYIVQZyepqk3kRPBGaW/xYwmNng04bVfMCtcTx9yrs7n4+Lt/Iw==",
+ "dev": true,
+ "requires": {
+ "@angular-devkit/core": "8.3.4",
+ "@angular-devkit/schematics": "8.3.4",
+ "@yarnpkg/lockfile": "1.1.0",
+ "ini": "1.3.5",
+ "pacote": "9.5.5",
+ "rxjs": "6.4.0",
+ "semver": "6.3.0",
+ "semver-intersect": "1.4.0"
+ },
+ "dependencies": {
+ "@angular-devkit/core": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.4.tgz",
+ "integrity": "sha512-QjUN9EakpQ+sFYeMfBMecxVhgI4Vdg0k20h6PZDjZ9lqYNXjpaQVtBo7qiPYHh5kQeJEvdrzca6yeYuCP3TvZw==",
+ "dev": true,
+ "requires": {
+ "ajv": "6.10.2",
+ "fast-json-stable-stringify": "2.0.0",
+ "magic-string": "0.25.3",
+ "rxjs": "6.4.0",
+ "source-map": "0.7.3"
+ }
+ },
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "rxjs": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz",
+ "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
+ "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ }
+ }
+ },
+ "@types/adal": {
+ "version": "1.0.29",
+ "resolved": "https://registry.npmjs.org/@types/adal/-/adal-1.0.29.tgz",
+ "integrity": "sha512-6kvyTWzue5lJ8xECAgVdMrs5+UEyPeflzU/L83QdufGnvjdyCiCWVgkfinMB7133ik/x+02T0q1070Z6/ZK6eQ==",
+ "dev": true,
+ "requires": {
+ "@types/angular": "*"
+ }
+ },
+ "@types/angular": {
+ "version": "1.6.56",
+ "resolved": "https://registry.npmjs.org/@types/angular/-/angular-1.6.56.tgz",
+ "integrity": "sha512-HxtqilvklZ7i6XOaiP7uIJIrFXEVEhfbSY45nfv2DeBRngncI58Y4ZOUMiUkcT8sqgLL1ablmbfylChUg7A3GA==",
+ "dev": true
+ },
+ "@types/events": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
+ "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==",
+ "dev": true
+ },
+ "@types/glob": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz",
+ "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==",
+ "dev": true,
+ "requires": {
+ "@types/events": "*",
+ "@types/minimatch": "*",
+ "@types/node": "*"
+ }
+ },
+ "@types/jasmine": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.4.0.tgz",
+ "integrity": "sha512-6pUnBg6DuSB55xnxJ5+gW9JOkFrPsXkYAuqqEE8oyrpgDiPQ+TZ+1Zt4S+CHcRJcxyNYXeIXG4vHSzdF6y9Uvw==",
+ "dev": true
+ },
+ "@types/jasminewd2": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.6.tgz",
+ "integrity": "sha512-2ZOKrxb8bKRmP/po5ObYnRDgFE4i+lQiEB27bAMmtMWLgJSqlIDqlLx6S0IRorpOmOPRQ6O80NujTmQAtBkeNw==",
+ "dev": true,
+ "requires": {
+ "@types/jasmine": "*"
+ }
+ },
+ "@types/lodash": {
+ "version": "4.14.138",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.138.tgz",
+ "integrity": "sha512-A4uJgHz4hakwNBdHNPdxOTkYmXNgmUAKLbXZ7PKGslgeV0Mb8P3BlbYfPovExek1qnod4pDfRbxuzcVs3dlFLg=="
+ },
+ "@types/lodash.memoize": {
+ "version": "4.1.6",
+ "resolved": "https://registry.npmjs.org/@types/lodash.memoize/-/lodash.memoize-4.1.6.tgz",
+ "integrity": "sha512-mYxjKiKzRadRJVClLKxS4wb3Iy9kzwJ1CkbyKiadVxejnswnRByyofmPMscFKscmYpl36BEEhCMPuWhA1R/1ZQ==",
+ "requires": {
+ "@types/lodash": "*"
+ }
+ },
+ "@types/minimatch": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
+ "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "12.7.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz",
+ "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==",
+ "dev": true
+ },
+ "@types/q": {
+ "version": "0.0.32",
+ "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz",
+ "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=",
+ "dev": true
+ },
+ "@types/selenium-webdriver": {
+ "version": "3.0.16",
+ "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.16.tgz",
+ "integrity": "sha512-lMC2G0ItF2xv4UCiwbJGbnJlIuUixHrioOhNGHSCsYCJ8l4t9hMCUimCytvFv7qy6AfSzRxhRHoGa+UqaqwyeA==",
+ "dev": true
+ },
+ "@types/source-list-map": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
+ "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
+ "dev": true
+ },
+ "@types/webpack-sources": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz",
+ "integrity": "sha512-zfvjpp7jiafSmrzJ2/i3LqOyTYTuJ7u1KOXlKgDlvsj9Rr0x7ZiYu5lZbXwobL7lmsRNtPXlBfmaUD8eU2Hu8w==",
+ "dev": true,
+ "requires": {
+ "@types/node": "*",
+ "@types/source-list-map": "*",
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "@webassemblyjs/ast": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
+ "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/helper-module-context": "1.8.5",
+ "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+ "@webassemblyjs/wast-parser": "1.8.5"
+ }
+ },
+ "@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz",
+ "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-api-error": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz",
+ "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-buffer": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz",
+ "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-code-frame": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz",
+ "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/wast-printer": "1.8.5"
+ }
+ },
+ "@webassemblyjs/helper-fsm": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz",
+ "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-module-context": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz",
+ "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "mamacro": "^0.0.3"
+ }
+ },
+ "@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz",
+ "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==",
+ "dev": true
+ },
+ "@webassemblyjs/helper-wasm-section": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz",
+ "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/helper-buffer": "1.8.5",
+ "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+ "@webassemblyjs/wasm-gen": "1.8.5"
+ }
+ },
+ "@webassemblyjs/ieee754": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz",
+ "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==",
+ "dev": true,
+ "requires": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "@webassemblyjs/leb128": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz",
+ "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==",
+ "dev": true,
+ "requires": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "@webassemblyjs/utf8": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz",
+ "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==",
+ "dev": true
+ },
+ "@webassemblyjs/wasm-edit": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz",
+ "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/helper-buffer": "1.8.5",
+ "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+ "@webassemblyjs/helper-wasm-section": "1.8.5",
+ "@webassemblyjs/wasm-gen": "1.8.5",
+ "@webassemblyjs/wasm-opt": "1.8.5",
+ "@webassemblyjs/wasm-parser": "1.8.5",
+ "@webassemblyjs/wast-printer": "1.8.5"
+ }
+ },
+ "@webassemblyjs/wasm-gen": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz",
+ "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+ "@webassemblyjs/ieee754": "1.8.5",
+ "@webassemblyjs/leb128": "1.8.5",
+ "@webassemblyjs/utf8": "1.8.5"
+ }
+ },
+ "@webassemblyjs/wasm-opt": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz",
+ "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/helper-buffer": "1.8.5",
+ "@webassemblyjs/wasm-gen": "1.8.5",
+ "@webassemblyjs/wasm-parser": "1.8.5"
+ }
+ },
+ "@webassemblyjs/wasm-parser": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz",
+ "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/helper-api-error": "1.8.5",
+ "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+ "@webassemblyjs/ieee754": "1.8.5",
+ "@webassemblyjs/leb128": "1.8.5",
+ "@webassemblyjs/utf8": "1.8.5"
+ }
+ },
+ "@webassemblyjs/wast-parser": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz",
+ "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/floating-point-hex-parser": "1.8.5",
+ "@webassemblyjs/helper-api-error": "1.8.5",
+ "@webassemblyjs/helper-code-frame": "1.8.5",
+ "@webassemblyjs/helper-fsm": "1.8.5",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "@webassemblyjs/wast-printer": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz",
+ "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/wast-parser": "1.8.5",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+ "dev": true
+ },
+ "@xtuc/long": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+ "dev": true
+ },
+ "@yarnpkg/lockfile": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
+ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
+ "dev": true
+ },
+ "JSONStream": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+ "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+ "dev": true,
+ "requires": {
+ "jsonparse": "^1.2.0",
+ "through": ">=2.2.7 <3"
+ }
+ },
+ "accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "dev": true,
+ "requires": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ },
+ "dependencies": {
+ "mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.40.0"
+ }
+ }
+ }
+ },
+ "acorn": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz",
+ "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==",
+ "dev": true
+ },
+ "adal-angular": {
+ "version": "1.0.17",
+ "resolved": "https://registry.npmjs.org/adal-angular/-/adal-angular-1.0.17.tgz",
+ "integrity": "sha1-bpNuDkH5HTsqiOf/ypwvb29WLMQ="
+ },
+ "adaptivecards": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/adaptivecards/-/adaptivecards-1.2.0.tgz",
+ "integrity": "sha512-rfB3dr2/yNMgJHiGCFH247RtLXkKcNwhGbI1GrXSITfyqfo12esTWDLkRLe62b0oGZxPKJZo5187BY9xORZYsg=="
+ },
+ "adm-zip": {
+ "version": "0.4.13",
+ "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz",
+ "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==",
+ "dev": true
+ },
+ "after": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
+ "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
+ "dev": true
+ },
+ "agent-base": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
+ "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
+ "dev": true,
+ "requires": {
+ "es6-promisify": "^5.0.0"
+ }
+ },
+ "agentkeepalive": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz",
+ "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==",
+ "dev": true,
+ "requires": {
+ "humanize-ms": "^1.2.1"
+ }
+ },
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ajv-errors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
+ "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
+ "dev": true
+ },
+ "ajv-keywords": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
+ "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
+ "dev": true
+ },
+ "amdefine": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+ "dev": true
+ },
+ "ansi-colors": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
+ "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==",
+ "dev": true
+ },
+ "ansi-escapes": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz",
+ "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.5.2"
+ }
+ },
+ "ansi-html": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
+ "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "anymatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dev": true,
+ "requires": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ }
+ },
+ "app-root-path": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.2.1.tgz",
+ "integrity": "sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA==",
+ "dev": true
+ },
+ "append-transform": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
+ "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==",
+ "dev": true,
+ "requires": {
+ "default-require-extensions": "^2.0.0"
+ }
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+ "dev": true
+ },
+ "arg": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.1.tgz",
+ "integrity": "sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw==",
+ "dev": true
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "aria-query": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz",
+ "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=",
+ "dev": true,
+ "requires": {
+ "ast-types-flow": "0.0.7",
+ "commander": "^2.11.0"
+ }
+ },
+ "arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+ "dev": true
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "dev": true
+ },
+ "arr-union": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+ "dev": true
+ },
+ "array-flatten": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
+ "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
+ "dev": true
+ },
+ "array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+ "dev": true,
+ "requires": {
+ "array-uniq": "^1.0.1"
+ }
+ },
+ "array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+ "dev": true
+ },
+ "arraybuffer.slice": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
+ "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==",
+ "dev": true
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
+ "dev": true
+ },
+ "asn1": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
+ "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
+ "dev": true
+ },
+ "asn1.js": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
+ "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "assert": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
+ "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
+ "dev": true,
+ "requires": {
+ "object-assign": "^4.1.1",
+ "util": "0.10.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+ "dev": true
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ }
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+ "dev": true
+ },
+ "assign-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+ "dev": true
+ },
+ "ast-types-flow": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
+ "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=",
+ "dev": true
+ },
+ "async": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
+ "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.14"
+ }
+ },
+ "async-each": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
+ "dev": true
+ },
+ "async-limiter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
+ "dev": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
+ "dev": true
+ },
+ "atob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz",
+ "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=",
+ "dev": true
+ },
+ "autoprefixer": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.6.1.tgz",
+ "integrity": "sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.6.3",
+ "caniuse-lite": "^1.0.30000980",
+ "chalk": "^2.4.2",
+ "normalize-range": "^0.1.2",
+ "num2fraction": "^1.2.2",
+ "postcss": "^7.0.17",
+ "postcss-value-parser": "^4.0.0"
+ }
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+ "dev": true
+ },
+ "aws4": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
+ "dev": true
+ },
+ "axobject-query": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
+ "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==",
+ "dev": true,
+ "requires": {
+ "ast-types-flow": "0.0.7"
+ }
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "requires": {
+ "chalk": "^1.1.3",
+ "esutils": "^2.0.2",
+ "js-tokens": "^3.0.2"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "babel-generator": {
+ "version": "6.26.1",
+ "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
+ "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==",
+ "dev": true,
+ "requires": {
+ "babel-messages": "^6.23.0",
+ "babel-runtime": "^6.26.0",
+ "babel-types": "^6.26.0",
+ "detect-indent": "^4.0.0",
+ "jsesc": "^1.3.0",
+ "lodash": "^4.17.4",
+ "source-map": "^0.5.7",
+ "trim-right": "^1.0.1"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+ "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
+ "dev": true
+ }
+ }
+ },
+ "babel-messages": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.22.0"
+ }
+ },
+ "babel-plugin-dynamic-import-node": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz",
+ "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==",
+ "dev": true,
+ "requires": {
+ "object.assign": "^4.1.0"
+ }
+ },
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "dev": true,
+ "requires": {
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz",
+ "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==",
+ "dev": true
+ },
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+ "dev": true
+ }
+ }
+ },
+ "babel-template": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
+ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.26.0",
+ "babel-traverse": "^6.26.0",
+ "babel-types": "^6.26.0",
+ "babylon": "^6.18.0",
+ "lodash": "^4.17.4"
+ }
+ },
+ "babel-traverse": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
+ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "^6.26.0",
+ "babel-messages": "^6.23.0",
+ "babel-runtime": "^6.26.0",
+ "babel-types": "^6.26.0",
+ "babylon": "^6.18.0",
+ "debug": "^2.6.8",
+ "globals": "^9.18.0",
+ "invariant": "^2.2.2",
+ "lodash": "^4.17.4"
+ },
+ "dependencies": {
+ "globals": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+ "dev": true
+ }
+ }
+ },
+ "babel-types": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+ "dev": true,
+ "requires": {
+ "babel-runtime": "^6.26.0",
+ "esutils": "^2.0.2",
+ "lodash": "^4.17.4",
+ "to-fast-properties": "^1.0.3"
+ },
+ "dependencies": {
+ "to-fast-properties": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
+ "dev": true
+ }
+ }
+ },
+ "babylon": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
+ "dev": true
+ },
+ "backo2": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
+ "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "base": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+ "dev": true,
+ "requires": {
+ "cache-base": "^1.0.1",
+ "class-utils": "^0.3.5",
+ "component-emitter": "^1.2.1",
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.1",
+ "mixin-deep": "^1.2.0",
+ "pascalcase": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "base64-arraybuffer": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
+ "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
+ "dev": true
+ },
+ "base64-js": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
+ "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==",
+ "dev": true
+ },
+ "base64id": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
+ "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=",
+ "dev": true
+ },
+ "batch": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+ "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "better-assert": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
+ "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
+ "dev": true,
+ "requires": {
+ "callsite": "1.0.0"
+ }
+ },
+ "big.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
+ "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
+ "dev": true
+ },
+ "blob": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
+ "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==",
+ "dev": true
+ },
+ "blocking-proxy": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz",
+ "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "bluebird": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
+ "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==",
+ "dev": true
+ },
+ "bn.js": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
+ "dev": true
+ },
+ "body-parser": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+ "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "dev": true,
+ "requires": {
+ "bytes": "3.1.0",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "on-finished": "~2.3.0",
+ "qs": "6.7.0",
+ "raw-body": "2.4.0",
+ "type-is": "~1.6.17"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+ "dev": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+ "dev": true
+ }
+ }
+ },
+ "bonjour": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
+ "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+ "dev": true,
+ "requires": {
+ "array-flatten": "^2.1.0",
+ "deep-equal": "^1.0.1",
+ "dns-equal": "^1.0.0",
+ "dns-txt": "^2.0.2",
+ "multicast-dns": "^6.0.1",
+ "multicast-dns-service-types": "^1.1.0"
+ }
+ },
+ "bootstrap": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.3.1.tgz",
+ "integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag=="
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "requires": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+ "dev": true
+ },
+ "browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+ "dev": true,
+ "requires": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+ "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+ "dev": true,
+ "requires": {
+ "browserify-aes": "^1.0.4",
+ "browserify-des": "^1.0.0",
+ "evp_bytestokey": "^1.0.0"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+ "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "des.js": "^1.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "randombytes": "^2.0.1"
+ }
+ },
+ "browserify-sign": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.1",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.2",
+ "elliptic": "^6.0.0",
+ "inherits": "^2.0.1",
+ "parse-asn1": "^5.0.0"
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+ "dev": true,
+ "requires": {
+ "pako": "~1.0.5"
+ }
+ },
+ "browserslist": {
+ "version": "4.6.6",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz",
+ "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30000984",
+ "electron-to-chromium": "^1.3.191",
+ "node-releases": "^1.1.25"
+ }
+ },
+ "browserstack": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.3.tgz",
+ "integrity": "sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==",
+ "dev": true,
+ "requires": {
+ "https-proxy-agent": "^2.2.1"
+ }
+ },
+ "buffer": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+ "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4",
+ "isarray": "^1.0.0"
+ }
+ },
+ "buffer-alloc": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+ "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+ "dev": true,
+ "requires": {
+ "buffer-alloc-unsafe": "^1.1.0",
+ "buffer-fill": "^1.0.0"
+ }
+ },
+ "buffer-alloc-unsafe": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
+ "dev": true
+ },
+ "buffer-fill": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+ "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
+ "dev": true
+ },
+ "buffer-from": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz",
+ "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==",
+ "dev": true
+ },
+ "buffer-indexof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
+ "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
+ "dev": true
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+ "dev": true
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+ "dev": true
+ },
+ "builtins": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz",
+ "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=",
+ "dev": true
+ },
+ "bytes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+ "dev": true
+ },
+ "cacache": {
+ "version": "12.0.2",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.2.tgz",
+ "integrity": "sha512-ifKgxH2CKhJEg6tNdAwziu6Q33EvuG26tYcda6PT3WKisZcYDXsnEdnRv67Po3yCzFfaSoMjGZzJyD2c3DT1dg==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "infer-owner": "^1.0.3",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ },
+ "dependencies": {
+ "bluebird": {
+ "version": "3.5.5",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
+ "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
+ "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ }
+ }
+ },
+ "cache-base": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+ "dev": true,
+ "requires": {
+ "collection-visit": "^1.0.0",
+ "component-emitter": "^1.2.1",
+ "get-value": "^2.0.6",
+ "has-value": "^1.0.0",
+ "isobject": "^3.0.1",
+ "set-value": "^2.0.0",
+ "to-object-path": "^0.3.0",
+ "union-value": "^1.0.0",
+ "unset-value": "^1.0.0"
+ }
+ },
+ "caller-callsite": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+ "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+ "dev": true,
+ "requires": {
+ "callsites": "^2.0.0"
+ }
+ },
+ "caller-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+ "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+ "dev": true,
+ "requires": {
+ "caller-callsite": "^2.0.0"
+ }
+ },
+ "callsite": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
+ "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
+ "dev": true
+ },
+ "callsites": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+ "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "caniuse-lite": {
+ "version": "1.0.30000989",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz",
+ "integrity": "sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw==",
+ "dev": true
+ },
+ "canonical-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz",
+ "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==",
+ "dev": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.1.0.tgz",
+ "integrity": "sha512-6vZfo+7W0EOlbSo0nhVKMz4yyssrwiPbBZ8wj1lq8/+l4ZhGZ2U4Md7PspvmijXp1a26D3B7AHEBmIB7aVtaOQ==",
+ "dev": true,
+ "requires": {
+ "anymatch": "^3.1.0",
+ "braces": "^3.0.2",
+ "fsevents": "^2.0.6",
+ "glob-parent": "^5.0.0",
+ "is-binary-path": "^2.1.0",
+ "is-glob": "^4.0.1",
+ "normalize-path": "^3.0.0",
+ "readdirp": "^3.1.1"
+ },
+ "dependencies": {
+ "anymatch": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.0.tgz",
+ "integrity": "sha512-Ozz7l4ixzI7Oxj2+cw+p0tVUt27BpaJ+1+q1TCeANWxHpvyn2+Un+YamBdfKu0uh8xLodGhoa1v7595NhKDAuA==",
+ "dev": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "binary-extensions": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz",
+ "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==",
+ "dev": true
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "glob-parent": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz",
+ "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ }
+ }
+ },
+ "chownr": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.2.tgz",
+ "integrity": "sha512-GkfeAQh+QNy3wquu9oIZr6SS5x7wGdSgNQvD10X3r+AZr1Oys22HW8kAmDMvNg2+Dm0TeGaEuO8gFwdBXxwO8A==",
+ "dev": true
+ },
+ "chrome-trace-event": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
+ "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "circular-dependency-plugin": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.0.tgz",
+ "integrity": "sha512-7p4Kn/gffhQaavNfyDFg7LS5S/UT1JAjyGd4UqR2+jzoYF02eDkj0Ec3+48TsIa4zghjLY87nQHIh/ecK9qLdw==",
+ "dev": true
+ },
+ "class-utils": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "define-property": "^0.2.5",
+ "isobject": "^3.0.0",
+ "static-extend": "^0.1.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "clean-css": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
+ "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==",
+ "dev": true,
+ "requires": {
+ "source-map": "~0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^3.1.0"
+ }
+ },
+ "cli-width": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+ "dev": true
+ },
+ "cliui": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
+ "dev": true
+ },
+ "clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ }
+ },
+ "co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "dev": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+ "dev": true
+ },
+ "codelyzer": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-5.1.0.tgz",
+ "integrity": "sha512-QiyY2/oDQnYx4mAVEDqr+z9MwrOto18tQFjExiuRChXCy0yvngS5fQpWIxvAGpbOmZFiR1PRTRLbEI71u10maA==",
+ "dev": true,
+ "requires": {
+ "app-root-path": "^2.2.1",
+ "aria-query": "^3.0.0",
+ "axobject-query": "^2.0.2",
+ "css-selector-tokenizer": "^0.7.1",
+ "cssauron": "^1.4.0",
+ "damerau-levenshtein": "^1.0.4",
+ "semver-dsl": "^1.0.1",
+ "source-map": "^0.5.7",
+ "sprintf-js": "^1.1.2"
+ },
+ "dependencies": {
+ "sprintf-js": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz",
+ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==",
+ "dev": true
+ }
+ }
+ },
+ "collection-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+ "dev": true,
+ "requires": {
+ "map-visit": "^1.0.0",
+ "object-visit": "^1.0.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz",
+ "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.1"
+ }
+ },
+ "color-name": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz",
+ "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=",
+ "dev": true
+ },
+ "colors": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
+ "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "commander": {
+ "version": "2.20.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
+ "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
+ "dev": true
+ },
+ "commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+ "dev": true
+ },
+ "compare-versions": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.5.1.tgz",
+ "integrity": "sha512-9fGPIB7C6AyM18CJJBHt5EnCZDG3oiTJYy0NjfIAGjKpzv0tkxWko7TNQHF5ymqm7IH03tqmeuBxtvD+Izh6mg==",
+ "dev": true
+ },
+ "component-bind": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
+ "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=",
+ "dev": true
+ },
+ "component-emitter": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+ "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=",
+ "dev": true
+ },
+ "component-inherit": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
+ "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=",
+ "dev": true
+ },
+ "compressible": {
+ "version": "2.0.17",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz",
+ "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==",
+ "dev": true,
+ "requires": {
+ "mime-db": ">= 1.40.0 < 2"
+ },
+ "dependencies": {
+ "mime-db": {
+ "version": "1.41.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.41.0.tgz",
+ "integrity": "sha512-B5gxBI+2K431XW8C2rcc/lhppbuji67nf9v39eH8pkWoZDxnAL0PxdpH32KYRScniF8qDHBDlI+ipgg5WrCUYw==",
+ "dev": true
+ }
+ }
+ },
+ "compression": {
+ "version": "1.7.4",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
+ "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.5",
+ "bytes": "3.0.0",
+ "compressible": "~2.0.16",
+ "debug": "2.6.9",
+ "on-headers": "~1.0.2",
+ "safe-buffer": "5.1.2",
+ "vary": "~1.1.2"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "connect": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+ "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "finalhandler": "1.1.2",
+ "parseurl": "~1.3.3",
+ "utils-merge": "1.0.1"
+ }
+ },
+ "connect-history-api-fallback": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
+ "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+ "dev": true
+ },
+ "console-browserify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+ "dev": true,
+ "requires": {
+ "date-now": "^0.1.4"
+ }
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
+ "dev": true
+ },
+ "content-disposition": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
+ "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz",
+ "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "cookie": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
+ "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
+ "dev": true
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
+ "dev": true
+ },
+ "copy-concurrently": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+ "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.1.1",
+ "fs-write-stream-atomic": "^1.0.8",
+ "iferr": "^0.1.5",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.0"
+ }
+ },
+ "copy-descriptor": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+ "dev": true
+ },
+ "copy-webpack-plugin": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.4.tgz",
+ "integrity": "sha512-YBuYGpSzoCHSSDGyHy6VJ7SHojKp6WHT4D7ItcQFNAYx2hrwkMe56e97xfVR0/ovDuMTrMffXUiltvQljtAGeg==",
+ "dev": true,
+ "requires": {
+ "cacache": "^11.3.3",
+ "find-cache-dir": "^2.1.0",
+ "glob-parent": "^3.1.0",
+ "globby": "^7.1.1",
+ "is-glob": "^4.0.1",
+ "loader-utils": "^1.2.3",
+ "minimatch": "^3.0.4",
+ "normalize-path": "^3.0.0",
+ "p-limit": "^2.2.0",
+ "schema-utils": "^1.0.0",
+ "serialize-javascript": "^1.7.0",
+ "webpack-log": "^2.0.0"
+ },
+ "dependencies": {
+ "bluebird": {
+ "version": "3.5.5",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
+ "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==",
+ "dev": true
+ },
+ "cacache": {
+ "version": "11.3.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz",
+ "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ }
+ },
+ "find-cache-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+ "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^2.0.0",
+ "pkg-dir": "^3.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
+ "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+ "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ }
+ }
+ },
+ "core-js": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
+ "integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw=="
+ },
+ "core-js-compat": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.2.1.tgz",
+ "integrity": "sha512-MwPZle5CF9dEaMYdDeWm73ao/IflDH+FjeJCWEADcEgFSE9TLimFKwJsfmkwzI8eC0Aj0mgvMDjeQjrElkz4/A==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.6.6",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "cosmiconfig": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
+ "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+ "dev": true,
+ "requires": {
+ "import-fresh": "^2.0.0",
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.13.1",
+ "parse-json": "^4.0.0"
+ }
+ },
+ "create-ecdh": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
+ "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "elliptic": "^6.0.0"
+ }
+ },
+ "create-hash": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+ "dev": true,
+ "requires": {
+ "browserify-cipher": "^1.0.0",
+ "browserify-sign": "^4.0.0",
+ "create-ecdh": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.0",
+ "diffie-hellman": "^5.0.0",
+ "inherits": "^2.0.1",
+ "pbkdf2": "^3.0.3",
+ "public-encrypt": "^4.0.0",
+ "randombytes": "^2.0.0",
+ "randomfill": "^1.0.3"
+ }
+ },
+ "css-parse": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz",
+ "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=",
+ "dev": true
+ },
+ "css-selector-tokenizer": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.1.tgz",
+ "integrity": "sha512-xYL0AMZJ4gFzJQsHUKa5jiWWi2vH77WVNg7JYRyewwj6oPh4yb/y6Y9ZCw9dsj/9UauMhtuxR+ogQd//EdEVNA==",
+ "dev": true,
+ "requires": {
+ "cssesc": "^0.1.0",
+ "fastparse": "^1.1.1",
+ "regexpu-core": "^1.0.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true
+ },
+ "regexpu-core": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
+ "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.2.1",
+ "regjsgen": "^0.2.0",
+ "regjsparser": "^0.1.4"
+ }
+ },
+ "regjsgen": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+ "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+ "dev": true,
+ "requires": {
+ "jsesc": "~0.5.0"
+ }
+ }
+ }
+ },
+ "cssauron": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz",
+ "integrity": "sha1-pmAt/34EqDBtwNuaVR6S6LVmKtg=",
+ "dev": true,
+ "requires": {
+ "through": "X.X.X"
+ }
+ },
+ "cssesc": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz",
+ "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=",
+ "dev": true
+ },
+ "csstype": {
+ "version": "2.6.6",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.6.tgz",
+ "integrity": "sha512-RpFbQGUE74iyPgvr46U9t1xoQBM8T4BL8SxrN66Le2xYAPSaDJJKeztV3awugusb3g3G9iL8StmkBBXhcbbXhg=="
+ },
+ "custom-event": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
+ "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=",
+ "dev": true
+ },
+ "cyclist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
+ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
+ "dev": true
+ },
+ "damerau-levenshtein": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz",
+ "integrity": "sha512-CBCRqFnpu715iPmw1KrdOrzRqbdFwQTwAWyyyYS42+iAgHCuXZ+/TdMgQkUENPomxEz9z1BEzuQU2Xw0kUuAgA==",
+ "dev": true
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "date-format": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz",
+ "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==",
+ "dev": true
+ },
+ "date-now": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+ "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "debuglog": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz",
+ "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=",
+ "dev": true
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+ "dev": true
+ },
+ "deep-equal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.0.tgz",
+ "integrity": "sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw==",
+ "dev": true,
+ "requires": {
+ "is-arguments": "^1.0.4",
+ "is-date-object": "^1.0.1",
+ "is-regex": "^1.0.4",
+ "object-is": "^1.0.1",
+ "object-keys": "^1.1.1",
+ "regexp.prototype.flags": "^1.2.0"
+ }
+ },
+ "default-gateway": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz",
+ "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0",
+ "ip-regex": "^2.1.0"
+ }
+ },
+ "default-require-extensions": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz",
+ "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=",
+ "dev": true,
+ "requires": {
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "define-property": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.2",
+ "isobject": "^3.0.1"
+ },
+ "dependencies": {
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "del": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz",
+ "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==",
+ "dev": true,
+ "requires": {
+ "@types/glob": "^7.1.1",
+ "globby": "^6.1.0",
+ "is-path-cwd": "^2.0.0",
+ "is-path-in-cwd": "^2.0.0",
+ "p-map": "^2.0.0",
+ "pify": "^4.0.1",
+ "rimraf": "^2.6.3"
+ },
+ "dependencies": {
+ "globby": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+ "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "glob": "^7.0.3",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ }
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
+ "dev": true
+ },
+ "depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+ "dev": true
+ },
+ "dependency-graph": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.7.2.tgz",
+ "integrity": "sha512-KqtH4/EZdtdfWX0p6MGP9jljvxSY6msy/pRUD4jgNwVpv3v1QmNLlsB3LDSSUg79BRVSn7jI1QPRtArGABovAQ==",
+ "dev": true
+ },
+ "des.js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
+ "dev": true
+ },
+ "detect-indent": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
+ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
+ "dev": true,
+ "requires": {
+ "repeating": "^2.0.0"
+ }
+ },
+ "detect-node": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
+ "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
+ "dev": true
+ },
+ "dezalgo": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
+ "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=",
+ "dev": true,
+ "requires": {
+ "asap": "^2.0.0",
+ "wrappy": "1"
+ }
+ },
+ "di": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz",
+ "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=",
+ "dev": true
+ },
+ "diff": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz",
+ "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==",
+ "dev": true
+ },
+ "diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ }
+ },
+ "dir-glob": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
+ "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
+ "dev": true,
+ "requires": {
+ "path-type": "^3.0.0"
+ }
+ },
+ "dns-equal": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
+ "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
+ "dev": true
+ },
+ "dns-packet": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
+ "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
+ "dev": true,
+ "requires": {
+ "ip": "^1.1.0",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "dns-txt": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
+ "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+ "dev": true,
+ "requires": {
+ "buffer-indexof": "^1.0.0"
+ }
+ },
+ "dom-serialize": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz",
+ "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=",
+ "dev": true,
+ "requires": {
+ "custom-event": "~1.0.0",
+ "ent": "~2.2.0",
+ "extend": "^3.0.0",
+ "void-elements": "^2.0.0"
+ }
+ },
+ "domain-browser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+ "dev": true
+ },
+ "duplexify": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
+ "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+ "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "~0.1.0"
+ }
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+ "dev": true
+ },
+ "electron-to-chromium": {
+ "version": "1.3.261",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.261.tgz",
+ "integrity": "sha512-nA9xFj1SgHXlW/6T4+udW2u/Ic/bne25UoFsddoNM7Ut2bgNGLLQUhLhk+vQlbKh9WiRgDDlHaC36Oy7AgRR9w==",
+ "dev": true
+ },
+ "elliptic": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz",
+ "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.4.0",
+ "brorand": "^1.0.1",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.0"
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "emojis-list": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
+ "dev": true
+ },
+ "encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+ "dev": true
+ },
+ "encoding": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
+ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
+ "dev": true,
+ "requires": {
+ "iconv-lite": "~0.4.13"
+ }
+ },
+ "end-of-stream": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "engine.io": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz",
+ "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.4",
+ "base64id": "1.0.0",
+ "cookie": "0.3.1",
+ "debug": "~3.1.0",
+ "engine.io-parser": "~2.1.0",
+ "ws": "~3.3.1"
+ },
+ "dependencies": {
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ws": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
+ "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
+ "dev": true,
+ "requires": {
+ "async-limiter": "~1.0.0",
+ "safe-buffer": "~5.1.0",
+ "ultron": "~1.1.0"
+ }
+ }
+ }
+ },
+ "engine.io-client": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz",
+ "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==",
+ "dev": true,
+ "requires": {
+ "component-emitter": "1.2.1",
+ "component-inherit": "0.0.3",
+ "debug": "~3.1.0",
+ "engine.io-parser": "~2.1.1",
+ "has-cors": "1.1.0",
+ "indexof": "0.0.1",
+ "parseqs": "0.0.5",
+ "parseuri": "0.0.5",
+ "ws": "~3.3.1",
+ "xmlhttprequest-ssl": "~1.5.4",
+ "yeast": "0.1.2"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ws": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
+ "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
+ "dev": true,
+ "requires": {
+ "async-limiter": "~1.0.0",
+ "safe-buffer": "~5.1.0",
+ "ultron": "~1.1.0"
+ }
+ }
+ }
+ },
+ "engine.io-parser": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
+ "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
+ "dev": true,
+ "requires": {
+ "after": "0.8.2",
+ "arraybuffer.slice": "~0.0.7",
+ "base64-arraybuffer": "0.1.5",
+ "blob": "0.0.5",
+ "has-binary2": "~1.0.2"
+ }
+ },
+ "enhanced-resolve": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz",
+ "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "memory-fs": "^0.4.0",
+ "tapable": "^1.0.0"
+ }
+ },
+ "ent": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz",
+ "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=",
+ "dev": true
+ },
+ "entities": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
+ "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw=="
+ },
+ "err-code": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz",
+ "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=",
+ "dev": true
+ },
+ "errno": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+ "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+ "dev": true,
+ "requires": {
+ "prr": "~1.0.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.14.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.14.2.tgz",
+ "integrity": "sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg==",
+ "dev": true,
+ "requires": {
+ "es-to-primitive": "^1.2.0",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.0",
+ "is-callable": "^1.1.4",
+ "is-regex": "^1.0.4",
+ "object-inspect": "^1.6.0",
+ "object-keys": "^1.1.1",
+ "string.prototype.trimleft": "^2.0.0",
+ "string.prototype.trimright": "^2.0.0"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+ "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "es6-promise": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz",
+ "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==",
+ "dev": true
+ },
+ "es6-promisify": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+ "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+ "dev": true,
+ "requires": {
+ "es6-promise": "^4.0.3"
+ }
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "eslint-scope": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
+ "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.1.0",
+ "estraverse": "^4.1.1"
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true
+ },
+ "esrecurse": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+ "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^4.1.0"
+ }
+ },
+ "estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
+ "dev": true
+ },
+ "eventemitter3": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz",
+ "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==",
+ "dev": true
+ },
+ "events": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
+ "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==",
+ "dev": true
+ },
+ "eventsource": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz",
+ "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==",
+ "dev": true,
+ "requires": {
+ "original": "^1.0.0"
+ }
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "dev": true,
+ "requires": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dev": true,
+ "requires": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ }
+ }
+ },
+ "exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+ "dev": true
+ },
+ "expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+ "dev": true,
+ "requires": {
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "expose-loader": {
+ "version": "0.7.5",
+ "resolved": "https://registry.npmjs.org/expose-loader/-/expose-loader-0.7.5.tgz",
+ "integrity": "sha512-iPowgKUZkTPX5PznYsmifVj9Bob0w2wTHVkt/eYNPSzyebkUgIedmskf/kcfEIWpiWjg3JRjnW+a17XypySMuw=="
+ },
+ "express": {
+ "version": "4.17.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
+ "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.7",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.19.0",
+ "content-disposition": "0.5.3",
+ "content-type": "~1.0.4",
+ "cookie": "0.4.0",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.1.2",
+ "fresh": "0.5.2",
+ "merge-descriptors": "1.0.1",
+ "methods": "~1.1.2",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.7",
+ "proxy-addr": "~2.0.5",
+ "qs": "6.7.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.1.2",
+ "send": "0.17.1",
+ "serve-static": "1.14.1",
+ "setprototypeof": "1.1.1",
+ "statuses": "~1.5.0",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "dependencies": {
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+ "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+ "dev": true
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "extend-shallow": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+ "dev": true,
+ "requires": {
+ "assign-symbols": "^1.0.0",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dev": true,
+ "requires": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ },
+ "dependencies": {
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ }
+ }
+ },
+ "extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "dev": true,
+ "requires": {
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+ "dev": true
+ },
+ "fastparse": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
+ "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
+ "dev": true
+ },
+ "faye-websocket": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+ "dev": true,
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "figgy-pudding": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
+ "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==",
+ "dev": true
+ },
+ "figures": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.0.0.tgz",
+ "integrity": "sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "file-loader": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.2.0.tgz",
+ "integrity": "sha512-+xZnaK5R8kBJrHK0/6HRlrKNamvVS5rjyuju+rnyxRGuwUJwpAMsVzUl5dz6rK8brkzjV6JpcFNjp6NqV0g1OQ==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.2.3",
+ "schema-utils": "^2.0.0"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.2.0.tgz",
+ "integrity": "sha512-5EwsCNhfFTZvUreQhx/4vVQpJ/lnCAkgoIHLhSpp4ZirE+4hzFvdJi0FMub6hxbFVBJYSpeVVmon+2e7uEGRrA==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.10.2",
+ "ajv-keywords": "^3.4.1"
+ }
+ }
+ }
+ },
+ "fileset": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz",
+ "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=",
+ "dev": true,
+ "requires": {
+ "glob": "^7.0.3",
+ "minimatch": "^3.0.3"
+ }
+ },
+ "fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "finalhandler": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+ "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.3.0",
+ "parseurl": "~1.3.3",
+ "statuses": "~1.5.0",
+ "unpipe": "~1.0.0"
+ }
+ },
+ "find-cache-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.0.0.tgz",
+ "integrity": "sha512-t7ulV1fmbxh5G9l/492O1p5+EBbr3uwpt6odhFTMc+nWyhmbloe+ja9BZ8pIBtqFWhOmCWVjx+pTW4zDkFoclw==",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^3.0.0",
+ "pkg-dir": "^4.1.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "make-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz",
+ "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==",
+ "dev": true,
+ "requires": {
+ "semver": "^6.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ },
+ "pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "requires": {
+ "find-up": "^4.0.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "flatted": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
+ "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
+ "dev": true
+ },
+ "flush-write-stream": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
+ "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.3.6"
+ }
+ },
+ "follow-redirects": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.9.0.tgz",
+ "integrity": "sha512-CRcPzsSIbXyVDl0QI01muNDu69S8trU4jArW9LpOt2WtC6LyUJetcIrmfHsRBx7/Jb6GHJUiuqyYxPooFfNt6A==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+ "dev": true
+ },
+ "form-data": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
+ "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "forwarded": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+ "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
+ "dev": true
+ },
+ "fragment-cache": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+ "dev": true,
+ "requires": {
+ "map-cache": "^0.2.2"
+ }
+ },
+ "free-style": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/free-style/-/free-style-2.6.1.tgz",
+ "integrity": "sha512-uaVA8e57tvhrFKAl6x32SGIrGFBoeTAFtfHDzWxjPhiXQiUxOI6EEdEReRkjNO2H9XcdMJXXEnMHw8Q7iMYLbw=="
+ },
+ "fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
+ "dev": true
+ },
+ "from2": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+ "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0"
+ }
+ },
+ "fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "fs-minipass": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
+ "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
+ "dev": true,
+ "requires": {
+ "minipass": "^2.6.0"
+ }
+ },
+ "fs-write-stream-atomic": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+ "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "iferr": "^0.1.5",
+ "imurmurhash": "^0.1.4",
+ "readable-stream": "1 || 2"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz",
+ "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==",
+ "dev": true,
+ "optional": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "genfun": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz",
+ "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==",
+ "dev": true
+ },
+ "get-caller-file": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
+ "dev": true
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ },
+ "dependencies": {
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ }
+ }
+ },
+ "get-value": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+ "dev": true
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+ "dev": true,
+ "requires": {
+ "is-glob": "^3.1.0",
+ "path-dirname": "^1.0.0"
+ },
+ "dependencies": {
+ "is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.0"
+ }
+ }
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "globby": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
+ "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "dir-glob": "^2.0.0",
+ "glob": "^7.1.2",
+ "ignore": "^3.3.5",
+ "pify": "^3.0.0",
+ "slash": "^1.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ }
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+ "dev": true
+ },
+ "handle-thing": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz",
+ "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==",
+ "dev": true
+ },
+ "handlebars": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.2.0.tgz",
+ "integrity": "sha512-Kb4xn5Qh1cxAKvQnzNWZ512DhABzyFNmsaJf3OAkWNa4NkaqWcNI8Tao8Tasi0/F4JD9oyG0YxuFyvyR57d+Gw==",
+ "dev": true,
+ "requires": {
+ "neo-async": "^2.6.0",
+ "optimist": "^0.6.1",
+ "source-map": "^0.6.1",
+ "uglify-js": "^3.1.4"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+ "dev": true
+ },
+ "har-validator": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+ "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.5.5",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "has-binary2": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
+ "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
+ "dev": true,
+ "requires": {
+ "isarray": "2.0.1"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+ "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
+ "dev": true
+ }
+ }
+ },
+ "has-cors": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
+ "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "has-symbols": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+ "dev": true
+ },
+ "has-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.6",
+ "has-values": "^1.0.0",
+ "isobject": "^3.0.0"
+ }
+ },
+ "has-values": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "kind-of": "^4.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "hash-base": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "dev": true,
+ "requires": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "hosted-git-info": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz",
+ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
+ "dev": true
+ },
+ "hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "obuf": "^1.0.0",
+ "readable-stream": "^2.0.1",
+ "wbuf": "^1.1.0"
+ }
+ },
+ "html-entities": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
+ "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
+ "dev": true
+ },
+ "http-cache-semantics": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz",
+ "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==",
+ "dev": true
+ },
+ "http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+ "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "dev": true,
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.1",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.0"
+ }
+ },
+ "http-parser-js": {
+ "version": "0.4.10",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz",
+ "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=",
+ "dev": true
+ },
+ "http-proxy": {
+ "version": "1.18.0",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz",
+ "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==",
+ "dev": true,
+ "requires": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "http-proxy-agent": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz",
+ "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
+ "dev": true,
+ "requires": {
+ "agent-base": "4",
+ "debug": "3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "http-proxy-middleware": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz",
+ "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==",
+ "dev": true,
+ "requires": {
+ "http-proxy": "^1.17.0",
+ "is-glob": "^4.0.0",
+ "lodash": "^4.17.11",
+ "micromatch": "^3.1.10"
+ }
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "https-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
+ "dev": true
+ },
+ "https-proxy-agent": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
+ "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
+ "dev": true,
+ "requires": {
+ "agent-base": "^4.1.0",
+ "debug": "^3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=",
+ "dev": true,
+ "requires": {
+ "ms": "^2.0.0"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
+ "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
+ "dev": true
+ },
+ "ieee754": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
+ "dev": true
+ },
+ "iferr": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
+ "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=",
+ "dev": true
+ },
+ "ignore": {
+ "version": "3.3.10",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
+ "dev": true
+ },
+ "ignore-walk": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.2.tgz",
+ "integrity": "sha512-EXyErtpHbn75ZTsOADsfx6J/FPo6/5cjev46PXrcTpd8z3BoRkXgYu9/JVqrI7tusjmwCZutGeRJeU0Wo1e4Cw==",
+ "dev": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "image-size": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
+ "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
+ "dev": true,
+ "optional": true
+ },
+ "immediate": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+ "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=",
+ "dev": true
+ },
+ "import-cwd": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
+ "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=",
+ "dev": true,
+ "requires": {
+ "import-from": "^2.1.0"
+ }
+ },
+ "import-fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
+ "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=",
+ "dev": true,
+ "requires": {
+ "caller-path": "^2.0.0",
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "import-from": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz",
+ "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=",
+ "dev": true,
+ "requires": {
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "import-local": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
+ "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
+ "dev": true,
+ "requires": {
+ "pkg-dir": "^3.0.0",
+ "resolve-cwd": "^2.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true
+ },
+ "indexof": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
+ "dev": true
+ },
+ "infer-owner": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
+ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
+ "dev": true
+ },
+ "inquirer": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.1.tgz",
+ "integrity": "sha512-uxNHBeQhRXIoHWTSNYUFhQVrHYFThIt6IVo2fFmSe8aBwdR3/w6b58hJpiL/fMukFkvGzjg+hSxFtwvVmKZmXw==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^2.4.2",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^2.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.15",
+ "mute-stream": "0.0.8",
+ "run-async": "^2.2.0",
+ "rxjs": "^6.4.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^5.1.0",
+ "through": "^2.3.6"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+ "dev": true
+ },
+ "rxjs": {
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz",
+ "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "string-width": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz",
+ "integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==",
+ "dev": true,
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^5.2.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^4.1.0"
+ }
+ }
+ }
+ },
+ "internal-ip": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz",
+ "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==",
+ "dev": true,
+ "requires": {
+ "default-gateway": "^4.2.0",
+ "ipaddr.js": "^1.9.0"
+ }
+ },
+ "invariant": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+ "dev": true,
+ "requires": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
+ "dev": true
+ },
+ "ip": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
+ "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=",
+ "dev": true
+ },
+ "ip-regex": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
+ "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=",
+ "dev": true
+ },
+ "ipaddr.js": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
+ "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==",
+ "dev": true
+ },
+ "is-absolute-url": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.2.tgz",
+ "integrity": "sha512-+5g/wLlcm1AcxSP7014m6GvbPHswDx980vD/3bZaap8aGV9Yfs7Q6y6tfaupgZ5O74Byzc8dGrSCJ+bFXx0KdA==",
+ "dev": true
+ },
+ "is-accessor-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
+ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-arguments": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
+ "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==",
+ "dev": true
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
+ "dev": true
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^1.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "is-builtin-module": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
+ "dev": true,
+ "requires": {
+ "builtin-modules": "^1.0.0"
+ }
+ },
+ "is-callable": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
+ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
+ "dev": true
+ },
+ "is-data-descriptor": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
+ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
+ "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
+ "dev": true
+ },
+ "is-descriptor": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
+ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^0.1.6",
+ "is-data-descriptor": "^0.1.4",
+ "kind-of": "^5.0.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true
+ }
+ }
+ },
+ "is-directory": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=",
+ "dev": true
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
+ },
+ "is-finite": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "is-glob": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz",
+ "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "is-path-cwd": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
+ "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
+ "dev": true
+ },
+ "is-path-in-cwd": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz",
+ "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==",
+ "dev": true,
+ "requires": {
+ "is-path-inside": "^2.1.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz",
+ "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "^1.0.2"
+ }
+ },
+ "is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=",
+ "dev": true
+ },
+ "is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+ "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
+ "dev": true
+ },
+ "is-regex": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
+ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.1"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
+ "dev": true
+ },
+ "is-symbol": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
+ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.0"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true
+ },
+ "is-wsl": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
+ "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isbinaryfile": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz",
+ "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==",
+ "dev": true,
+ "requires": {
+ "buffer-alloc": "^1.2.0"
+ }
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+ "dev": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
+ "dev": true
+ },
+ "istanbul-api": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.6.tgz",
+ "integrity": "sha512-x0Eicp6KsShG1k1rMgBAi/1GgY7kFGEBwQpw3PXGEmu+rBcBNhqU8g2DgY9mlepAsLPzrzrbqSgCGANnki4POA==",
+ "dev": true,
+ "requires": {
+ "async": "^2.6.2",
+ "compare-versions": "^3.4.0",
+ "fileset": "^2.0.3",
+ "istanbul-lib-coverage": "^2.0.5",
+ "istanbul-lib-hook": "^2.0.7",
+ "istanbul-lib-instrument": "^3.3.0",
+ "istanbul-lib-report": "^2.0.8",
+ "istanbul-lib-source-maps": "^3.0.6",
+ "istanbul-reports": "^2.2.4",
+ "js-yaml": "^3.13.1",
+ "make-dir": "^2.1.0",
+ "minimatch": "^3.0.4",
+ "once": "^1.4.0"
+ },
+ "dependencies": {
+ "istanbul-lib-coverage": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+ "dev": true
+ },
+ "istanbul-lib-instrument": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
+ "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
+ "dev": true,
+ "requires": {
+ "@babel/generator": "^7.4.0",
+ "@babel/parser": "^7.4.3",
+ "@babel/template": "^7.4.0",
+ "@babel/traverse": "^7.4.3",
+ "@babel/types": "^7.4.0",
+ "istanbul-lib-coverage": "^2.0.5",
+ "semver": "^6.0.0"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "istanbul-instrumenter-loader": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz",
+ "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==",
+ "dev": true,
+ "requires": {
+ "convert-source-map": "^1.5.0",
+ "istanbul-lib-instrument": "^1.7.3",
+ "loader-utils": "^1.1.0",
+ "schema-utils": "^0.3.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "5.5.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+ "dev": true,
+ "requires": {
+ "co": "^4.6.0",
+ "fast-deep-equal": "^1.0.0",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.3.0"
+ }
+ },
+ "fast-deep-equal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+ "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
+ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
+ "dev": true
+ },
+ "schema-utils": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
+ "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=",
+ "dev": true,
+ "requires": {
+ "ajv": "^5.0.0"
+ }
+ }
+ }
+ },
+ "istanbul-lib-coverage": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz",
+ "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==",
+ "dev": true
+ },
+ "istanbul-lib-hook": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz",
+ "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==",
+ "dev": true,
+ "requires": {
+ "append-transform": "^1.0.0"
+ }
+ },
+ "istanbul-lib-instrument": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz",
+ "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==",
+ "dev": true,
+ "requires": {
+ "babel-generator": "^6.18.0",
+ "babel-template": "^6.16.0",
+ "babel-traverse": "^6.18.0",
+ "babel-types": "^6.18.0",
+ "babylon": "^6.18.0",
+ "istanbul-lib-coverage": "^1.2.1",
+ "semver": "^5.3.0"
+ }
+ },
+ "istanbul-lib-report": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz",
+ "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==",
+ "dev": true,
+ "requires": {
+ "istanbul-lib-coverage": "^2.0.5",
+ "make-dir": "^2.1.0",
+ "supports-color": "^6.1.0"
+ },
+ "dependencies": {
+ "istanbul-lib-coverage": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "istanbul-lib-source-maps": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz",
+ "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^2.0.5",
+ "make-dir": "^2.1.0",
+ "rimraf": "^2.6.3",
+ "source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "glob": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "istanbul-lib-coverage": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "istanbul-reports": {
+ "version": "2.2.6",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz",
+ "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==",
+ "dev": true,
+ "requires": {
+ "handlebars": "^4.1.2"
+ }
+ },
+ "jasmine": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz",
+ "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=",
+ "dev": true,
+ "requires": {
+ "exit": "^0.1.2",
+ "glob": "^7.0.6",
+ "jasmine-core": "~2.8.0"
+ },
+ "dependencies": {
+ "jasmine-core": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz",
+ "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=",
+ "dev": true
+ }
+ }
+ },
+ "jasmine-core": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.4.0.tgz",
+ "integrity": "sha512-HU/YxV4i6GcmiH4duATwAbJQMlE0MsDIR5XmSVxURxKHn3aGAdbY1/ZJFmVRbKtnLwIxxMJD7gYaPsypcbYimg==",
+ "dev": true
+ },
+ "jasmine-spec-reporter": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz",
+ "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==",
+ "dev": true,
+ "requires": {
+ "colors": "1.1.2"
+ }
+ },
+ "jasminewd2": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz",
+ "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=",
+ "dev": true
+ },
+ "jquery": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
+ "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
+ },
+ "js-levenshtein": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
+ "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.13.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
+ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
+ "dev": true,
+ "optional": true
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "dev": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
+ "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
+ "dev": true
+ },
+ "json3": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz",
+ "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==",
+ "dev": true
+ },
+ "json5": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
+ "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=",
+ "dev": true
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
+ "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ }
+ },
+ "jszip": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.1.5.tgz",
+ "integrity": "sha512-5W8NUaFRFRqTOL7ZDDrx5qWHJyBXy6velVudIzQUSoqAAYqzSh2Z7/m0Rf1QbmQJccegD0r+YZxBjzqoBiEeJQ==",
+ "dev": true,
+ "requires": {
+ "core-js": "~2.3.0",
+ "es6-promise": "~3.0.2",
+ "lie": "~3.1.0",
+ "pako": "~1.0.2",
+ "readable-stream": "~2.0.6"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz",
+ "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=",
+ "dev": true
+ },
+ "es6-promise": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz",
+ "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~1.0.6",
+ "string_decoder": "~0.10.x",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ }
+ }
+ },
+ "karma": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/karma/-/karma-4.3.0.tgz",
+ "integrity": "sha512-NSPViHOt+RW38oJklvYxQC4BSQsv737oQlr/r06pCM+slDOr4myuI1ivkRmp+3dVpJDfZt2DmaPJ2wkx+ZZuMQ==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.3.0",
+ "body-parser": "^1.16.1",
+ "braces": "^3.0.2",
+ "chokidar": "^3.0.0",
+ "colors": "^1.1.0",
+ "connect": "^3.6.0",
+ "core-js": "^3.1.3",
+ "di": "^0.0.1",
+ "dom-serialize": "^2.2.0",
+ "flatted": "^2.0.0",
+ "glob": "^7.1.1",
+ "graceful-fs": "^4.1.2",
+ "http-proxy": "^1.13.0",
+ "isbinaryfile": "^3.0.0",
+ "lodash": "^4.17.14",
+ "log4js": "^4.0.0",
+ "mime": "^2.3.1",
+ "minimatch": "^3.0.2",
+ "optimist": "^0.6.1",
+ "qjobs": "^1.1.4",
+ "range-parser": "^1.2.0",
+ "rimraf": "^2.6.0",
+ "safe-buffer": "^5.0.1",
+ "socket.io": "2.1.1",
+ "source-map": "^0.6.1",
+ "tmp": "0.0.33",
+ "useragent": "2.3.0"
+ },
+ "dependencies": {
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "mime": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ }
+ }
+ },
+ "karma-chrome-launcher": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.0.tgz",
+ "integrity": "sha512-3dPs/n7vgz1rxxtynpzZTvb9y/GIaW8xjAwcIGttLbycqoFtI7yo1NGnQi6oFTherRE+GIhCAHZC4vEqWGhNvg==",
+ "dev": true,
+ "requires": {
+ "which": "^1.2.1"
+ }
+ },
+ "karma-coverage-istanbul-reporter": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.1.0.tgz",
+ "integrity": "sha512-UH0mXPJFJyK5uiK7EkwGtQ8f30lCBAfqRResnZ4pzLJ04SOp4SPlYkmwbbZ6iVJ6sQFVzlDUXlntBEsLRdgZpg==",
+ "dev": true,
+ "requires": {
+ "istanbul-api": "^2.1.6",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "karma-jasmine": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-2.0.1.tgz",
+ "integrity": "sha512-iuC0hmr9b+SNn1DaUD2QEYtUxkS1J+bSJSn7ejdEexs7P8EYvA1CWkEdrDQ+8jVH3AgWlCNwjYsT1chjcNW9lA==",
+ "dev": true,
+ "requires": {
+ "jasmine-core": "^3.3"
+ }
+ },
+ "karma-jasmine-html-reporter": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.4.2.tgz",
+ "integrity": "sha512-7g0gPj8+9JepCNJR9WjDyQ2RkZ375jpdurYQyAYv8PorUCadepl8vrD6LmMqOGcM17cnrynBawQYZHaumgDjBw==",
+ "dev": true
+ },
+ "karma-source-map-support": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz",
+ "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==",
+ "dev": true,
+ "requires": {
+ "source-map-support": "^0.5.5"
+ }
+ },
+ "killable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
+ "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+ "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+ "dev": true
+ },
+ "lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "dev": true,
+ "requires": {
+ "invert-kv": "^2.0.0"
+ }
+ },
+ "less": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/less/-/less-3.9.0.tgz",
+ "integrity": "sha512-31CmtPEZraNUtuUREYjSqRkeETFdyEHSEPAGq4erDlUXtda7pzNmctdljdIagSb589d/qXGWiiP31R5JVf+v0w==",
+ "dev": true,
+ "requires": {
+ "clone": "^2.1.2",
+ "errno": "^0.1.1",
+ "graceful-fs": "^4.1.2",
+ "image-size": "~0.5.0",
+ "mime": "^1.4.1",
+ "mkdirp": "^0.5.0",
+ "promise": "^7.1.1",
+ "request": "^2.83.0",
+ "source-map": "~0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "less-loader": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-5.0.0.tgz",
+ "integrity": "sha512-bquCU89mO/yWLaUq0Clk7qCsKhsF/TZpJUzETRvJa9KSVEL9SO3ovCvdEHISBhrC81OwC8QSVX7E0bzElZj9cg==",
+ "dev": true,
+ "requires": {
+ "clone": "^2.1.1",
+ "loader-utils": "^1.1.0",
+ "pify": "^4.0.1"
+ }
+ },
+ "license-webpack-plugin": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.1.2.tgz",
+ "integrity": "sha512-7poZHRla+ae0eEButlwMrPpkXyhNVBf2EHePYWT0jyLnI6311/OXJkTI2sOIRungRpQgU2oDMpro5bSFPT5F0A==",
+ "dev": true,
+ "requires": {
+ "@types/webpack-sources": "^0.1.5",
+ "webpack-sources": "^1.2.0"
+ }
+ },
+ "lie": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
+ "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=",
+ "dev": true,
+ "requires": {
+ "immediate": "~3.0.5"
+ }
+ },
+ "linkify-it": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
+ "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
+ "requires": {
+ "uc.micro": "^1.0.1"
+ }
+ },
+ "loader-runner": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
+ "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==",
+ "dev": true
+ },
+ "loader-utils": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz",
+ "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^2.0.0",
+ "json5": "^1.0.1"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+ "dev": true
+ },
+ "lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
+ "dev": true
+ },
+ "lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
+ },
+ "log4js": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz",
+ "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==",
+ "dev": true,
+ "requires": {
+ "date-format": "^2.0.0",
+ "debug": "^4.1.1",
+ "flatted": "^2.0.0",
+ "rfdc": "^1.1.4",
+ "streamroller": "^1.0.6"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "loglevel": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.4.tgz",
+ "integrity": "sha512-p0b6mOGKcGa+7nnmKbpzR6qloPbrgLcnio++E+14Vo/XffOGwZtRpUhr8dTH/x2oCMmEoIU0Zwm3ZauhvYD17g==",
+ "dev": true
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dev": true,
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "magic-string": {
+ "version": "0.25.3",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz",
+ "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==",
+ "dev": true,
+ "requires": {
+ "sourcemap-codec": "^1.4.4"
+ }
+ },
+ "make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "dev": true,
+ "requires": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ }
+ }
+ },
+ "make-error": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz",
+ "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==",
+ "dev": true
+ },
+ "make-fetch-happen": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.0.tgz",
+ "integrity": "sha512-nFr/vpL1Jc60etMVKeaLOqfGjMMb3tAHFVJWxHOFCFS04Zmd7kGlMxo0l1tzfhoQje0/UPnd0X8OeGUiXXnfPA==",
+ "dev": true,
+ "requires": {
+ "agentkeepalive": "^3.4.1",
+ "cacache": "^12.0.0",
+ "http-cache-semantics": "^3.8.1",
+ "http-proxy-agent": "^2.1.0",
+ "https-proxy-agent": "^2.2.1",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "node-fetch-npm": "^2.0.2",
+ "promise-retry": "^1.1.1",
+ "socks-proxy-agent": "^4.0.0",
+ "ssri": "^6.0.0"
+ },
+ "dependencies": {
+ "bluebird": {
+ "version": "3.5.5",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
+ "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==",
+ "dev": true
+ },
+ "cacache": {
+ "version": "12.0.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz",
+ "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "infer-owner": "^1.0.3",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
+ "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "mississippi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+ "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^3.0.0",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "ssri": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+ "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+ "dev": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1"
+ }
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+ "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
+ "dev": true
+ }
+ }
+ },
+ "mamacro": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz",
+ "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==",
+ "dev": true
+ },
+ "map-age-cleaner": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+ "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+ "dev": true,
+ "requires": {
+ "p-defer": "^1.0.0"
+ }
+ },
+ "map-cache": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
+ "dev": true
+ },
+ "map-visit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
+ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
+ "dev": true,
+ "requires": {
+ "object-visit": "^1.0.0"
+ }
+ },
+ "markdown-it": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
+ "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
+ "requires": {
+ "argparse": "^1.0.7",
+ "entities": "~2.0.0",
+ "linkify-it": "^2.0.0",
+ "mdurl": "^1.0.1",
+ "uc.micro": "^1.0.5"
+ }
+ },
+ "md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "dev": true,
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "mdurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+ "dev": true
+ },
+ "mem": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+ "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+ "dev": true,
+ "requires": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^2.0.0",
+ "p-is-promise": "^2.0.0"
+ }
+ },
+ "memory-fs": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
+ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=",
+ "dev": true,
+ "requires": {
+ "errno": "^0.1.3",
+ "readable-stream": "^2.0.1"
+ }
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
+ "dev": true
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.0.0",
+ "brorand": "^1.0.1"
+ }
+ },
+ "mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.33.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
+ "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.18",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
+ "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
+ "dev": true,
+ "requires": {
+ "mime-db": "~1.33.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ },
+ "mini-css-extract-plugin": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz",
+ "integrity": "sha512-MNpRGbNA52q6U92i0qbVpQNsgk7LExy41MdAlG84FeytfDOtRIf/mCHdEgG8rpTKOaNKiqUnZdlptF469hxqOw==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "normalize-url": "1.9.1",
+ "schema-utils": "^1.0.0",
+ "webpack-sources": "^1.1.0"
+ }
+ },
+ "minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ },
+ "minipass": {
+ "version": "2.6.5",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.6.5.tgz",
+ "integrity": "sha512-ewSKOPFH9blOLXx0YSE+mbrNMBFPS+11a2b03QZ+P4LVrUHW/GAlqeYC7DBknDyMWkHzrzTpDhUvy7MUxqyrPA==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ },
+ "dependencies": {
+ "yallist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+ "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
+ "dev": true
+ }
+ }
+ },
+ "minizlib": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.2.tgz",
+ "integrity": "sha512-hR3At21uSrsjjDTWrbu0IMLTpnkpv8IIMFDFaoz43Tmu4LkmAXfH44vNNzpTnf+OAQQCHrb91y/wc2J4x5XgSQ==",
+ "dev": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "mississippi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+ "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^3.0.0",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ },
+ "dependencies": {
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ }
+ }
+ },
+ "mixin-deep": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz",
+ "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==",
+ "dev": true,
+ "requires": {
+ "for-in": "^1.0.2",
+ "is-extendable": "^1.0.1"
+ },
+ "dependencies": {
+ "is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
+ "requires": {
+ "is-plain-object": "^2.0.4"
+ }
+ }
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "moment": {
+ "version": "2.24.0",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
+ "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
+ },
+ "moment-timezone": {
+ "version": "0.5.26",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.26.tgz",
+ "integrity": "sha512-sFP4cgEKTCymBBKgoxZjYzlSovC20Y6J7y3nanDc5RoBIXKlZhoYwBoZGe3flwU6A372AcRwScH8KiwV6zjy1g==",
+ "requires": {
+ "moment": ">= 2.9.0"
+ }
+ },
+ "move-concurrently": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
+ "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.1.1",
+ "copy-concurrently": "^1.0.0",
+ "fs-write-stream-atomic": "^1.0.8",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.3"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "msal": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/msal/-/msal-0.2.2.tgz",
+ "integrity": "sha512-a/3b5HYaJYEebTSI+r+tpIwF9rX6XgTS7mWxaOrMYyg+Szz8SevYd/aHR5c0R63dQkM6/SK3hJ+i1GaGkDVdSA==",
+ "requires": {
+ "tslib": "1.7.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.7.1.tgz",
+ "integrity": "sha1-vIAEFkaRkjp5/oN4u+s9ogF1OOw="
+ }
+ }
+ },
+ "msteams-ui-icons-core": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/msteams-ui-icons-core/-/msteams-ui-icons-core-0.4.2.tgz",
+ "integrity": "sha512-jaHadyxAuSwvopQjcMSjlkVB1B2z4Ln5XE683d0unfDtrlL9jSczHRfCQoSVHE4khjtBG/4HU92zf+SbmUGzkQ==",
+ "requires": {
+ "lodash.memoize": "^4.1.2"
+ }
+ },
+ "msteams-ui-styles-core": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/msteams-ui-styles-core/-/msteams-ui-styles-core-0.8.2.tgz",
+ "integrity": "sha512-no6iryXptjFtPJSFqy0q/cYQ0iwwJQXVawvWL8/5M322pIVECazrlM8kN9Fb/wFVKzaRNPnccjPmn641lZgXHA==",
+ "requires": {
+ "msteams-ui-icons-core": "^0.4.2"
+ }
+ },
+ "multicast-dns": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
+ "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
+ "dev": true,
+ "requires": {
+ "dns-packet": "^1.3.1",
+ "thunky": "^1.0.2"
+ }
+ },
+ "multicast-dns-service-types": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
+ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
+ "dev": true
+ },
+ "mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.14.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
+ "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
+ "dev": true,
+ "optional": true
+ },
+ "nanomatch": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
+ "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
+ "dev": true,
+ "requires": {
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "fragment-cache": "^0.2.1",
+ "is-windows": "^1.0.2",
+ "kind-of": "^6.0.2",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ }
+ },
+ "negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
+ "dev": true
+ },
+ "neo-async": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
+ "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
+ "dev": true
+ },
+ "ng4-loading-spinner": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/ng4-loading-spinner/-/ng4-loading-spinner-1.2.3.tgz",
+ "integrity": "sha512-AxokaWmIMSv4YeZcwzSCs0f1PBnn/lgOVpaXuR5PdnNqGkpDema6b2KwONLtdzmL5YqKOpQo8DoyTRhlzGoohQ=="
+ },
+ "nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
+ "dev": true
+ },
+ "node-fetch-npm": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz",
+ "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==",
+ "dev": true,
+ "requires": {
+ "encoding": "^0.1.11",
+ "json-parse-better-errors": "^1.0.0",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node-forge": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.8.2.tgz",
+ "integrity": "sha512-mXQ9GBq1N3uDCyV1pdSzgIguwgtVpM7f5/5J4ipz12PKWElmPpVWLDuWl8iXmhysr21+WmX/OJ5UKx82wjomgg==",
+ "dev": true
+ },
+ "node-libs-browser": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz",
+ "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==",
+ "dev": true,
+ "requires": {
+ "assert": "^1.1.1",
+ "browserify-zlib": "^0.2.0",
+ "buffer": "^4.3.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "^1.0.0",
+ "crypto-browserify": "^3.11.0",
+ "domain-browser": "^1.1.1",
+ "events": "^3.0.0",
+ "https-browserify": "^1.0.0",
+ "os-browserify": "^0.3.0",
+ "path-browserify": "0.0.1",
+ "process": "^0.11.10",
+ "punycode": "^1.2.4",
+ "querystring-es3": "^0.2.0",
+ "readable-stream": "^2.3.3",
+ "stream-browserify": "^2.0.1",
+ "stream-http": "^2.7.2",
+ "string_decoder": "^1.0.0",
+ "timers-browserify": "^2.0.4",
+ "tty-browserify": "0.0.0",
+ "url": "^0.11.0",
+ "util": "^0.11.0",
+ "vm-browserify": "^1.0.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ }
+ }
+ },
+ "node-releases": {
+ "version": "1.1.32",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.32.tgz",
+ "integrity": "sha512-VhVknkitq8dqtWoluagsGPn3dxTvN9fwgR59fV3D7sLBHe0JfDramsMI8n8mY//ccq/Kkrf8ZRHRpsyVZ3qw1A==",
+ "dev": true,
+ "requires": {
+ "semver": "^5.3.0"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "is-builtin-module": "^1.0.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true,
+ "requires": {
+ "remove-trailing-separator": "^1.0.1"
+ }
+ },
+ "normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
+ "dev": true
+ },
+ "normalize-url": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz",
+ "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=",
+ "dev": true,
+ "requires": {
+ "object-assign": "^4.0.1",
+ "prepend-http": "^1.0.0",
+ "query-string": "^4.1.0",
+ "sort-keys": "^1.0.0"
+ }
+ },
+ "npm": {
+ "version": "6.11.3",
+ "resolved": "https://registry.npmjs.org/npm/-/npm-6.11.3.tgz",
+ "integrity": "sha512-K2h+MPzZiY39Xf6eHEdECe/LKoJXam4UCflz5kIxoskN3LQFeYs5fqBGT5i4TtM/aBk+86Mcf+jgXs/WuWAutQ==",
+ "requires": {
+ "JSONStream": "^1.3.5",
+ "abbrev": "~1.1.1",
+ "ansicolors": "~0.3.2",
+ "ansistyles": "~0.1.3",
+ "aproba": "^2.0.0",
+ "archy": "~1.0.0",
+ "bin-links": "^1.1.3",
+ "bluebird": "^3.5.5",
+ "byte-size": "^5.0.1",
+ "cacache": "^12.0.3",
+ "call-limit": "^1.1.1",
+ "chownr": "^1.1.2",
+ "ci-info": "^2.0.0",
+ "cli-columns": "^3.1.2",
+ "cli-table3": "^0.5.1",
+ "cmd-shim": "^3.0.3",
+ "columnify": "~1.5.4",
+ "config-chain": "^1.1.12",
+ "debuglog": "*",
+ "detect-indent": "~5.0.0",
+ "detect-newline": "^2.1.0",
+ "dezalgo": "~1.0.3",
+ "editor": "~1.0.0",
+ "figgy-pudding": "^3.5.1",
+ "find-npm-prefix": "^1.0.2",
+ "fs-vacuum": "~1.2.10",
+ "fs-write-stream-atomic": "~1.0.10",
+ "gentle-fs": "^2.2.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.2",
+ "has-unicode": "~2.0.1",
+ "hosted-git-info": "^2.8.2",
+ "iferr": "^1.0.2",
+ "imurmurhash": "*",
+ "infer-owner": "^1.0.4",
+ "inflight": "~1.0.6",
+ "inherits": "^2.0.4",
+ "ini": "^1.3.5",
+ "init-package-json": "^1.10.3",
+ "is-cidr": "^3.0.0",
+ "json-parse-better-errors": "^1.0.2",
+ "lazy-property": "~1.0.0",
+ "libcipm": "^4.0.3",
+ "libnpm": "^3.0.1",
+ "libnpmaccess": "^3.0.2",
+ "libnpmhook": "^5.0.3",
+ "libnpmorg": "^1.0.1",
+ "libnpmsearch": "^2.0.2",
+ "libnpmteam": "^1.0.2",
+ "libnpx": "^10.2.0",
+ "lock-verify": "^2.1.0",
+ "lockfile": "^1.0.4",
+ "lodash._baseindexof": "*",
+ "lodash._baseuniq": "~4.6.0",
+ "lodash._bindcallback": "*",
+ "lodash._cacheindexof": "*",
+ "lodash._createcache": "*",
+ "lodash._getnative": "*",
+ "lodash.clonedeep": "~4.5.0",
+ "lodash.restparam": "*",
+ "lodash.union": "~4.6.0",
+ "lodash.uniq": "~4.5.0",
+ "lodash.without": "~4.4.0",
+ "lru-cache": "^5.1.1",
+ "meant": "~1.0.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "~0.5.1",
+ "move-concurrently": "^1.0.1",
+ "node-gyp": "^5.0.3",
+ "nopt": "~4.0.1",
+ "normalize-package-data": "^2.5.0",
+ "npm-audit-report": "^1.3.2",
+ "npm-cache-filename": "~1.0.2",
+ "npm-install-checks": "~3.0.0",
+ "npm-lifecycle": "^3.1.3",
+ "npm-package-arg": "^6.1.1",
+ "npm-packlist": "^1.4.4",
+ "npm-pick-manifest": "^3.0.2",
+ "npm-profile": "^4.0.2",
+ "npm-registry-fetch": "^4.0.0",
+ "npm-user-validate": "~1.0.0",
+ "npmlog": "~4.1.2",
+ "once": "~1.4.0",
+ "opener": "^1.5.1",
+ "osenv": "^0.1.5",
+ "pacote": "^9.5.8",
+ "path-is-inside": "~1.0.2",
+ "promise-inflight": "~1.0.1",
+ "qrcode-terminal": "^0.12.0",
+ "query-string": "^6.8.2",
+ "qw": "~1.0.1",
+ "read": "~1.0.7",
+ "read-cmd-shim": "^1.0.4",
+ "read-installed": "~4.0.3",
+ "read-package-json": "^2.1.0",
+ "read-package-tree": "^5.3.1",
+ "readable-stream": "^3.4.0",
+ "readdir-scoped-modules": "^1.1.0",
+ "request": "^2.88.0",
+ "retry": "^0.12.0",
+ "rimraf": "^2.6.3",
+ "safe-buffer": "^5.1.2",
+ "semver": "^5.7.1",
+ "sha": "^3.0.0",
+ "slide": "~1.1.6",
+ "sorted-object": "~2.0.1",
+ "sorted-union-stream": "~2.1.3",
+ "ssri": "^6.0.1",
+ "stringify-package": "^1.0.0",
+ "tar": "^4.4.10",
+ "text-table": "~0.2.0",
+ "tiny-relative-date": "^1.3.0",
+ "uid-number": "0.0.6",
+ "umask": "~1.1.0",
+ "unique-filename": "^1.1.1",
+ "unpipe": "~1.0.0",
+ "update-notifier": "^2.5.0",
+ "uuid": "^3.3.2",
+ "validate-npm-package-license": "^3.0.4",
+ "validate-npm-package-name": "~3.0.0",
+ "which": "^1.3.1",
+ "worker-farm": "^1.7.0",
+ "write-file-atomic": "^2.4.3"
+ },
+ "dependencies": {
+ "JSONStream": {
+ "version": "1.3.5",
+ "bundled": true,
+ "requires": {
+ "jsonparse": "^1.2.0",
+ "through": ">=2.2.7 <3"
+ }
+ },
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true
+ },
+ "agent-base": {
+ "version": "4.3.0",
+ "bundled": true,
+ "requires": {
+ "es6-promisify": "^5.0.0"
+ }
+ },
+ "agentkeepalive": {
+ "version": "3.5.2",
+ "bundled": true,
+ "requires": {
+ "humanize-ms": "^1.2.1"
+ }
+ },
+ "ajv": {
+ "version": "5.5.2",
+ "bundled": true,
+ "requires": {
+ "co": "^4.6.0",
+ "fast-deep-equal": "^1.0.0",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.3.0"
+ }
+ },
+ "ansi-align": {
+ "version": "2.0.0",
+ "bundled": true,
+ "requires": {
+ "string-width": "^2.0.0"
+ }
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "bundled": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "ansicolors": {
+ "version": "0.3.2",
+ "bundled": true
+ },
+ "ansistyles": {
+ "version": "0.1.3",
+ "bundled": true
+ },
+ "aproba": {
+ "version": "2.0.0",
+ "bundled": true
+ },
+ "archy": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "bundled": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ }
+ }
+ },
+ "asap": {
+ "version": "2.0.6",
+ "bundled": true
+ },
+ "asn1": {
+ "version": "0.2.4",
+ "bundled": true,
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "bundled": true
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "bundled": true
+ },
+ "aws4": {
+ "version": "1.8.0",
+ "bundled": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "bin-links": {
+ "version": "1.1.3",
+ "bundled": true,
+ "requires": {
+ "bluebird": "^3.5.3",
+ "cmd-shim": "^3.0.0",
+ "gentle-fs": "^2.0.1",
+ "graceful-fs": "^4.1.15",
+ "write-file-atomic": "^2.3.0"
+ }
+ },
+ "bluebird": {
+ "version": "3.5.5",
+ "bundled": true
+ },
+ "boxen": {
+ "version": "1.3.0",
+ "bundled": true,
+ "requires": {
+ "ansi-align": "^2.0.0",
+ "camelcase": "^4.0.0",
+ "chalk": "^2.0.1",
+ "cli-boxes": "^1.0.0",
+ "string-width": "^2.0.0",
+ "term-size": "^1.2.0",
+ "widest-line": "^2.0.0"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "buffer-from": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "builtins": {
+ "version": "1.0.3",
+ "bundled": true
+ },
+ "byline": {
+ "version": "5.0.0",
+ "bundled": true
+ },
+ "byte-size": {
+ "version": "5.0.1",
+ "bundled": true
+ },
+ "cacache": {
+ "version": "12.0.3",
+ "bundled": true,
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "infer-owner": "^1.0.3",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ }
+ },
+ "call-limit": {
+ "version": "1.1.1",
+ "bundled": true
+ },
+ "camelcase": {
+ "version": "4.1.0",
+ "bundled": true
+ },
+ "capture-stack-trace": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "bundled": true
+ },
+ "chalk": {
+ "version": "2.4.1",
+ "bundled": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "chownr": {
+ "version": "1.1.2",
+ "bundled": true
+ },
+ "ci-info": {
+ "version": "2.0.0",
+ "bundled": true
+ },
+ "cidr-regex": {
+ "version": "2.0.10",
+ "bundled": true,
+ "requires": {
+ "ip-regex": "^2.1.0"
+ }
+ },
+ "cli-boxes": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "cli-columns": {
+ "version": "3.1.2",
+ "bundled": true,
+ "requires": {
+ "string-width": "^2.0.0",
+ "strip-ansi": "^3.0.1"
+ }
+ },
+ "cli-table3": {
+ "version": "0.5.1",
+ "bundled": true,
+ "requires": {
+ "colors": "^1.1.2",
+ "object-assign": "^4.1.0",
+ "string-width": "^2.1.1"
+ }
+ },
+ "cliui": {
+ "version": "4.1.0",
+ "bundled": true,
+ "requires": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "bundled": true
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "bundled": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "clone": {
+ "version": "1.0.4",
+ "bundled": true
+ },
+ "cmd-shim": {
+ "version": "3.0.3",
+ "bundled": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "mkdirp": "~0.5.0"
+ }
+ },
+ "co": {
+ "version": "4.6.0",
+ "bundled": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "color-convert": {
+ "version": "1.9.1",
+ "bundled": true,
+ "requires": {
+ "color-name": "^1.1.1"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "bundled": true
+ },
+ "colors": {
+ "version": "1.3.3",
+ "bundled": true,
+ "optional": true
+ },
+ "columnify": {
+ "version": "1.5.4",
+ "bundled": true,
+ "requires": {
+ "strip-ansi": "^3.0.0",
+ "wcwidth": "^1.0.0"
+ }
+ },
+ "combined-stream": {
+ "version": "1.0.6",
+ "bundled": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true
+ },
+ "concat-stream": {
+ "version": "1.6.2",
+ "bundled": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ }
+ }
+ },
+ "config-chain": {
+ "version": "1.1.12",
+ "bundled": true,
+ "requires": {
+ "ini": "^1.3.4",
+ "proto-list": "~1.2.1"
+ }
+ },
+ "configstore": {
+ "version": "3.1.2",
+ "bundled": true,
+ "requires": {
+ "dot-prop": "^4.1.0",
+ "graceful-fs": "^4.1.2",
+ "make-dir": "^1.0.0",
+ "unique-string": "^1.0.0",
+ "write-file-atomic": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ }
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "copy-concurrently": {
+ "version": "1.0.5",
+ "bundled": true,
+ "requires": {
+ "aproba": "^1.1.1",
+ "fs-write-stream-atomic": "^1.0.8",
+ "iferr": "^0.1.5",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.0"
+ },
+ "dependencies": {
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true
+ },
+ "iferr": {
+ "version": "0.1.5",
+ "bundled": true
+ }
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "create-error-class": {
+ "version": "3.0.2",
+ "bundled": true,
+ "requires": {
+ "capture-stack-trace": "^1.0.0"
+ }
+ },
+ "cross-spawn": {
+ "version": "5.1.0",
+ "bundled": true,
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "4.1.5",
+ "bundled": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "bundled": true
+ }
+ }
+ },
+ "crypto-random-string": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "cyclist": {
+ "version": "0.2.2",
+ "bundled": true
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "bundled": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "debug": {
+ "version": "3.1.0",
+ "bundled": true,
+ "requires": {
+ "ms": "2.0.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.0.0",
+ "bundled": true
+ }
+ }
+ },
+ "debuglog": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "bundled": true
+ },
+ "decode-uri-component": {
+ "version": "0.2.0",
+ "bundled": true
+ },
+ "deep-extend": {
+ "version": "0.5.1",
+ "bundled": true
+ },
+ "defaults": {
+ "version": "1.0.3",
+ "bundled": true,
+ "requires": {
+ "clone": "^1.0.2"
+ }
+ },
+ "define-properties": {
+ "version": "1.1.3",
+ "bundled": true,
+ "requires": {
+ "object-keys": "^1.0.12"
+ }
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "detect-indent": {
+ "version": "5.0.0",
+ "bundled": true
+ },
+ "detect-newline": {
+ "version": "2.1.0",
+ "bundled": true
+ },
+ "dezalgo": {
+ "version": "1.0.3",
+ "bundled": true,
+ "requires": {
+ "asap": "^2.0.0",
+ "wrappy": "1"
+ }
+ },
+ "dot-prop": {
+ "version": "4.2.0",
+ "bundled": true,
+ "requires": {
+ "is-obj": "^1.0.0"
+ }
+ },
+ "dotenv": {
+ "version": "5.0.1",
+ "bundled": true
+ },
+ "duplexer3": {
+ "version": "0.1.4",
+ "bundled": true
+ },
+ "duplexify": {
+ "version": "3.6.0",
+ "bundled": true,
+ "requires": {
+ "end-of-stream": "^1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ }
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "editor": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "encoding": {
+ "version": "0.1.12",
+ "bundled": true,
+ "requires": {
+ "iconv-lite": "~0.4.13"
+ }
+ },
+ "end-of-stream": {
+ "version": "1.4.1",
+ "bundled": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "env-paths": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "err-code": {
+ "version": "1.1.2",
+ "bundled": true
+ },
+ "errno": {
+ "version": "0.1.7",
+ "bundled": true,
+ "requires": {
+ "prr": "~1.0.1"
+ }
+ },
+ "es-abstract": {
+ "version": "1.12.0",
+ "bundled": true,
+ "requires": {
+ "es-to-primitive": "^1.1.1",
+ "function-bind": "^1.1.1",
+ "has": "^1.0.1",
+ "is-callable": "^1.1.3",
+ "is-regex": "^1.0.4"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.0",
+ "bundled": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "es6-promise": {
+ "version": "4.2.8",
+ "bundled": true
+ },
+ "es6-promisify": {
+ "version": "5.0.0",
+ "bundled": true,
+ "requires": {
+ "es6-promise": "^4.0.3"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "bundled": true
+ },
+ "execa": {
+ "version": "0.7.0",
+ "bundled": true,
+ "requires": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "3.0.0",
+ "bundled": true
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "bundled": true
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "bundled": true
+ },
+ "fast-deep-equal": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.0.0",
+ "bundled": true
+ },
+ "figgy-pudding": {
+ "version": "3.5.1",
+ "bundled": true
+ },
+ "find-npm-prefix": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "find-up": {
+ "version": "2.1.0",
+ "bundled": true,
+ "requires": {
+ "locate-path": "^2.0.0"
+ }
+ },
+ "flush-write-stream": {
+ "version": "1.0.3",
+ "bundled": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.4"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ }
+ }
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "bundled": true
+ },
+ "form-data": {
+ "version": "2.3.2",
+ "bundled": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "from2": {
+ "version": "2.3.0",
+ "bundled": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ }
+ }
+ },
+ "fs-minipass": {
+ "version": "1.2.6",
+ "bundled": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "fs-vacuum": {
+ "version": "1.2.10",
+ "bundled": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "path-is-inside": "^1.0.1",
+ "rimraf": "^2.5.2"
+ }
+ },
+ "fs-write-stream-atomic": {
+ "version": "1.0.10",
+ "bundled": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "iferr": "^0.1.5",
+ "imurmurhash": "^0.1.4",
+ "readable-stream": "1 || 2"
+ },
+ "dependencies": {
+ "iferr": {
+ "version": "0.1.5",
+ "bundled": true
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ }
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "bundled": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ },
+ "dependencies": {
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ }
+ }
+ },
+ "genfun": {
+ "version": "5.0.0",
+ "bundled": true
+ },
+ "gentle-fs": {
+ "version": "2.2.1",
+ "bundled": true,
+ "requires": {
+ "aproba": "^1.1.2",
+ "chownr": "^1.1.2",
+ "fs-vacuum": "^1.2.10",
+ "graceful-fs": "^4.1.11",
+ "iferr": "^0.1.5",
+ "infer-owner": "^1.0.4",
+ "mkdirp": "^0.5.1",
+ "path-is-inside": "^1.0.2",
+ "read-cmd-shim": "^1.0.1",
+ "slide": "^1.1.6"
+ },
+ "dependencies": {
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true
+ },
+ "iferr": {
+ "version": "0.1.5",
+ "bundled": true
+ }
+ }
+ },
+ "get-caller-file": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "get-stream": {
+ "version": "4.1.0",
+ "bundled": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "bundled": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.4",
+ "bundled": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "global-dirs": {
+ "version": "0.1.1",
+ "bundled": true,
+ "requires": {
+ "ini": "^1.3.4"
+ }
+ },
+ "got": {
+ "version": "6.7.1",
+ "bundled": true,
+ "requires": {
+ "create-error-class": "^3.0.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^3.0.0",
+ "is-redirect": "^1.0.0",
+ "is-retry-allowed": "^1.0.0",
+ "is-stream": "^1.0.0",
+ "lowercase-keys": "^1.0.0",
+ "safe-buffer": "^5.0.1",
+ "timed-out": "^4.0.0",
+ "unzip-response": "^2.0.1",
+ "url-parse-lax": "^1.0.0"
+ },
+ "dependencies": {
+ "get-stream": {
+ "version": "3.0.0",
+ "bundled": true
+ }
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.2",
+ "bundled": true
+ },
+ "har-schema": {
+ "version": "2.0.0",
+ "bundled": true
+ },
+ "har-validator": {
+ "version": "5.1.0",
+ "bundled": true,
+ "requires": {
+ "ajv": "^5.3.0",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "has": {
+ "version": "1.0.3",
+ "bundled": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "bundled": true
+ },
+ "has-symbols": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true
+ },
+ "hosted-git-info": {
+ "version": "2.8.2",
+ "bundled": true,
+ "requires": {
+ "lru-cache": "^5.1.1"
+ }
+ },
+ "http-cache-semantics": {
+ "version": "3.8.1",
+ "bundled": true
+ },
+ "http-proxy-agent": {
+ "version": "2.1.0",
+ "bundled": true,
+ "requires": {
+ "agent-base": "4",
+ "debug": "3.1.0"
+ }
+ },
+ "http-signature": {
+ "version": "1.2.0",
+ "bundled": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ }
+ },
+ "https-proxy-agent": {
+ "version": "2.2.2",
+ "bundled": true,
+ "requires": {
+ "agent-base": "^4.3.0",
+ "debug": "^3.1.0"
+ }
+ },
+ "humanize-ms": {
+ "version": "1.2.1",
+ "bundled": true,
+ "requires": {
+ "ms": "^2.0.0"
+ }
+ },
+ "iconv-lite": {
+ "version": "0.4.23",
+ "bundled": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "iferr": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "ignore-walk": {
+ "version": "3.0.1",
+ "bundled": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "import-lazy": {
+ "version": "2.1.0",
+ "bundled": true
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "bundled": true
+ },
+ "infer-owner": {
+ "version": "1.0.4",
+ "bundled": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "bundled": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true
+ },
+ "init-package-json": {
+ "version": "1.10.3",
+ "bundled": true,
+ "requires": {
+ "glob": "^7.1.1",
+ "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0",
+ "promzard": "^0.3.0",
+ "read": "~1.0.1",
+ "read-package-json": "1 || 2",
+ "semver": "2.x || 3.x || 4 || 5",
+ "validate-npm-package-license": "^3.0.1",
+ "validate-npm-package-name": "^3.0.0"
+ }
+ },
+ "invert-kv": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "ip": {
+ "version": "1.1.5",
+ "bundled": true
+ },
+ "ip-regex": {
+ "version": "2.1.0",
+ "bundled": true
+ },
+ "is-callable": {
+ "version": "1.1.4",
+ "bundled": true
+ },
+ "is-ci": {
+ "version": "1.1.0",
+ "bundled": true,
+ "requires": {
+ "ci-info": "^1.0.0"
+ },
+ "dependencies": {
+ "ci-info": {
+ "version": "1.6.0",
+ "bundled": true
+ }
+ }
+ },
+ "is-cidr": {
+ "version": "3.0.0",
+ "bundled": true,
+ "requires": {
+ "cidr-regex": "^2.0.10"
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "is-installed-globally": {
+ "version": "0.1.0",
+ "bundled": true,
+ "requires": {
+ "global-dirs": "^0.1.0",
+ "is-path-inside": "^1.0.0"
+ }
+ },
+ "is-npm": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "is-obj": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "is-path-inside": {
+ "version": "1.0.1",
+ "bundled": true,
+ "requires": {
+ "path-is-inside": "^1.0.1"
+ }
+ },
+ "is-redirect": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "is-regex": {
+ "version": "1.0.4",
+ "bundled": true,
+ "requires": {
+ "has": "^1.0.1"
+ }
+ },
+ "is-retry-allowed": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "is-symbol": {
+ "version": "1.0.2",
+ "bundled": true,
+ "requires": {
+ "has-symbols": "^1.0.0"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "bundled": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "bundled": true
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "bundled": true
+ },
+ "json-schema-traverse": {
+ "version": "0.3.1",
+ "bundled": true
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "bundled": true
+ },
+ "jsonparse": {
+ "version": "1.3.1",
+ "bundled": true
+ },
+ "jsprim": {
+ "version": "1.4.1",
+ "bundled": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.2.3",
+ "verror": "1.10.0"
+ }
+ },
+ "latest-version": {
+ "version": "3.1.0",
+ "bundled": true,
+ "requires": {
+ "package-json": "^4.0.0"
+ }
+ },
+ "lazy-property": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "lcid": {
+ "version": "1.0.0",
+ "bundled": true,
+ "requires": {
+ "invert-kv": "^1.0.0"
+ }
+ },
+ "libcipm": {
+ "version": "4.0.3",
+ "bundled": true,
+ "requires": {
+ "bin-links": "^1.1.2",
+ "bluebird": "^3.5.1",
+ "figgy-pudding": "^3.5.1",
+ "find-npm-prefix": "^1.0.2",
+ "graceful-fs": "^4.1.11",
+ "ini": "^1.3.5",
+ "lock-verify": "^2.0.2",
+ "mkdirp": "^0.5.1",
+ "npm-lifecycle": "^3.0.0",
+ "npm-logical-tree": "^1.2.1",
+ "npm-package-arg": "^6.1.0",
+ "pacote": "^9.1.0",
+ "read-package-json": "^2.0.13",
+ "rimraf": "^2.6.2",
+ "worker-farm": "^1.6.0"
+ }
+ },
+ "libnpm": {
+ "version": "3.0.1",
+ "bundled": true,
+ "requires": {
+ "bin-links": "^1.1.2",
+ "bluebird": "^3.5.3",
+ "find-npm-prefix": "^1.0.2",
+ "libnpmaccess": "^3.0.2",
+ "libnpmconfig": "^1.2.1",
+ "libnpmhook": "^5.0.3",
+ "libnpmorg": "^1.0.1",
+ "libnpmpublish": "^1.1.2",
+ "libnpmsearch": "^2.0.2",
+ "libnpmteam": "^1.0.2",
+ "lock-verify": "^2.0.2",
+ "npm-lifecycle": "^3.0.0",
+ "npm-logical-tree": "^1.2.1",
+ "npm-package-arg": "^6.1.0",
+ "npm-profile": "^4.0.2",
+ "npm-registry-fetch": "^4.0.0",
+ "npmlog": "^4.1.2",
+ "pacote": "^9.5.3",
+ "read-package-json": "^2.0.13",
+ "stringify-package": "^1.0.0"
+ }
+ },
+ "libnpmaccess": {
+ "version": "3.0.2",
+ "bundled": true,
+ "requires": {
+ "aproba": "^2.0.0",
+ "get-stream": "^4.0.0",
+ "npm-package-arg": "^6.1.0",
+ "npm-registry-fetch": "^4.0.0"
+ }
+ },
+ "libnpmconfig": {
+ "version": "1.2.1",
+ "bundled": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1",
+ "find-up": "^3.0.0",
+ "ini": "^1.3.5"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "3.0.0",
+ "bundled": true,
+ "requires": {
+ "locate-path": "^3.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "3.0.0",
+ "bundled": true,
+ "requires": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.2.0",
+ "bundled": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "bundled": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "bundled": true
+ }
+ }
+ },
+ "libnpmhook": {
+ "version": "5.0.3",
+ "bundled": true,
+ "requires": {
+ "aproba": "^2.0.0",
+ "figgy-pudding": "^3.4.1",
+ "get-stream": "^4.0.0",
+ "npm-registry-fetch": "^4.0.0"
+ }
+ },
+ "libnpmorg": {
+ "version": "1.0.1",
+ "bundled": true,
+ "requires": {
+ "aproba": "^2.0.0",
+ "figgy-pudding": "^3.4.1",
+ "get-stream": "^4.0.0",
+ "npm-registry-fetch": "^4.0.0"
+ }
+ },
+ "libnpmpublish": {
+ "version": "1.1.2",
+ "bundled": true,
+ "requires": {
+ "aproba": "^2.0.0",
+ "figgy-pudding": "^3.5.1",
+ "get-stream": "^4.0.0",
+ "lodash.clonedeep": "^4.5.0",
+ "normalize-package-data": "^2.4.0",
+ "npm-package-arg": "^6.1.0",
+ "npm-registry-fetch": "^4.0.0",
+ "semver": "^5.5.1",
+ "ssri": "^6.0.1"
+ }
+ },
+ "libnpmsearch": {
+ "version": "2.0.2",
+ "bundled": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1",
+ "get-stream": "^4.0.0",
+ "npm-registry-fetch": "^4.0.0"
+ }
+ },
+ "libnpmteam": {
+ "version": "1.0.2",
+ "bundled": true,
+ "requires": {
+ "aproba": "^2.0.0",
+ "figgy-pudding": "^3.4.1",
+ "get-stream": "^4.0.0",
+ "npm-registry-fetch": "^4.0.0"
+ }
+ },
+ "libnpx": {
+ "version": "10.2.0",
+ "bundled": true,
+ "requires": {
+ "dotenv": "^5.0.1",
+ "npm-package-arg": "^6.0.0",
+ "rimraf": "^2.6.2",
+ "safe-buffer": "^5.1.0",
+ "update-notifier": "^2.3.0",
+ "which": "^1.3.0",
+ "y18n": "^4.0.0",
+ "yargs": "^11.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "2.0.0",
+ "bundled": true,
+ "requires": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ }
+ },
+ "lock-verify": {
+ "version": "2.1.0",
+ "bundled": true,
+ "requires": {
+ "npm-package-arg": "^6.1.0",
+ "semver": "^5.4.1"
+ }
+ },
+ "lockfile": {
+ "version": "1.0.4",
+ "bundled": true,
+ "requires": {
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "lodash._baseindexof": {
+ "version": "3.1.0",
+ "bundled": true
+ },
+ "lodash._baseuniq": {
+ "version": "4.6.0",
+ "bundled": true,
+ "requires": {
+ "lodash._createset": "~4.0.0",
+ "lodash._root": "~3.0.0"
+ }
+ },
+ "lodash._bindcallback": {
+ "version": "3.0.1",
+ "bundled": true
+ },
+ "lodash._cacheindexof": {
+ "version": "3.0.2",
+ "bundled": true
+ },
+ "lodash._createcache": {
+ "version": "3.1.2",
+ "bundled": true,
+ "requires": {
+ "lodash._getnative": "^3.0.0"
+ }
+ },
+ "lodash._createset": {
+ "version": "4.0.3",
+ "bundled": true
+ },
+ "lodash._getnative": {
+ "version": "3.9.1",
+ "bundled": true
+ },
+ "lodash._root": {
+ "version": "3.0.1",
+ "bundled": true
+ },
+ "lodash.clonedeep": {
+ "version": "4.5.0",
+ "bundled": true
+ },
+ "lodash.restparam": {
+ "version": "3.6.1",
+ "bundled": true
+ },
+ "lodash.union": {
+ "version": "4.6.0",
+ "bundled": true
+ },
+ "lodash.uniq": {
+ "version": "4.5.0",
+ "bundled": true
+ },
+ "lodash.without": {
+ "version": "4.4.0",
+ "bundled": true
+ },
+ "lowercase-keys": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "bundled": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "make-dir": {
+ "version": "1.3.0",
+ "bundled": true,
+ "requires": {
+ "pify": "^3.0.0"
+ }
+ },
+ "make-fetch-happen": {
+ "version": "5.0.0",
+ "bundled": true,
+ "requires": {
+ "agentkeepalive": "^3.4.1",
+ "cacache": "^12.0.0",
+ "http-cache-semantics": "^3.8.1",
+ "http-proxy-agent": "^2.1.0",
+ "https-proxy-agent": "^2.2.1",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "node-fetch-npm": "^2.0.2",
+ "promise-retry": "^1.1.1",
+ "socks-proxy-agent": "^4.0.0",
+ "ssri": "^6.0.0"
+ }
+ },
+ "meant": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "mem": {
+ "version": "1.1.0",
+ "bundled": true,
+ "requires": {
+ "mimic-fn": "^1.0.0"
+ }
+ },
+ "mime-db": {
+ "version": "1.35.0",
+ "bundled": true
+ },
+ "mime-types": {
+ "version": "2.1.19",
+ "bundled": true,
+ "requires": {
+ "mime-db": "~1.35.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "1.2.0",
+ "bundled": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true
+ },
+ "minipass": {
+ "version": "2.3.3",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ },
+ "dependencies": {
+ "yallist": {
+ "version": "3.0.2",
+ "bundled": true
+ }
+ }
+ },
+ "minizlib": {
+ "version": "1.2.1",
+ "bundled": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "mississippi": {
+ "version": "3.0.0",
+ "bundled": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^3.0.0",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "move-concurrently": {
+ "version": "1.0.1",
+ "bundled": true,
+ "requires": {
+ "aproba": "^1.1.1",
+ "copy-concurrently": "^1.0.0",
+ "fs-write-stream-atomic": "^1.0.8",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.3"
+ },
+ "dependencies": {
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true
+ }
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "bundled": true
+ },
+ "mute-stream": {
+ "version": "0.0.7",
+ "bundled": true
+ },
+ "node-fetch-npm": {
+ "version": "2.0.2",
+ "bundled": true,
+ "requires": {
+ "encoding": "^0.1.11",
+ "json-parse-better-errors": "^1.0.0",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node-gyp": {
+ "version": "5.0.3",
+ "bundled": true,
+ "requires": {
+ "env-paths": "^1.0.0",
+ "glob": "^7.0.3",
+ "graceful-fs": "^4.1.2",
+ "mkdirp": "^0.5.0",
+ "nopt": "2 || 3",
+ "npmlog": "0 || 1 || 2 || 3 || 4",
+ "request": "^2.87.0",
+ "rimraf": "2",
+ "semver": "~5.3.0",
+ "tar": "^4.4.8",
+ "which": "1"
+ },
+ "dependencies": {
+ "nopt": {
+ "version": "3.0.6",
+ "bundled": true,
+ "requires": {
+ "abbrev": "1"
+ }
+ },
+ "semver": {
+ "version": "5.3.0",
+ "bundled": true
+ }
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "normalize-package-data": {
+ "version": "2.5.0",
+ "bundled": true,
+ "requires": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ },
+ "dependencies": {
+ "resolve": {
+ "version": "1.10.0",
+ "bundled": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ }
+ }
+ },
+ "npm-audit-report": {
+ "version": "1.3.2",
+ "bundled": true,
+ "requires": {
+ "cli-table3": "^0.5.0",
+ "console-control-strings": "^1.1.0"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.0.6",
+ "bundled": true
+ },
+ "npm-cache-filename": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "npm-install-checks": {
+ "version": "3.0.0",
+ "bundled": true,
+ "requires": {
+ "semver": "^2.3.0 || 3.x || 4 || 5"
+ }
+ },
+ "npm-lifecycle": {
+ "version": "3.1.3",
+ "bundled": true,
+ "requires": {
+ "byline": "^5.0.0",
+ "graceful-fs": "^4.1.15",
+ "node-gyp": "^5.0.2",
+ "resolve-from": "^4.0.0",
+ "slide": "^1.1.6",
+ "uid-number": "0.0.6",
+ "umask": "^1.1.0",
+ "which": "^1.3.1"
+ }
+ },
+ "npm-logical-tree": {
+ "version": "1.2.1",
+ "bundled": true
+ },
+ "npm-package-arg": {
+ "version": "6.1.1",
+ "bundled": true,
+ "requires": {
+ "hosted-git-info": "^2.7.1",
+ "osenv": "^0.1.5",
+ "semver": "^5.6.0",
+ "validate-npm-package-name": "^3.0.0"
+ }
+ },
+ "npm-packlist": {
+ "version": "1.4.4",
+ "bundled": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npm-pick-manifest": {
+ "version": "3.0.2",
+ "bundled": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1",
+ "npm-package-arg": "^6.0.0",
+ "semver": "^5.4.1"
+ }
+ },
+ "npm-profile": {
+ "version": "4.0.2",
+ "bundled": true,
+ "requires": {
+ "aproba": "^1.1.2 || 2",
+ "figgy-pudding": "^3.4.1",
+ "npm-registry-fetch": "^4.0.0"
+ }
+ },
+ "npm-registry-fetch": {
+ "version": "4.0.0",
+ "bundled": true,
+ "requires": {
+ "JSONStream": "^1.3.4",
+ "bluebird": "^3.5.1",
+ "figgy-pudding": "^3.4.1",
+ "lru-cache": "^5.1.1",
+ "make-fetch-happen": "^5.0.0",
+ "npm-package-arg": "^6.1.0"
+ }
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "bundled": true,
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "npm-user-validate": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "bundled": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true
+ },
+ "object-keys": {
+ "version": "1.0.12",
+ "bundled": true
+ },
+ "object.getownpropertydescriptors": {
+ "version": "2.0.3",
+ "bundled": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.5.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "opener": {
+ "version": "1.5.1",
+ "bundled": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "os-locale": {
+ "version": "2.1.0",
+ "bundled": true,
+ "requires": {
+ "execa": "^0.7.0",
+ "lcid": "^1.0.0",
+ "mem": "^1.1.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "p-limit": {
+ "version": "1.2.0",
+ "bundled": true,
+ "requires": {
+ "p-try": "^1.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "2.0.0",
+ "bundled": true,
+ "requires": {
+ "p-limit": "^1.1.0"
+ }
+ },
+ "p-try": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "package-json": {
+ "version": "4.0.1",
+ "bundled": true,
+ "requires": {
+ "got": "^6.7.1",
+ "registry-auth-token": "^3.0.1",
+ "registry-url": "^3.0.3",
+ "semver": "^5.1.0"
+ }
+ },
+ "pacote": {
+ "version": "9.5.8",
+ "bundled": true,
+ "requires": {
+ "bluebird": "^3.5.3",
+ "cacache": "^12.0.2",
+ "chownr": "^1.1.2",
+ "figgy-pudding": "^3.5.1",
+ "get-stream": "^4.1.0",
+ "glob": "^7.1.3",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^5.1.1",
+ "make-fetch-happen": "^5.0.0",
+ "minimatch": "^3.0.4",
+ "minipass": "^2.3.5",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "normalize-package-data": "^2.4.0",
+ "npm-package-arg": "^6.1.0",
+ "npm-packlist": "^1.1.12",
+ "npm-pick-manifest": "^3.0.0",
+ "npm-registry-fetch": "^4.0.0",
+ "osenv": "^0.1.5",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^1.1.1",
+ "protoduck": "^5.0.1",
+ "rimraf": "^2.6.2",
+ "safe-buffer": "^5.1.2",
+ "semver": "^5.6.0",
+ "ssri": "^6.0.1",
+ "tar": "^4.4.10",
+ "unique-filename": "^1.1.1",
+ "which": "^1.3.1"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "2.3.5",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ }
+ }
+ },
+ "parallel-transform": {
+ "version": "1.1.0",
+ "bundled": true,
+ "requires": {
+ "cyclist": "~0.2.2",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.1.5"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ }
+ }
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "bundled": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "bundled": true
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "bundled": true
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "bundled": true
+ },
+ "pify": {
+ "version": "3.0.0",
+ "bundled": true
+ },
+ "prepend-http": {
+ "version": "1.0.4",
+ "bundled": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "bundled": true
+ },
+ "promise-inflight": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "promise-retry": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "err-code": "^1.0.0",
+ "retry": "^0.10.0"
+ },
+ "dependencies": {
+ "retry": {
+ "version": "0.10.1",
+ "bundled": true
+ }
+ }
+ },
+ "promzard": {
+ "version": "0.3.0",
+ "bundled": true,
+ "requires": {
+ "read": "1"
+ }
+ },
+ "proto-list": {
+ "version": "1.2.4",
+ "bundled": true
+ },
+ "protoduck": {
+ "version": "5.0.1",
+ "bundled": true,
+ "requires": {
+ "genfun": "^5.0.0"
+ }
+ },
+ "prr": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "psl": {
+ "version": "1.1.29",
+ "bundled": true
+ },
+ "pump": {
+ "version": "3.0.0",
+ "bundled": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "pumpify": {
+ "version": "1.5.1",
+ "bundled": true,
+ "requires": {
+ "duplexify": "^3.6.0",
+ "inherits": "^2.0.3",
+ "pump": "^2.0.0"
+ },
+ "dependencies": {
+ "pump": {
+ "version": "2.0.1",
+ "bundled": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ }
+ }
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "bundled": true
+ },
+ "qrcode-terminal": {
+ "version": "0.12.0",
+ "bundled": true
+ },
+ "qs": {
+ "version": "6.5.2",
+ "bundled": true
+ },
+ "query-string": {
+ "version": "6.8.2",
+ "bundled": true,
+ "requires": {
+ "decode-uri-component": "^0.2.0",
+ "split-on-first": "^1.0.0",
+ "strict-uri-encode": "^2.0.0"
+ }
+ },
+ "qw": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "rc": {
+ "version": "1.2.7",
+ "bundled": true,
+ "requires": {
+ "deep-extend": "^0.5.1",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true
+ }
+ }
+ },
+ "read": {
+ "version": "1.0.7",
+ "bundled": true,
+ "requires": {
+ "mute-stream": "~0.0.4"
+ }
+ },
+ "read-cmd-shim": {
+ "version": "1.0.4",
+ "bundled": true,
+ "requires": {
+ "graceful-fs": "^4.1.2"
+ }
+ },
+ "read-installed": {
+ "version": "4.0.3",
+ "bundled": true,
+ "requires": {
+ "debuglog": "^1.0.1",
+ "graceful-fs": "^4.1.2",
+ "read-package-json": "^2.0.0",
+ "readdir-scoped-modules": "^1.0.0",
+ "semver": "2 || 3 || 4 || 5",
+ "slide": "~1.1.3",
+ "util-extend": "^1.0.1"
+ }
+ },
+ "read-package-json": {
+ "version": "2.1.0",
+ "bundled": true,
+ "requires": {
+ "glob": "^7.1.1",
+ "graceful-fs": "^4.1.2",
+ "json-parse-better-errors": "^1.0.1",
+ "normalize-package-data": "^2.0.0",
+ "slash": "^1.0.0"
+ }
+ },
+ "read-package-tree": {
+ "version": "5.3.1",
+ "bundled": true,
+ "requires": {
+ "read-package-json": "^2.0.0",
+ "readdir-scoped-modules": "^1.0.0",
+ "util-promisify": "^2.1.0"
+ }
+ },
+ "readable-stream": {
+ "version": "3.4.0",
+ "bundled": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "readdir-scoped-modules": {
+ "version": "1.1.0",
+ "bundled": true,
+ "requires": {
+ "debuglog": "^1.0.1",
+ "dezalgo": "^1.0.0",
+ "graceful-fs": "^4.1.2",
+ "once": "^1.3.0"
+ }
+ },
+ "registry-auth-token": {
+ "version": "3.3.2",
+ "bundled": true,
+ "requires": {
+ "rc": "^1.1.6",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "registry-url": {
+ "version": "3.1.0",
+ "bundled": true,
+ "requires": {
+ "rc": "^1.0.1"
+ }
+ },
+ "request": {
+ "version": "2.88.0",
+ "bundled": true,
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.0",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.4.3",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "bundled": true
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "bundled": true
+ },
+ "retry": {
+ "version": "0.12.0",
+ "bundled": true
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "bundled": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "run-queue": {
+ "version": "1.0.3",
+ "bundled": true,
+ "requires": {
+ "aproba": "^1.1.1"
+ },
+ "dependencies": {
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true
+ }
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "bundled": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true
+ },
+ "semver": {
+ "version": "5.7.1",
+ "bundled": true
+ },
+ "semver-diff": {
+ "version": "2.1.0",
+ "bundled": true,
+ "requires": {
+ "semver": "^5.0.3"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true
+ },
+ "sha": {
+ "version": "3.0.0",
+ "bundled": true,
+ "requires": {
+ "graceful-fs": "^4.1.2"
+ }
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "bundled": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true
+ },
+ "slash": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "slide": {
+ "version": "1.1.6",
+ "bundled": true
+ },
+ "smart-buffer": {
+ "version": "4.0.2",
+ "bundled": true
+ },
+ "socks": {
+ "version": "2.3.2",
+ "bundled": true,
+ "requires": {
+ "ip": "^1.1.5",
+ "smart-buffer": "4.0.2"
+ }
+ },
+ "socks-proxy-agent": {
+ "version": "4.0.2",
+ "bundled": true,
+ "requires": {
+ "agent-base": "~4.2.1",
+ "socks": "~2.3.2"
+ },
+ "dependencies": {
+ "agent-base": {
+ "version": "4.2.1",
+ "bundled": true,
+ "requires": {
+ "es6-promisify": "^5.0.0"
+ }
+ }
+ }
+ },
+ "sorted-object": {
+ "version": "2.0.1",
+ "bundled": true
+ },
+ "sorted-union-stream": {
+ "version": "2.1.3",
+ "bundled": true,
+ "requires": {
+ "from2": "^1.3.0",
+ "stream-iterate": "^1.1.0"
+ },
+ "dependencies": {
+ "from2": {
+ "version": "1.3.0",
+ "bundled": true,
+ "requires": {
+ "inherits": "~2.0.1",
+ "readable-stream": "~1.1.10"
+ }
+ },
+ "isarray": {
+ "version": "0.0.1",
+ "bundled": true
+ },
+ "readable-stream": {
+ "version": "1.1.14",
+ "bundled": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "bundled": true
+ }
+ }
+ },
+ "spdx-correct": {
+ "version": "3.0.0",
+ "bundled": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.1.0",
+ "bundled": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "bundled": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.3",
+ "bundled": true
+ },
+ "split-on-first": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "sshpk": {
+ "version": "1.14.2",
+ "bundled": true,
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "ssri": {
+ "version": "6.0.1",
+ "bundled": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1"
+ }
+ },
+ "stream-each": {
+ "version": "1.2.2",
+ "bundled": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "stream-iterate": {
+ "version": "1.2.0",
+ "bundled": true,
+ "requires": {
+ "readable-stream": "^2.1.5",
+ "stream-shift": "^1.0.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ }
+ }
+ },
+ "stream-shift": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "strict-uri-encode": {
+ "version": "2.0.0",
+ "bundled": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "bundled": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "bundled": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "bundled": true
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "bundled": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "string_decoder": {
+ "version": "1.2.0",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "stringify-package": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true
+ },
+ "supports-color": {
+ "version": "5.4.0",
+ "bundled": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "tar": {
+ "version": "4.4.10",
+ "bundled": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.3.5",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "2.3.5",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "bundled": true
+ }
+ }
+ },
+ "term-size": {
+ "version": "1.2.0",
+ "bundled": true,
+ "requires": {
+ "execa": "^0.7.0"
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "bundled": true
+ },
+ "through": {
+ "version": "2.3.8",
+ "bundled": true
+ },
+ "through2": {
+ "version": "2.0.3",
+ "bundled": true,
+ "requires": {
+ "readable-stream": "^2.1.5",
+ "xtend": "~4.0.1"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ }
+ }
+ },
+ "timed-out": {
+ "version": "4.0.1",
+ "bundled": true
+ },
+ "tiny-relative-date": {
+ "version": "1.3.0",
+ "bundled": true
+ },
+ "tough-cookie": {
+ "version": "2.4.3",
+ "bundled": true,
+ "requires": {
+ "psl": "^1.1.24",
+ "punycode": "^1.4.1"
+ }
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "bundled": true,
+ "optional": true
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "bundled": true
+ },
+ "uid-number": {
+ "version": "0.0.6",
+ "bundled": true
+ },
+ "umask": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "unique-filename": {
+ "version": "1.1.1",
+ "bundled": true,
+ "requires": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "2.0.0",
+ "bundled": true,
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "unique-string": {
+ "version": "1.0.0",
+ "bundled": true,
+ "requires": {
+ "crypto-random-string": "^1.0.0"
+ }
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "unzip-response": {
+ "version": "2.0.1",
+ "bundled": true
+ },
+ "update-notifier": {
+ "version": "2.5.0",
+ "bundled": true,
+ "requires": {
+ "boxen": "^1.2.1",
+ "chalk": "^2.0.1",
+ "configstore": "^3.0.0",
+ "import-lazy": "^2.1.0",
+ "is-ci": "^1.0.10",
+ "is-installed-globally": "^0.1.0",
+ "is-npm": "^1.0.0",
+ "latest-version": "^3.0.0",
+ "semver-diff": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ }
+ },
+ "url-parse-lax": {
+ "version": "1.0.0",
+ "bundled": true,
+ "requires": {
+ "prepend-http": "^1.0.1"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "util-extend": {
+ "version": "1.0.3",
+ "bundled": true
+ },
+ "util-promisify": {
+ "version": "2.1.0",
+ "bundled": true,
+ "requires": {
+ "object.getownpropertydescriptors": "^2.0.3"
+ }
+ },
+ "uuid": {
+ "version": "3.3.2",
+ "bundled": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.4",
+ "bundled": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "validate-npm-package-name": {
+ "version": "3.0.0",
+ "bundled": true,
+ "requires": {
+ "builtins": "^1.0.3"
+ }
+ },
+ "verror": {
+ "version": "1.10.0",
+ "bundled": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "wcwidth": {
+ "version": "1.0.1",
+ "bundled": true,
+ "requires": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "which": {
+ "version": "1.3.1",
+ "bundled": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "bundled": true
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "bundled": true,
+ "requires": {
+ "string-width": "^1.0.2"
+ },
+ "dependencies": {
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ }
+ }
+ },
+ "widest-line": {
+ "version": "2.0.0",
+ "bundled": true,
+ "requires": {
+ "string-width": "^2.1.1"
+ }
+ },
+ "worker-farm": {
+ "version": "1.7.0",
+ "bundled": true,
+ "requires": {
+ "errno": "~0.1.7"
+ }
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "bundled": true,
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "dependencies": {
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ }
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "write-file-atomic": {
+ "version": "2.4.3",
+ "bundled": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "xdg-basedir": {
+ "version": "3.0.0",
+ "bundled": true
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "bundled": true
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "bundled": true
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "bundled": true
+ },
+ "yargs": {
+ "version": "11.0.0",
+ "bundled": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.1.1",
+ "find-up": "^2.1.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^2.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1",
+ "yargs-parser": "^9.0.2"
+ },
+ "dependencies": {
+ "y18n": {
+ "version": "3.2.1",
+ "bundled": true
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "9.0.2",
+ "bundled": true,
+ "requires": {
+ "camelcase": "^4.1.0"
+ }
+ }
+ }
+ },
+ "npm-bundled": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz",
+ "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==",
+ "dev": true
+ },
+ "npm-package-arg": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.0.tgz",
+ "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==",
+ "dev": true,
+ "requires": {
+ "hosted-git-info": "^2.6.0",
+ "osenv": "^0.1.5",
+ "semver": "^5.5.0",
+ "validate-npm-package-name": "^3.0.0"
+ }
+ },
+ "npm-packlist": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.4.tgz",
+ "integrity": "sha512-zTLo8UcVYtDU3gdeaFu2Xu0n0EvelfHDGuqtNIn5RO7yQj4H1TqNdBc/yZjxnWA0PVB8D3Woyp0i5B43JwQ6Vw==",
+ "dev": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npm-pick-manifest": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz",
+ "integrity": "sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA==",
+ "dev": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1",
+ "npm-package-arg": "^6.0.0",
+ "semver": "^5.4.1"
+ }
+ },
+ "npm-registry-fetch": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.1.tgz",
+ "integrity": "sha512-1ZQ+yjnxc698R5h9Yje9CASapzAZr7aYDkJDdERg9xg2hOEY0vRJwskOaJAXq8N/eLavzvW4g564YAfq6zMn/A==",
+ "dev": true,
+ "requires": {
+ "JSONStream": "^1.3.4",
+ "bluebird": "^3.5.1",
+ "figgy-pudding": "^3.4.1",
+ "lru-cache": "^5.1.1",
+ "make-fetch-happen": "^5.0.0",
+ "npm-package-arg": "^6.1.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
+ "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+ "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
+ "dev": true
+ }
+ }
+ },
+ "npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
+ "dev": true,
+ "requires": {
+ "path-key": "^2.0.0"
+ }
+ },
+ "num2fraction": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
+ "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=",
+ "dev": true
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
+ },
+ "object-component": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
+ "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=",
+ "dev": true
+ },
+ "object-copy": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
+ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
+ "dev": true,
+ "requires": {
+ "copy-descriptor": "^0.1.0",
+ "define-property": "^0.2.5",
+ "kind-of": "^3.0.3"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "object-inspect": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
+ "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
+ "dev": true
+ },
+ "object-is": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz",
+ "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
+ "object-visit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
+ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.0"
+ }
+ },
+ "object.assign": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
+ "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "function-bind": "^1.1.1",
+ "has-symbols": "^1.0.0",
+ "object-keys": "^1.0.11"
+ }
+ },
+ "object.getownpropertydescriptors": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
+ "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "es-abstract": "^1.5.1"
+ }
+ },
+ "object.pick": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
+ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
+ "dev": true,
+ "requires": {
+ "isobject": "^3.0.1"
+ }
+ },
+ "obuf": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
+ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
+ "dev": true
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "dev": true,
+ "requires": {
+ "ee-first": "1.1.1"
+ }
+ },
+ "on-headers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
+ "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
+ "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "open": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz",
+ "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==",
+ "dev": true,
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "opn": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
+ "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==",
+ "dev": true,
+ "requires": {
+ "is-wsl": "^1.1.0"
+ }
+ },
+ "optimist": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+ "dev": true,
+ "requires": {
+ "minimist": "~0.0.1",
+ "wordwrap": "~0.0.2"
+ }
+ },
+ "original": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz",
+ "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==",
+ "dev": true,
+ "requires": {
+ "url-parse": "^1.4.3"
+ }
+ },
+ "os-browserify": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+ "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
+ "dev": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+ "dev": true
+ },
+ "os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "dev": true,
+ "requires": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
+ "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
+ "dev": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "p-defer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+ "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
+ "dev": true
+ },
+ "p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
+ "dev": true
+ },
+ "p-is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
+ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
+ "dev": true
+ },
+ "p-limit": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz",
+ "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.0.0"
+ }
+ },
+ "p-map": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
+ "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
+ "dev": true
+ },
+ "p-retry": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz",
+ "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==",
+ "dev": true,
+ "requires": {
+ "retry": "^0.12.0"
+ },
+ "dependencies": {
+ "retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
+ "dev": true
+ }
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "pacote": {
+ "version": "9.5.5",
+ "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.5.tgz",
+ "integrity": "sha512-jAEP+Nqj4kyMWyNpfTU/Whx1jA7jEc5cCOlurm0/0oL+v8TAp1QSsK83N7bYe+2bEdFzMAtPG5TBebjzzGV0cA==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.3",
+ "cacache": "^12.0.2",
+ "figgy-pudding": "^3.5.1",
+ "get-stream": "^4.1.0",
+ "glob": "^7.1.3",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^5.1.1",
+ "make-fetch-happen": "^5.0.0",
+ "minimatch": "^3.0.4",
+ "minipass": "^2.3.5",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "normalize-package-data": "^2.4.0",
+ "npm-package-arg": "^6.1.0",
+ "npm-packlist": "^1.1.12",
+ "npm-pick-manifest": "^2.2.3",
+ "npm-registry-fetch": "^4.0.0",
+ "osenv": "^0.1.5",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^1.1.1",
+ "protoduck": "^5.0.1",
+ "rimraf": "^2.6.2",
+ "safe-buffer": "^5.1.2",
+ "semver": "^5.6.0",
+ "ssri": "^6.0.1",
+ "tar": "^4.4.8",
+ "unique-filename": "^1.1.1",
+ "which": "^1.3.1"
+ },
+ "dependencies": {
+ "bluebird": {
+ "version": "3.5.5",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
+ "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==",
+ "dev": true
+ },
+ "cacache": {
+ "version": "12.0.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz",
+ "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==",
+ "dev": true,
+ "requires": {
+ "bluebird": "^3.5.5",
+ "chownr": "^1.1.1",
+ "figgy-pudding": "^3.5.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.1.15",
+ "infer-owner": "^1.0.3",
+ "lru-cache": "^5.1.1",
+ "mississippi": "^3.0.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.3",
+ "ssri": "^6.0.1",
+ "unique-filename": "^1.1.1",
+ "y18n": "^4.0.0"
+ },
+ "dependencies": {
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ }
+ }
+ },
+ "glob": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
+ "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
+ "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "requires": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "mississippi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+ "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+ "dev": true,
+ "requires": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^3.0.0",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true
+ },
+ "ssri": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+ "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+ "dev": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1"
+ }
+ },
+ "tar": {
+ "version": "4.4.11",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.11.tgz",
+ "integrity": "sha512-iI4zh3ktLJKaDNZKZc+fUONiQrSn9HkCFzamtb7k8FFmVilHVob7QsLX/VySAW8lAviMzMbFw4QtFb4errwgYA==",
+ "dev": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.6.4",
+ "minizlib": "^1.2.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.3"
+ }
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+ "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
+ "dev": true
+ }
+ }
+ },
+ "pako": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz",
+ "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==",
+ "dev": true
+ },
+ "parallel-transform": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
+ "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
+ "dev": true,
+ "requires": {
+ "cyclist": "^1.0.1",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.1.5"
+ }
+ },
+ "parse-asn1": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz",
+ "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==",
+ "dev": true,
+ "requires": {
+ "asn1.js": "^4.0.0",
+ "browserify-aes": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.0",
+ "pbkdf2": "^3.0.3",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+ "dev": true,
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "parse5": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
+ "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
+ "dev": true
+ },
+ "parseqs": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
+ "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
+ "dev": true,
+ "requires": {
+ "better-assert": "~1.0.0"
+ }
+ },
+ "parseuri": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
+ "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
+ "dev": true,
+ "requires": {
+ "better-assert": "~1.0.0"
+ }
+ },
+ "parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "dev": true
+ },
+ "pascalcase": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
+ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
+ "dev": true
+ },
+ "path-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz",
+ "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==",
+ "dev": true
+ },
+ "path-dirname": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
+ "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-is-inside": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
+ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
+ "dev": true
+ },
+ "path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
+ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+ "dev": true
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
+ "dev": true
+ },
+ "path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "requires": {
+ "pify": "^3.0.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+ "dev": true
+ }
+ }
+ },
+ "pbkdf2": {
+ "version": "3.0.17",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
+ "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==",
+ "dev": true,
+ "requires": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz",
+ "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==",
+ "dev": true
+ },
+ "pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "dev": true
+ },
+ "pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
+ "dev": true
+ },
+ "pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
+ "dev": true,
+ "requires": {
+ "pinkie": "^2.0.0"
+ }
+ },
+ "pkg-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+ "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+ "dev": true,
+ "requires": {
+ "find-up": "^3.0.0"
+ }
+ },
+ "popper.js": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.15.0.tgz",
+ "integrity": "sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA=="
+ },
+ "portfinder": {
+ "version": "1.0.24",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.24.tgz",
+ "integrity": "sha512-ekRl7zD2qxYndYflwiryJwMioBI7LI7rVXg3EnLK3sjkouT5eOuhS3gS255XxBksa30VG8UPZYZCdgfGOfkSUg==",
+ "dev": true,
+ "requires": {
+ "async": "^1.5.2",
+ "debug": "^2.2.0",
+ "mkdirp": "0.5.x"
+ },
+ "dependencies": {
+ "async": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+ "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+ "dev": true
+ }
+ }
+ },
+ "posix-character-classes": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
+ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
+ "dev": true
+ },
+ "postcss": {
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
+ "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.4.2",
+ "source-map": "^0.6.1",
+ "supports-color": "^6.1.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "postcss-import": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz",
+ "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==",
+ "dev": true,
+ "requires": {
+ "postcss": "^7.0.1",
+ "postcss-value-parser": "^3.2.3",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "dependencies": {
+ "postcss-value-parser": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
+ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
+ "dev": true
+ }
+ }
+ },
+ "postcss-load-config": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz",
+ "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==",
+ "dev": true,
+ "requires": {
+ "cosmiconfig": "^5.0.0",
+ "import-cwd": "^2.0.0"
+ }
+ },
+ "postcss-loader": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz",
+ "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "postcss": "^7.0.0",
+ "postcss-load-config": "^2.0.0",
+ "schema-utils": "^1.0.0"
+ }
+ },
+ "postcss-value-parser": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz",
+ "integrity": "sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ==",
+ "dev": true
+ },
+ "prepend-http": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
+ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
+ "dev": true
+ },
+ "private": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
+ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==",
+ "dev": true
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
+ "dev": true
+ },
+ "promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "asap": "~2.0.3"
+ }
+ },
+ "promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
+ "dev": true
+ },
+ "promise-retry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz",
+ "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=",
+ "dev": true,
+ "requires": {
+ "err-code": "^1.0.0",
+ "retry": "^0.10.0"
+ }
+ },
+ "protoduck": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz",
+ "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==",
+ "dev": true,
+ "requires": {
+ "genfun": "^5.0.0"
+ }
+ },
+ "protractor": {
+ "version": "5.4.2",
+ "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.2.tgz",
+ "integrity": "sha512-zlIj64Cr6IOWP7RwxVeD8O4UskLYPoyIcg0HboWJL9T79F1F0VWtKkGTr/9GN6BKL+/Q/GmM7C9kFVCfDbP5sA==",
+ "dev": true,
+ "requires": {
+ "@types/q": "^0.0.32",
+ "@types/selenium-webdriver": "^3.0.0",
+ "blocking-proxy": "^1.0.0",
+ "browserstack": "^1.5.1",
+ "chalk": "^1.1.3",
+ "glob": "^7.0.3",
+ "jasmine": "2.8.0",
+ "jasminewd2": "^2.1.0",
+ "optimist": "~0.6.0",
+ "q": "1.4.1",
+ "saucelabs": "^1.5.0",
+ "selenium-webdriver": "3.6.0",
+ "source-map-support": "~0.4.0",
+ "webdriver-js-extender": "2.1.0",
+ "webdriver-manager": "^12.0.6"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "del": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+ "dev": true,
+ "requires": {
+ "globby": "^5.0.0",
+ "is-path-cwd": "^1.0.0",
+ "is-path-in-cwd": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0",
+ "rimraf": "^2.2.8"
+ }
+ },
+ "globby": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+ "dev": true,
+ "requires": {
+ "array-union": "^1.0.1",
+ "arrify": "^1.0.0",
+ "glob": "^7.0.3",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ }
+ },
+ "is-path-cwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
+ "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=",
+ "dev": true
+ },
+ "is-path-in-cwd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz",
+ "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==",
+ "dev": true,
+ "requires": {
+ "is-path-inside": "^1.0.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
+ "dev": true,
+ "requires": {
+ "path-is-inside": "^1.0.1"
+ }
+ },
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.4.18",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
+ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
+ "dev": true,
+ "requires": {
+ "source-map": "^0.5.6"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "webdriver-manager": {
+ "version": "12.1.7",
+ "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.7.tgz",
+ "integrity": "sha512-XINj6b8CYuUYC93SG3xPkxlyUc3IJbD6Vvo75CVGuG9uzsefDzWQrhz0Lq8vbPxtb4d63CZdYophF8k8Or/YiA==",
+ "dev": true,
+ "requires": {
+ "adm-zip": "^0.4.9",
+ "chalk": "^1.1.1",
+ "del": "^2.2.0",
+ "glob": "^7.0.3",
+ "ini": "^1.3.4",
+ "minimist": "^1.2.0",
+ "q": "^1.4.1",
+ "request": "^2.87.0",
+ "rimraf": "^2.5.2",
+ "semver": "^5.3.0",
+ "xml2js": "^0.4.17"
+ }
+ }
+ }
+ },
+ "proxy-addr": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
+ "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==",
+ "dev": true,
+ "requires": {
+ "forwarded": "~0.1.2",
+ "ipaddr.js": "1.9.0"
+ }
+ },
+ "prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+ "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
+ "dev": true
+ },
+ "pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
+ "dev": true
+ },
+ "psl": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz",
+ "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==",
+ "dev": true
+ },
+ "public-encrypt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+ "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "parse-asn1": "^5.0.0",
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "pump": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "pumpify": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
+ "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
+ "dev": true,
+ "requires": {
+ "duplexify": "^3.6.0",
+ "inherits": "^2.0.3",
+ "pump": "^2.0.0"
+ }
+ },
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ },
+ "q": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
+ "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
+ "dev": true
+ },
+ "qjobs": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz",
+ "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.5.2",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+ "dev": true
+ },
+ "query-string": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
+ "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
+ "dev": true,
+ "requires": {
+ "object-assign": "^4.1.0",
+ "strict-uri-encode": "^1.0.0"
+ }
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
+ "dev": true
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
+ "dev": true
+ },
+ "querystringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
+ "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==",
+ "dev": true
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "randomfill": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+ "dev": true,
+ "requires": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "dev": true
+ },
+ "raw-body": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
+ "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "dev": true,
+ "requires": {
+ "bytes": "3.1.0",
+ "http-errors": "1.7.2",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "dependencies": {
+ "bytes": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+ "dev": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ }
+ }
+ },
+ "raw-loader": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-3.1.0.tgz",
+ "integrity": "sha512-lzUVMuJ06HF4rYveaz9Tv0WRlUMxJ0Y1hgSkkgg+50iEdaI0TthyEDe08KIHb0XsF6rn8WYTqPCaGTZg3sX+qA==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0",
+ "schema-utils": "^2.0.1"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.2.0.tgz",
+ "integrity": "sha512-5EwsCNhfFTZvUreQhx/4vVQpJ/lnCAkgoIHLhSpp4ZirE+4hzFvdJi0FMub6hxbFVBJYSpeVVmon+2e7uEGRrA==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.10.2",
+ "ajv-keywords": "^3.4.1"
+ }
+ }
+ }
+ },
+ "read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=",
+ "dev": true,
+ "requires": {
+ "pify": "^2.3.0"
+ },
+ "dependencies": {
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
+ "dev": true
+ }
+ }
+ },
+ "read-package-json": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.0.tgz",
+ "integrity": "sha512-KLhu8M1ZZNkMcrq1+0UJbR8Dii8KZUqB0Sha4mOx/bknfKI/fyrQVrG/YIt2UOtG667sD8+ee4EXMM91W9dC+A==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.1",
+ "graceful-fs": "^4.1.2",
+ "json-parse-better-errors": "^1.0.1",
+ "normalize-package-data": "^2.0.0",
+ "slash": "^1.0.0"
+ }
+ },
+ "read-package-tree": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz",
+ "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==",
+ "dev": true,
+ "requires": {
+ "read-package-json": "^2.0.0",
+ "readdir-scoped-modules": "^1.0.0",
+ "util-promisify": "^2.1.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "readdir-scoped-modules": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz",
+ "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==",
+ "dev": true,
+ "requires": {
+ "debuglog": "^1.0.1",
+ "dezalgo": "^1.0.0",
+ "graceful-fs": "^4.1.2",
+ "once": "^1.3.0"
+ }
+ },
+ "readdirp": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.1.2.tgz",
+ "integrity": "sha512-8rhl0xs2cxfVsqzreYCvs8EwBfn/DhVdqtoLmw19uI3SC5avYX9teCurlErfpPXGmYtMHReGaP2RsLnFvz/lnw==",
+ "dev": true,
+ "requires": {
+ "picomatch": "^2.0.4"
+ }
+ },
+ "reflect-metadata": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
+ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
+ "dev": true
+ },
+ "regenerate": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
+ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
+ "dev": true
+ },
+ "regenerate-unicode-properties": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz",
+ "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.4.0"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
+ "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==",
+ "dev": true
+ },
+ "regenerator-transform": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz",
+ "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==",
+ "dev": true,
+ "requires": {
+ "private": "^0.1.6"
+ }
+ },
+ "regex-not": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
+ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "regexp-tree": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.13.tgz",
+ "integrity": "sha512-hwdV/GQY5F8ReLZWO+W1SRoN5YfpOKY6852+tBFcma72DKBIcHjPRIlIvQN35bCOljuAfP2G2iB0FC/w236mUw==",
+ "dev": true
+ },
+ "regexp.prototype.flags": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz",
+ "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2"
+ }
+ },
+ "regexpu-core": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz",
+ "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.4.0",
+ "regenerate-unicode-properties": "^8.1.0",
+ "regjsgen": "^0.5.0",
+ "regjsparser": "^0.6.0",
+ "unicode-match-property-ecmascript": "^1.0.4",
+ "unicode-match-property-value-ecmascript": "^1.1.0"
+ }
+ },
+ "regjsgen": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz",
+ "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz",
+ "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==",
+ "dev": true,
+ "requires": {
+ "jsesc": "~0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true
+ }
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true
+ },
+ "repeat-element": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
+ "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true,
+ "requires": {
+ "is-finite": "^1.0.0"
+ }
+ },
+ "request": {
+ "version": "2.88.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+ "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.0",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.4.3",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ },
+ "dependencies": {
+ "mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.40.0"
+ }
+ }
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "dev": true
+ },
+ "require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
+ "dev": true
+ },
+ "requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
+ "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.6"
+ }
+ },
+ "resolve-cwd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
+ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=",
+ "dev": true,
+ "requires": {
+ "resolve-from": "^3.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
+ "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=",
+ "dev": true
+ },
+ "resolve-url": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
+ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "dev": true
+ },
+ "restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "requires": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "dev": true
+ },
+ "retry": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz",
+ "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=",
+ "dev": true
+ },
+ "rfdc": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz",
+ "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.0.5"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+ "dev": true,
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "run-async": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
+ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
+ "dev": true,
+ "requires": {
+ "is-promise": "^2.1.0"
+ }
+ },
+ "run-queue": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
+ "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=",
+ "dev": true,
+ "requires": {
+ "aproba": "^1.1.1"
+ }
+ },
+ "rxjs": {
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz",
+ "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==",
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "rxjs-compat": {
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/rxjs-compat/-/rxjs-compat-6.5.3.tgz",
+ "integrity": "sha512-BIJX2yovz3TBpjJoAZyls2QYuU6ZiCaZ+U96SmxQpuSP/qDUfiXPKOVLbThBB2WZijNHkdTTJXKRwvv5Y48H7g=="
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "safe-regex": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
+ "dev": true,
+ "requires": {
+ "ret": "~0.1.10"
+ }
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "sass": {
+ "version": "1.22.9",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.22.9.tgz",
+ "integrity": "sha512-FzU1X2V8DlnqabrL4u7OBwD2vcOzNMongEJEx3xMEhWY/v26FFR3aG0hyeu2T965sfR0E9ufJwmG+Qjz78vFPQ==",
+ "dev": true,
+ "requires": {
+ "chokidar": ">=2.0.0 <4.0.0"
+ }
+ },
+ "sass-loader": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.2.0.tgz",
+ "integrity": "sha512-h8yUWaWtsbuIiOCgR9fd9c2lRXZ2uG+h8Dzg/AGNj+Hg/3TO8+BBAW9mEP+mh8ei+qBKqSJ0F1FLlYjNBc61OA==",
+ "dev": true,
+ "requires": {
+ "clone-deep": "^4.0.1",
+ "loader-utils": "^1.0.1",
+ "neo-async": "^2.5.0",
+ "pify": "^4.0.1",
+ "semver": "^5.5.0"
+ }
+ },
+ "saucelabs": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/saucelabs/-/saucelabs-1.5.0.tgz",
+ "integrity": "sha512-jlX3FGdWvYf4Q3LFfFWS1QvPg3IGCGWxIc8QBFdPTbpTJnt/v17FHXYVAn7C8sHf1yUXo2c7yIM0isDryfYtHQ==",
+ "dev": true,
+ "requires": {
+ "https-proxy-agent": "^2.2.1"
+ }
+ },
+ "sax": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz",
+ "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=",
+ "dev": true
+ },
+ "schema-utils": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
+ "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-errors": "^1.0.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
+ "dev": true
+ },
+ "selenium-webdriver": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz",
+ "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==",
+ "dev": true,
+ "requires": {
+ "jszip": "^3.1.3",
+ "rimraf": "^2.5.4",
+ "tmp": "0.0.30",
+ "xml2js": "^0.4.17"
+ },
+ "dependencies": {
+ "tmp": {
+ "version": "0.0.30",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz",
+ "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.1"
+ }
+ }
+ }
+ },
+ "selfsigned": {
+ "version": "1.10.6",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.6.tgz",
+ "integrity": "sha512-i3+CeqxL7DpAazgVpAGdKMwHuL63B5nhJMh9NQ7xmChGkA3jNFflq6Jyo1LLJYcr3idWiNOPWHCrm4zMayLG4w==",
+ "dev": true,
+ "requires": {
+ "node-forge": "0.8.2"
+ }
+ },
+ "semver": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+ "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+ "dev": true
+ },
+ "semver-dsl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/semver-dsl/-/semver-dsl-1.0.1.tgz",
+ "integrity": "sha1-02eN5VVeimH2Ke7QJTZq5fJzQKA=",
+ "dev": true,
+ "requires": {
+ "semver": "^5.3.0"
+ }
+ },
+ "semver-intersect": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz",
+ "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==",
+ "dev": true,
+ "requires": {
+ "semver": "^5.0.0"
+ }
+ },
+ "send": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
+ "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+ "dev": true,
+ "requires": {
+ "debug": "2.6.9",
+ "depd": "~1.1.2",
+ "destroy": "~1.0.4",
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "0.5.2",
+ "http-errors": "~1.7.2",
+ "mime": "1.6.0",
+ "ms": "2.1.1",
+ "on-finished": "~2.3.0",
+ "range-parser": "~1.2.1",
+ "statuses": "~1.5.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+ "dev": true
+ }
+ }
+ },
+ "serialize-javascript": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz",
+ "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==",
+ "dev": true
+ },
+ "serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
+ "dev": true,
+ "requires": {
+ "accepts": "~1.3.4",
+ "batch": "0.6.1",
+ "debug": "2.6.9",
+ "escape-html": "~1.0.3",
+ "http-errors": "~1.6.2",
+ "mime-types": "~2.1.17",
+ "parseurl": "~1.3.2"
+ },
+ "dependencies": {
+ "http-errors": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+ "dev": true,
+ "requires": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ }
+ },
+ "setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+ "dev": true
+ }
+ }
+ },
+ "serve-static": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
+ "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+ "dev": true,
+ "requires": {
+ "encodeurl": "~1.0.2",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.17.1"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
+ "set-value": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
+ "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.3",
+ "split-string": "^3.0.1"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=",
+ "dev": true
+ },
+ "setprototypeof": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+ "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==",
+ "dev": true
+ },
+ "sha.js": {
+ "version": "2.4.11",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.2"
+ }
+ },
+ "shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^1.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
+ "dev": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
+ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
+ "dev": true
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+ "dev": true
+ },
+ "smart-buffer": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz",
+ "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==",
+ "dev": true
+ },
+ "snapdragon": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
+ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "dev": true,
+ "requires": {
+ "base": "^0.11.1",
+ "debug": "^2.2.0",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "map-cache": "^0.2.2",
+ "source-map": "^0.5.6",
+ "source-map-resolve": "^0.5.0",
+ "use": "^3.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ },
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ }
+ }
+ },
+ "snapdragon-node": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
+ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^1.0.0",
+ "isobject": "^3.0.0",
+ "snapdragon-util": "^3.0.1"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^1.0.0"
+ }
+ },
+ "is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^6.0.0"
+ }
+ },
+ "is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
+ "requires": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ }
+ }
+ }
+ },
+ "snapdragon-util": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
+ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.2.0"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "socket.io": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz",
+ "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==",
+ "dev": true,
+ "requires": {
+ "debug": "~3.1.0",
+ "engine.io": "~3.2.0",
+ "has-binary2": "~1.0.2",
+ "socket.io-adapter": "~1.1.0",
+ "socket.io-client": "2.1.1",
+ "socket.io-parser": "~3.2.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "socket.io-adapter": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz",
+ "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=",
+ "dev": true
+ },
+ "socket.io-client": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz",
+ "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==",
+ "dev": true,
+ "requires": {
+ "backo2": "1.0.2",
+ "base64-arraybuffer": "0.1.5",
+ "component-bind": "1.0.0",
+ "component-emitter": "1.2.1",
+ "debug": "~3.1.0",
+ "engine.io-client": "~3.2.0",
+ "has-binary2": "~1.0.2",
+ "has-cors": "1.1.0",
+ "indexof": "0.0.1",
+ "object-component": "0.0.3",
+ "parseqs": "0.0.5",
+ "parseuri": "0.0.5",
+ "socket.io-parser": "~3.2.0",
+ "to-array": "0.1.4"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ }
+ }
+ },
+ "socket.io-parser": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz",
+ "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==",
+ "dev": true,
+ "requires": {
+ "component-emitter": "1.2.1",
+ "debug": "~3.1.0",
+ "isarray": "2.0.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "isarray": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+ "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
+ "dev": true
+ }
+ }
+ },
+ "sockjs": {
+ "version": "0.3.19",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz",
+ "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==",
+ "dev": true,
+ "requires": {
+ "faye-websocket": "^0.10.0",
+ "uuid": "^3.0.1"
+ }
+ },
+ "sockjs-client": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz",
+ "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.2.5",
+ "eventsource": "^1.0.7",
+ "faye-websocket": "~0.11.1",
+ "inherits": "^2.0.3",
+ "json3": "^3.3.2",
+ "url-parse": "^1.4.3"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "faye-websocket": {
+ "version": "0.11.3",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz",
+ "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==",
+ "dev": true,
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "socks": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.2.tgz",
+ "integrity": "sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==",
+ "dev": true,
+ "requires": {
+ "ip": "^1.1.5",
+ "smart-buffer": "4.0.2"
+ }
+ },
+ "socks-proxy-agent": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz",
+ "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==",
+ "dev": true,
+ "requires": {
+ "agent-base": "~4.2.1",
+ "socks": "~2.3.2"
+ }
+ },
+ "sort-keys": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
+ "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=",
+ "dev": true,
+ "requires": {
+ "is-plain-obj": "^1.0.0"
+ }
+ },
+ "source-list-map": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
+ "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "source-map-loader": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz",
+ "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==",
+ "dev": true,
+ "requires": {
+ "async": "^2.5.0",
+ "loader-utils": "^1.1.0"
+ }
+ },
+ "source-map-resolve": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
+ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
+ "dev": true,
+ "requires": {
+ "atob": "^2.1.1",
+ "decode-uri-component": "^0.2.0",
+ "resolve-url": "^0.2.1",
+ "source-map-url": "^0.4.0",
+ "urix": "^0.1.0"
+ }
+ },
+ "source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "source-map-url": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
+ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+ "dev": true
+ },
+ "sourcemap-codec": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz",
+ "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==",
+ "dev": true
+ },
+ "spdx-correct": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz",
+ "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==",
+ "dev": true,
+ "requires": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-exceptions": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz",
+ "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==",
+ "dev": true
+ },
+ "spdx-expression-parse": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
+ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
+ "dev": true,
+ "requires": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "spdx-license-ids": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz",
+ "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==",
+ "dev": true
+ },
+ "spdy": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.1.tgz",
+ "integrity": "sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "handle-thing": "^2.0.0",
+ "http-deceiver": "^1.2.7",
+ "select-hose": "^2.0.0",
+ "spdy-transport": "^3.0.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "spdy-transport": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
+ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "detect-node": "^2.0.4",
+ "hpack.js": "^2.1.6",
+ "obuf": "^1.1.2",
+ "readable-stream": "^3.0.6",
+ "wbuf": "^1.7.3"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
+ "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "speed-measure-webpack-plugin": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.1.tgz",
+ "integrity": "sha512-qVIkJvbtS9j/UeZumbdfz0vg+QfG/zxonAjzefZrqzkr7xOncLVXkeGbTpzd1gjCBM4PmVNkWlkeTVhgskAGSQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^2.0.1"
+ }
+ },
+ "split-string": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
+ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^3.0.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
+ },
+ "sshpk": {
+ "version": "1.14.2",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
+ "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
+ "dev": true,
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "ssri": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+ "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+ "dev": true,
+ "requires": {
+ "figgy-pudding": "^3.5.1"
+ }
+ },
+ "static-extend": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
+ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
+ "dev": true,
+ "requires": {
+ "define-property": "^0.2.5",
+ "object-copy": "^0.1.0"
+ },
+ "dependencies": {
+ "define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "requires": {
+ "is-descriptor": "^0.1.0"
+ }
+ }
+ }
+ },
+ "statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+ "dev": true
+ },
+ "stream-browserify": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
+ "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==",
+ "dev": true,
+ "requires": {
+ "inherits": "~2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "stream-each": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
+ "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "stream-http": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
+ "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
+ "dev": true,
+ "requires": {
+ "builtin-status-codes": "^3.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.3.6",
+ "to-arraybuffer": "^1.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "stream-shift": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
+ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
+ "dev": true
+ },
+ "streamroller": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz",
+ "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==",
+ "dev": true,
+ "requires": {
+ "async": "^2.6.2",
+ "date-format": "^2.0.0",
+ "debug": "^3.2.6",
+ "fs-extra": "^7.0.1",
+ "lodash": "^4.17.14"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
+ "strict-uri-encode": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
+ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string.prototype.trimleft": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz",
+ "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "function-bind": "^1.1.1"
+ }
+ },
+ "string.prototype.trimright": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz",
+ "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.3",
+ "function-bind": "^1.1.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+ "dev": true
+ },
+ "strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
+ "dev": true
+ },
+ "style-loader": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.0.0.tgz",
+ "integrity": "sha512-B0dOCFwv7/eY31a5PCieNwMgMhVGFe9w+rh7s/Bx8kfFkrth9zfTZquoYvdw8URgiqxObQKcpW51Ugz1HjfdZw==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.2.3",
+ "schema-utils": "^2.0.1"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.2.0.tgz",
+ "integrity": "sha512-5EwsCNhfFTZvUreQhx/4vVQpJ/lnCAkgoIHLhSpp4ZirE+4hzFvdJi0FMub6hxbFVBJYSpeVVmon+2e7uEGRrA==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.10.2",
+ "ajv-keywords": "^3.4.1"
+ }
+ }
+ }
+ },
+ "stylus": {
+ "version": "0.54.5",
+ "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz",
+ "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=",
+ "dev": true,
+ "requires": {
+ "css-parse": "1.7.x",
+ "debug": "*",
+ "glob": "7.0.x",
+ "mkdirp": "0.5.x",
+ "sax": "0.5.x",
+ "source-map": "0.1.x"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
+ "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.2",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "source-map": {
+ "version": "0.1.43",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
+ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
+ "dev": true,
+ "requires": {
+ "amdefine": ">=0.0.4"
+ }
+ }
+ }
+ },
+ "stylus-loader": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz",
+ "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.0.2",
+ "lodash.clonedeep": "^4.5.0",
+ "when": "~3.6.x"
+ }
+ },
+ "supports-color": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
+ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "symbol-observable": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
+ "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==",
+ "dev": true
+ },
+ "tapable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+ "dev": true
+ },
+ "terser": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-4.1.4.tgz",
+ "integrity": "sha512-+ZwXJvdSwbd60jG0Illav0F06GDJF0R4ydZ21Q3wGAFKoBGyJGo34F63vzJHgvYxc1ukOtIjvwEvl9MkjzM6Pg==",
+ "dev": true,
+ "requires": {
+ "commander": "^2.20.0",
+ "source-map": "~0.6.1",
+ "source-map-support": "~0.5.12"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "terser-webpack-plugin": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz",
+ "integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==",
+ "dev": true,
+ "requires": {
+ "cacache": "^12.0.2",
+ "find-cache-dir": "^2.1.0",
+ "is-wsl": "^1.1.0",
+ "schema-utils": "^1.0.0",
+ "serialize-javascript": "^1.7.0",
+ "source-map": "^0.6.1",
+ "terser": "^4.1.2",
+ "webpack-sources": "^1.4.0",
+ "worker-farm": "^1.7.0"
+ },
+ "dependencies": {
+ "find-cache-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+ "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+ "dev": true,
+ "requires": {
+ "commondir": "^1.0.1",
+ "make-dir": "^2.0.0",
+ "pkg-dir": "^3.0.0"
+ }
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
+ "dev": true
+ },
+ "through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "thunky": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz",
+ "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==",
+ "dev": true
+ },
+ "timers-browserify": {
+ "version": "2.0.11",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz",
+ "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==",
+ "dev": true,
+ "requires": {
+ "setimmediate": "^1.0.4"
+ }
+ },
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
+ "to-array": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
+ "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=",
+ "dev": true
+ },
+ "to-arraybuffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
+ "dev": true
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "dev": true
+ },
+ "to-object-path": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
+ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
+ "dev": true,
+ "requires": {
+ "kind-of": "^3.0.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "requires": {
+ "is-buffer": "^1.1.5"
+ }
+ }
+ }
+ },
+ "to-regex": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
+ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
+ "dev": true,
+ "requires": {
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "regex-not": "^1.0.2",
+ "safe-regex": "^1.1.0"
+ }
+ },
+ "to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
+ "dev": true,
+ "requires": {
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "toidentifier": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
+ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
+ "dev": true
+ },
+ "tough-cookie": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+ "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+ "dev": true,
+ "requires": {
+ "psl": "^1.1.24",
+ "punycode": "^1.4.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ }
+ }
+ },
+ "tree-kill": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz",
+ "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==",
+ "dev": true
+ },
+ "trim-right": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
+ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
+ "dev": true
+ },
+ "ts-node": {
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.4.1.tgz",
+ "integrity": "sha512-5LpRN+mTiCs7lI5EtbXmF/HfMeCjzt7DH9CZwtkr6SywStrNQC723wG+aOWFiLNn7zT3kD/RnFqi3ZUfr4l5Qw==",
+ "dev": true,
+ "requires": {
+ "arg": "^4.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "source-map-support": "^0.5.6",
+ "yn": "^3.0.0"
+ }
+ },
+ "tslib": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
+ },
+ "tslint": {
+ "version": "5.20.0",
+ "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.0.tgz",
+ "integrity": "sha512-2vqIvkMHbnx8acMogAERQ/IuINOq6DFqgF8/VDvhEkBqQh/x6SP0Y+OHnKth9/ZcHQSroOZwUQSN18v8KKF0/g==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.0.0",
+ "builtin-modules": "^1.1.1",
+ "chalk": "^2.3.0",
+ "commander": "^2.12.1",
+ "diff": "^4.0.1",
+ "glob": "^7.1.1",
+ "js-yaml": "^3.13.1",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "resolve": "^1.3.2",
+ "semver": "^5.3.0",
+ "tslib": "^1.8.0",
+ "tsutils": "^2.29.0"
+ }
+ },
+ "tsutils": {
+ "version": "2.29.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
+ "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
+ "dev": true
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
+ "dev": true,
+ "optional": true
+ },
+ "type-fest": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz",
+ "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==",
+ "dev": true
+ },
+ "type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dev": true,
+ "requires": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "dependencies": {
+ "mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.40.0"
+ }
+ }
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
+ "dev": true
+ },
+ "typescript": {
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.1.tgz",
+ "integrity": "sha512-64HkdiRv1yYZsSe4xC1WVgamNigVYjlssIoaH2HcZF0+ijsk5YK2g0G34w9wJkze8+5ow4STd22AynfO6ZYYLw==",
+ "dev": true
+ },
+ "typestyle": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/typestyle/-/typestyle-2.0.4.tgz",
+ "integrity": "sha512-+57eGqcEjiAc51hB/zXnZFoVuzwuxb9WbPpb1VT2zPJPIo88wGXod7dHa0IJ1Ue+sncHj2WZMZEPJRAqwVraoA==",
+ "requires": {
+ "csstype": "^2.4.0",
+ "free-style": "2.6.1"
+ }
+ },
+ "uc.micro": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
+ },
+ "uglify-js": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
+ "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "commander": "~2.20.0",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "ultron": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
+ "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==",
+ "dev": true
+ },
+ "unicode-canonical-property-names-ecmascript": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",
+ "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==",
+ "dev": true
+ },
+ "unicode-match-property-ecmascript": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz",
+ "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==",
+ "dev": true,
+ "requires": {
+ "unicode-canonical-property-names-ecmascript": "^1.0.4",
+ "unicode-property-aliases-ecmascript": "^1.0.4"
+ }
+ },
+ "unicode-match-property-value-ecmascript": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz",
+ "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==",
+ "dev": true
+ },
+ "unicode-property-aliases-ecmascript": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz",
+ "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==",
+ "dev": true
+ },
+ "union-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
+ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=",
+ "dev": true,
+ "requires": {
+ "arr-union": "^3.1.0",
+ "get-value": "^2.0.6",
+ "is-extendable": "^0.1.1",
+ "set-value": "^0.4.3"
+ },
+ "dependencies": {
+ "extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "requires": {
+ "is-extendable": "^0.1.0"
+ }
+ },
+ "set-value": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz",
+ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=",
+ "dev": true,
+ "requires": {
+ "extend-shallow": "^2.0.1",
+ "is-extendable": "^0.1.1",
+ "is-plain-object": "^2.0.1",
+ "to-object-path": "^0.3.0"
+ }
+ }
+ }
+ },
+ "unique-filename": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+ "dev": true,
+ "requires": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "unique-slug": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+ "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
+ "dev": true,
+ "requires": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "universal-analytics": {
+ "version": "0.4.20",
+ "resolved": "https://registry.npmjs.org/universal-analytics/-/universal-analytics-0.4.20.tgz",
+ "integrity": "sha512-gE91dtMvNkjO+kWsPstHRtSwHXz0l2axqptGYp5ceg4MsuurloM0PU3pdOfpb5zBXUvyjT4PwhWK2m39uczZuw==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.0.0",
+ "request": "^2.88.0",
+ "uuid": "^3.0.0"
+ },
+ "dependencies": {
+ "ajv": {
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+ "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^2.0.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "aws4": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
+ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+ "dev": true
+ },
+ "har-validator": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
+ "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.5.5",
+ "har-schema": "^2.0.0"
+ }
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.40.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+ "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.24",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+ "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.40.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "dev": true
+ },
+ "request": {
+ "version": "2.88.0",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
+ "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.0",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.4.3",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
+ "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
+ "dev": true,
+ "requires": {
+ "psl": "^1.1.24",
+ "punycode": "^1.4.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ }
+ }
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ }
+ }
+ },
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+ "dev": true
+ },
+ "unset-value": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
+ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
+ "dev": true,
+ "requires": {
+ "has-value": "^0.3.1",
+ "isobject": "^3.0.0"
+ },
+ "dependencies": {
+ "has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dev": true,
+ "requires": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "dependencies": {
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ }
+ }
+ },
+ "has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "dev": true
+ }
+ }
+ },
+ "upath": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
+ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
+ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "urix": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
+ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "dev": true
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "dev": true,
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
+ "dev": true
+ }
+ }
+ },
+ "url-parse": {
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
+ "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
+ "dev": true,
+ "requires": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "use": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
+ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
+ "dev": true
+ },
+ "useragent": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz",
+ "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "4.1.x",
+ "tmp": "0.0.x"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dev": true,
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
+ "dev": true
+ }
+ }
+ },
+ "util": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
+ "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "util-promisify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz",
+ "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=",
+ "dev": true,
+ "requires": {
+ "object.getownpropertydescriptors": "^2.0.3"
+ }
+ },
+ "util.promisify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
+ "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
+ "dev": true,
+ "requires": {
+ "define-properties": "^1.1.2",
+ "object.getownpropertydescriptors": "^2.0.3"
+ }
+ },
+ "utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
+ "dev": true
+ },
+ "validate-npm-package-license": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz",
+ "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==",
+ "dev": true,
+ "requires": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "validate-npm-package-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz",
+ "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=",
+ "dev": true,
+ "requires": {
+ "builtins": "^1.0.3"
+ }
+ },
+ "vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+ "dev": true
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "vm-browserify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz",
+ "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==",
+ "dev": true
+ },
+ "void-elements": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
+ "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
+ "dev": true
+ },
+ "watchpack": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
+ "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==",
+ "dev": true,
+ "requires": {
+ "chokidar": "^2.0.2",
+ "graceful-fs": "^4.1.2",
+ "neo-async": "^2.5.0"
+ },
+ "dependencies": {
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "dev": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "fsevents": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
+ "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "nan": "^2.12.1",
+ "node-pre-gyp": "^0.12.0"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chownr": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "fs-minipass": {
+ "version": "1.2.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minipass": {
+ "version": "2.3.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.2.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "needle": {
+ "version": "2.3.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.12.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "npm-packlist": {
+ "version": "1.4.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "semver": {
+ "version": "5.7.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "4.4.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.3.4",
+ "minizlib": "^1.1.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.2"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ }
+ }
+ },
+ "wbuf": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+ "dev": true,
+ "requires": {
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "webdriver-js-extender": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz",
+ "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==",
+ "dev": true,
+ "requires": {
+ "@types/selenium-webdriver": "^3.0.0",
+ "selenium-webdriver": "^3.0.1"
+ }
+ },
+ "webpack": {
+ "version": "4.39.2",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.39.2.tgz",
+ "integrity": "sha512-AKgTfz3xPSsEibH00JfZ9sHXGUwIQ6eZ9tLN8+VLzachk1Cw2LVmy+4R7ZiwTa9cZZ15tzySjeMui/UnSCAZhA==",
+ "dev": true,
+ "requires": {
+ "@webassemblyjs/ast": "1.8.5",
+ "@webassemblyjs/helper-module-context": "1.8.5",
+ "@webassemblyjs/wasm-edit": "1.8.5",
+ "@webassemblyjs/wasm-parser": "1.8.5",
+ "acorn": "^6.2.1",
+ "ajv": "^6.10.2",
+ "ajv-keywords": "^3.4.1",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^4.1.0",
+ "eslint-scope": "^4.0.3",
+ "json-parse-better-errors": "^1.0.2",
+ "loader-runner": "^2.4.0",
+ "loader-utils": "^1.2.3",
+ "memory-fs": "^0.4.1",
+ "micromatch": "^3.1.10",
+ "mkdirp": "^0.5.1",
+ "neo-async": "^2.6.1",
+ "node-libs-browser": "^2.2.1",
+ "schema-utils": "^1.0.0",
+ "tapable": "^1.1.3",
+ "terser-webpack-plugin": "^1.4.1",
+ "watchpack": "^1.6.0",
+ "webpack-sources": "^1.4.1"
+ }
+ },
+ "webpack-core": {
+ "version": "0.6.9",
+ "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz",
+ "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=",
+ "dev": true,
+ "requires": {
+ "source-list-map": "~0.1.7",
+ "source-map": "~0.4.1"
+ },
+ "dependencies": {
+ "source-list-map": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz",
+ "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+ "dev": true,
+ "requires": {
+ "amdefine": ">=0.0.4"
+ }
+ }
+ }
+ },
+ "webpack-dev-middleware": {
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.0.tgz",
+ "integrity": "sha512-qvDesR1QZRIAZHOE3iQ4CXLZZSQ1lAUsSpnQmlB1PBfoN/xdRjmge3Dok0W4IdaVLJOGJy3sGI4sZHwjRU0PCA==",
+ "dev": true,
+ "requires": {
+ "memory-fs": "^0.4.1",
+ "mime": "^2.4.2",
+ "range-parser": "^1.2.1",
+ "webpack-log": "^2.0.0"
+ },
+ "dependencies": {
+ "mime": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==",
+ "dev": true
+ }
+ }
+ },
+ "webpack-dev-server": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.8.0.tgz",
+ "integrity": "sha512-Hs8K9yI6pyMvGkaPTeTonhD6JXVsigXDApYk9JLW4M7viVBspQvb1WdAcWxqtmttxNW4zf2UFLsLNe0y87pIGQ==",
+ "dev": true,
+ "requires": {
+ "ansi-html": "0.0.7",
+ "bonjour": "^3.5.0",
+ "chokidar": "^2.1.6",
+ "compression": "^1.7.4",
+ "connect-history-api-fallback": "^1.6.0",
+ "debug": "^4.1.1",
+ "del": "^4.1.1",
+ "express": "^4.17.1",
+ "html-entities": "^1.2.1",
+ "http-proxy-middleware": "^0.19.1",
+ "import-local": "^2.0.0",
+ "internal-ip": "^4.3.0",
+ "ip": "^1.1.5",
+ "is-absolute-url": "^3.0.0",
+ "killable": "^1.0.1",
+ "loglevel": "^1.6.3",
+ "opn": "^5.5.0",
+ "p-retry": "^3.0.1",
+ "portfinder": "^1.0.21",
+ "schema-utils": "^1.0.0",
+ "selfsigned": "^1.10.4",
+ "semver": "^6.3.0",
+ "serve-index": "^1.9.1",
+ "sockjs": "0.3.19",
+ "sockjs-client": "1.3.0",
+ "spdy": "^4.0.1",
+ "strip-ansi": "^3.0.1",
+ "supports-color": "^6.1.0",
+ "url": "^0.11.0",
+ "webpack-dev-middleware": "^3.7.0",
+ "webpack-log": "^2.0.0",
+ "ws": "^6.2.1",
+ "yargs": "12.0.5"
+ },
+ "dependencies": {
+ "chokidar": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
+ "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
+ "dev": true,
+ "requires": {
+ "anymatch": "^2.0.0",
+ "async-each": "^1.0.1",
+ "braces": "^2.3.2",
+ "fsevents": "^1.2.7",
+ "glob-parent": "^3.1.0",
+ "inherits": "^2.0.3",
+ "is-binary-path": "^1.0.0",
+ "is-glob": "^4.0.0",
+ "normalize-path": "^3.0.0",
+ "path-is-absolute": "^1.0.0",
+ "readdirp": "^2.2.1",
+ "upath": "^1.1.1"
+ }
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "fsevents": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
+ "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "nan": "^2.12.1",
+ "node-pre-gyp": "^0.12.0"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true
+ },
+ "aproba": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "chownr": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "debug": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "deep-extend": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "fs-minipass": {
+ "version": "1.2.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "glob": {
+ "version": "7.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "iconv-lite": {
+ "version": "0.4.24",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ignore-walk": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minimatch": "^3.0.4"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true,
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "number-is-nan": "^1.0.0"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "dev": true
+ },
+ "minipass": {
+ "version": "2.3.5",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.0"
+ }
+ },
+ "minizlib": {
+ "version": "1.2.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "minipass": "^2.2.1"
+ }
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "needle": {
+ "version": "2.3.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "debug": "^4.1.0",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ }
+ },
+ "node-pre-gyp": {
+ "version": "0.12.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "^1.0.2",
+ "mkdirp": "^0.5.1",
+ "needle": "^2.2.1",
+ "nopt": "^4.0.1",
+ "npm-packlist": "^1.1.6",
+ "npmlog": "^4.0.2",
+ "rc": "^1.2.7",
+ "rimraf": "^2.6.1",
+ "semver": "^5.3.0",
+ "tar": "^4"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ }
+ },
+ "npm-bundled": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "npm-packlist": {
+ "version": "1.4.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ignore-walk": "^3.0.1",
+ "npm-bundled": "^1.0.1"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "bundled": true,
+ "dev": true
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sax": {
+ "version": "1.2.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "semver": {
+ "version": "5.7.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "4.4.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "chownr": "^1.1.1",
+ "fs-minipass": "^1.2.5",
+ "minipass": "^2.3.4",
+ "minizlib": "^1.1.1",
+ "mkdirp": "^0.5.0",
+ "safe-buffer": "^5.1.2",
+ "yallist": "^3.0.2"
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "bundled": true,
+ "dev": true
+ }
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "readdirp": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+ "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.11",
+ "micromatch": "^3.1.10",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "webpack-log": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
+ "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^3.0.0",
+ "uuid": "^3.3.2"
+ }
+ },
+ "webpack-merge": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz",
+ "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.17.5"
+ }
+ },
+ "webpack-sources": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
+ "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
+ "dev": true,
+ "requires": {
+ "source-list-map": "^2.0.0",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
+ }
+ },
+ "webpack-subresource-integrity": {
+ "version": "1.1.0-rc.6",
+ "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.1.0-rc.6.tgz",
+ "integrity": "sha512-Az7y8xTniNhaA0620AV1KPwWOqawurVVDzQSpPAeR5RwNbL91GoBSJAAo9cfd+GiFHwsS5bbHepBw1e6Hzxy4w==",
+ "dev": true,
+ "requires": {
+ "webpack-core": "^0.6.8"
+ }
+ },
+ "websocket-driver": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz",
+ "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==",
+ "dev": true,
+ "requires": {
+ "http-parser-js": ">=0.4.0 <0.4.11",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ }
+ },
+ "websocket-extensions": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
+ "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
+ "dev": true
+ },
+ "when": {
+ "version": "3.6.4",
+ "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz",
+ "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=",
+ "dev": true
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "wordwrap": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+ "dev": true
+ },
+ "worker-farm": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
+ "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
+ "dev": true,
+ "requires": {
+ "errno": "~0.1.7"
+ }
+ },
+ "worker-plugin": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-3.2.0.tgz",
+ "integrity": "sha512-W5nRkw7+HlbsEt3qRP6MczwDDISjiRj2GYt9+bpe8A2La00TmJdwzG5bpdMXhRt1qcWmwAvl1TiKaHRa+XDS9Q==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.1.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
+ "dev": true,
+ "requires": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "ws": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
+ "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
+ "dev": true,
+ "requires": {
+ "async-limiter": "~1.0.0"
+ }
+ },
+ "xml2js": {
+ "version": "0.4.22",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.22.tgz",
+ "integrity": "sha512-MWTbxAQqclRSTnehWWe5nMKzI3VmJ8ltiJEco8akcC6j3miOhjjfzKum5sId+CWhfxdOs/1xauYr8/ZDBtQiRw==",
+ "dev": true,
+ "requires": {
+ "sax": ">=0.6.0",
+ "util.promisify": "~1.0.0",
+ "xmlbuilder": "~11.0.0"
+ },
+ "dependencies": {
+ "sax": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
+ "dev": true
+ }
+ }
+ },
+ "xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "dev": true
+ },
+ "xmlhttprequest-ssl": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
+ "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=",
+ "dev": true
+ },
+ "xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "dev": true
+ },
+ "y18n": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+ "dev": true
+ },
+ "yallist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+ "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "12.0.5",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
+ "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
+ "dev": true,
+ "requires": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^3.0.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1 || ^4.0.0",
+ "yargs-parser": "^11.1.1"
+ },
+ "dependencies": {
+ "ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
+ "dev": true
+ },
+ "string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "requires": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ }
+ },
+ "strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^3.0.0"
+ }
+ }
+ }
+ },
+ "yargs-parser": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
+ "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ },
+ "yeast": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
+ "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
+ "dev": true
+ },
+ "yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "dev": true
+ },
+ "zone.js": {
+ "version": "0.10.2",
+ "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.2.tgz",
+ "integrity": "sha512-UAYfiuvxLN4oyuqhJwd21Uxb4CNawrq6fPS/05Su5L4G+1TN+HVDJMUHNMobVQDFJRir2cLAODXwluaOKB7HFg=="
+ }
+ }
+}
diff --git a/Source/DashboardTabApp/package.json b/Source/DashboardTabApp/package.json
new file mode 100644
index 0000000..62a1e51
--- /dev/null
+++ b/Source/DashboardTabApp/package.json
@@ -0,0 +1,71 @@
+{
+ "name": "dashboard-tab-app",
+ "version": "0.0.0",
+ "scripts": {
+ "ng": "ng",
+ "start": "ng serve",
+ "build": "ng build",
+ "test": "ng test",
+ "lint": "ng lint",
+ "e2e": "ng e2e"
+ },
+ "private": true,
+ "dependencies": {
+ "@angular/animations": "^8.2.6",
+ "@angular/cdk": "^8.2.0",
+ "@angular/common": "^8.2.6",
+ "@angular/compiler": "^8.2.6",
+ "@angular/core": "^8.2.6",
+ "@angular/forms": "^8.2.6",
+ "@angular/http": "^7.2.15",
+ "@angular/material": "^8.2.0",
+ "@angular/platform-browser": "^8.2.6",
+ "@angular/platform-browser-dynamic": "^8.2.6",
+ "@angular/router": "^8.2.6",
+ "@azure/msal-angular": "^0.1.4",
+ "@fortawesome/angular-fontawesome": "^0.5.0",
+ "@fortawesome/fontawesome-svg-core": "^1.2.24",
+ "@fortawesome/free-solid-svg-icons": "^5.11.1",
+ "@microsoft/teams-js": "^1.5.1",
+ "@types/lodash.memoize": "^4.1.6",
+ "adal-angular": "^1.0.17",
+ "adaptivecards": "^1.2.0",
+ "bootstrap": "^4.3.1",
+ "core-js": "^3.2.1",
+ "expose-loader": "^0.7.5",
+ "jquery": "^3.4.1",
+ "markdown-it": "^10.0.0",
+ "moment-timezone": "^0.5.26",
+ "msteams-ui-icons-core": "^0.4.2",
+ "msteams-ui-styles-core": "^0.8.2",
+ "ng4-loading-spinner": "^1.2.3",
+ "npm": "^6.11.3",
+ "popper.js": "^1.15.0",
+ "rxjs": "^6.5.3",
+ "rxjs-compat": "^6.5.3",
+ "typestyle": "^2.0.4",
+ "zone.js": "^0.10.2"
+ },
+ "devDependencies": {
+ "@angular-devkit/build-angular": "^0.803.4",
+ "@angular/cli": "~8.3.4",
+ "@angular/compiler-cli": "^8.2.6",
+ "@angular/language-service": "^8.2.6",
+ "@types/adal": "^1.0.29",
+ "@types/jasmine": "~3.4.0",
+ "@types/jasminewd2": "~2.0.6",
+ "@types/node": "~12.7.5",
+ "codelyzer": "~5.1.0",
+ "jasmine-core": "~3.4.0",
+ "jasmine-spec-reporter": "~4.2.1",
+ "karma": "~4.3.0",
+ "karma-chrome-launcher": "~3.1.0",
+ "karma-coverage-istanbul-reporter": "~2.1.0",
+ "karma-jasmine": "~2.0.1",
+ "karma-jasmine-html-reporter": "^1.4.2",
+ "protractor": "~5.4.2",
+ "ts-node": "~8.4.1",
+ "tslint": "~5.20.0",
+ "typescript": "^3.5.1"
+ }
+}
diff --git a/Source/DashboardTabApp/src/app/add-course-dialog/add-course-dialog.component.html b/Source/DashboardTabApp/src/app/add-course-dialog/add-course-dialog.component.html
new file mode 100644
index 0000000..cdb3c16
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/add-course-dialog/add-course-dialog.component.html
@@ -0,0 +1,17 @@
+
Select Course
+
+
Select from an existing team.
+
+
+
+
+
+ {{obj.displayName}}
+
+
+
+
+
+ OK
+ Cancel
+
diff --git a/Source/DashboardTabApp/src/app/add-course-dialog/add-course-dialog.component.scss b/Source/DashboardTabApp/src/app/add-course-dialog/add-course-dialog.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/Source/DashboardTabApp/src/app/add-course-dialog/add-course-dialog.component.spec.ts b/Source/DashboardTabApp/src/app/add-course-dialog/add-course-dialog.component.spec.ts
new file mode 100644
index 0000000..08da541
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/add-course-dialog/add-course-dialog.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AddCourseDialogComponent } from './add-course-dialog.component';
+
+describe('AddCourseDialogComponent', () => {
+ let component: AddCourseDialogComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ AddCourseDialogComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AddCourseDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/Source/DashboardTabApp/src/app/add-course-dialog/add-course-dialog.component.ts b/Source/DashboardTabApp/src/app/add-course-dialog/add-course-dialog.component.ts
new file mode 100644
index 0000000..80fd18b
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/add-course-dialog/add-course-dialog.component.ts
@@ -0,0 +1,25 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+
+@Component({
+ selector: 'app-add-course-dialog',
+ templateUrl: './add-course-dialog.component.html',
+ styleUrls: ['./add-course-dialog.component.scss']
+})
+export class AddCourseDialogComponent implements OnInit {
+ selectedCourse: any;
+
+ constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any) {
+ }
+
+ ngOnInit() {
+ }
+
+ onOkClick(): void {
+ this.dialogRef.close(this.selectedCourse);
+ }
+
+ onCancelClick(): void {
+ this.dialogRef.close();
+ }
+}
diff --git a/Source/DashboardTabApp/src/app/analytics/analytics.component.css b/Source/DashboardTabApp/src/app/analytics/analytics.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/Source/DashboardTabApp/src/app/analytics/analytics.component.html b/Source/DashboardTabApp/src/app/analytics/analytics.component.html
new file mode 100644
index 0000000..c9abb3d
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/analytics/analytics.component.html
@@ -0,0 +1,3 @@
+Analytics
+Analytics page placeholder
+
diff --git a/Source/DashboardTabApp/src/app/analytics/analytics.component.ts b/Source/DashboardTabApp/src/app/analytics/analytics.component.ts
new file mode 100644
index 0000000..06180c0
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/analytics/analytics.component.ts
@@ -0,0 +1,9 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'analytics',
+ templateUrl: './analytics.component.html',
+ styleUrls: ['./analytics.component.css']
+})
+export class AnalyticsComponent {
+}
diff --git a/Source/DashboardTabApp/src/app/app.component.css b/Source/DashboardTabApp/src/app/app.component.css
new file mode 100644
index 0000000..33bfcb7
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/app.component.css
@@ -0,0 +1,6 @@
+@media (max-width: 767px) {
+ /* On small screens, the nav menu spans the full width of the screen. Leave a space for it. */
+ .body-content {
+ padding-top: 50px;
+ }
+}
diff --git a/Source/DashboardTabApp/src/app/app.component.html b/Source/DashboardTabApp/src/app/app.component.html
new file mode 100644
index 0000000..3d57f90
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/app.component.html
@@ -0,0 +1,11 @@
+
+
diff --git a/Source/DashboardTabApp/src/app/app.component.spec.ts b/Source/DashboardTabApp/src/app/app.component.spec.ts
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/app.component.spec.ts
@@ -0,0 +1 @@
+
diff --git a/Source/DashboardTabApp/src/app/app.component.ts b/Source/DashboardTabApp/src/app/app.component.ts
new file mode 100644
index 0000000..24dc9f7
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/app.component.ts
@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+})
+
+export class AppComponent {
+}
diff --git a/Source/DashboardTabApp/src/app/app.module.ts b/Source/DashboardTabApp/src/app/app.module.ts
new file mode 100644
index 0000000..43bb05c
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/app.module.ts
@@ -0,0 +1,111 @@
+import { NgModule, APP_INITIALIZER } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { RouterModule, Routes } from '@angular/router';
+import { Http, HttpModule } from '@angular/http';
+import { FormsModule } from '@angular/forms';
+
+import { AppComponent } from './app.component';
+import { AppService } from './app.service';
+
+import { QuestionComponent } from './question/question.component';
+import { NavMenuComponent } from './navmenu/navmenu.component';
+import { HomeComponent } from './home/home.component';
+import { ConfigComponent } from './config/config.component';
+import { MyStudentsComponent } from './mystudents/mystudents.component';
+import { AnalyticsComponent } from './analytics/analytics.component';
+
+import { Tabs } from './tabcontrol/tabs';
+import { Tab } from './tabcontrol/tab';
+
+import { Ng4LoadingSpinnerModule } from 'ng4-loading-spinner';
+import { CourseadminComponent } from './courseadmin/courseadmin.component';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { HttpClient, HttpClientModule, HttpClientJsonpModule, HTTP_INTERCEPTORS } from '@angular/common/http';
+import { ReactiveFormsModule } from '@angular/forms';
+import { UserAdmin } from './useradmin/useradmin.component';
+import { GenericDialogComponent } from './generic-dialog/generic-dialog.component';
+
+import { MatDialogModule, MatTableModule, MatFormFieldModule, MatInputModule, MatButtonModule, MatIconModule, MatSelectModule, MatListModule } from '@angular/material';
+import { CdkTableModule } from '@angular/cdk/table';
+
+import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
+import { AddCourseDialogComponent } from './add-course-dialog/add-course-dialog.component';
+import { DeleteCourseDialogComponent } from './delete-course-dialog/delete-course-dialog.component';
+import { CourseProvisioningInfoDialogComponent } from './course-provisioning-info-dialog/course-provisioning-info-dialog.component';
+import { DragDropModule } from '@angular/cdk/drag-drop';
+import { TutorialAdminComponent } from './tutorialadmin/tutorialadmin.component';
+import { UserTutorialDialogComponent } from './user-tutorial-dialog/user-tutorial-dialog.component';
+
+/*Authentication*/
+import { MsalModule, MsalInterceptor } from '@azure/msal-angular';
+import { SilentStartComponent } from './silent-start/silent-start.component';
+import { SilentEndComponent } from './silent-end/silent-end.component';
+import { AuthService } from './auth.service';
+
+const appRoutes: Routes = [
+ { path: '', redirectTo: 'home', pathMatch: 'full' },
+ { path: 'home', component: HomeComponent },
+ { path: 'question/:id', component: QuestionComponent, runGuardsAndResolvers: 'always' },
+ { path: 'config', component: ConfigComponent },
+ { path: 'mystudents', component: MyStudentsComponent },
+ { path: 'analytics', component: AnalyticsComponent },
+ { path: 'courseadmin', component: CourseadminComponent },
+ { path: 'app-silent-start', component: SilentStartComponent },
+ { path: 'app-silent-end', component: SilentEndComponent },
+
+
+ { path: 'app-useradmin', component: UserAdmin },
+ { path: 'tutorialadmin', component: TutorialAdminComponent },
+ { path: 'courseinfo', component: CourseProvisioningInfoDialogComponent },
+ { path: '**', component: HomeComponent }
+];
+
+@NgModule({
+ declarations: [
+ AppComponent,
+ HomeComponent,
+ NavMenuComponent,
+ QuestionComponent,
+ ConfigComponent,
+ MyStudentsComponent,
+ AnalyticsComponent,
+ Tabs,
+ Tab,
+ CourseadminComponent,
+ UserAdmin,
+ GenericDialogComponent,
+ AddCourseDialogComponent,
+ DeleteCourseDialogComponent,
+ CourseProvisioningInfoDialogComponent,
+ TutorialAdminComponent,
+ UserTutorialDialogComponent,
+ SilentStartComponent,
+ SilentEndComponent
+ ],
+ imports: [BrowserModule, FormsModule, HttpModule, Ng4LoadingSpinnerModule.forRoot(),
+ RouterModule.forRoot(appRoutes, { onSameUrlNavigation: 'reload' }),
+ BrowserAnimationsModule,
+ HttpClientModule,
+ HttpClientJsonpModule,
+ ReactiveFormsModule,
+ MatDialogModule,
+ FontAwesomeModule,
+ MatTableModule,
+ MatFormFieldModule,
+ MatInputModule,
+ CdkTableModule,
+ MatButtonModule,
+ MatIconModule,
+ MatSelectModule,
+ MatListModule,
+ DragDropModule
+ ],
+ entryComponents: [GenericDialogComponent, AddCourseDialogComponent, DeleteCourseDialogComponent, UserTutorialDialogComponent],
+ providers: [{ provide: 'BASE_URL', useFactory: getBaseUrl }, AppService, AuthService],
+ bootstrap: [AppComponent]
+})
+export class AppModule { }
+
+export function getBaseUrl() {
+ return document.getElementsByTagName('base')[0].href;
+}
diff --git a/Source/DashboardTabApp/src/app/app.service.ts b/Source/DashboardTabApp/src/app/app.service.ts
new file mode 100644
index 0000000..2b2e955
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/app.service.ts
@@ -0,0 +1,167 @@
+import { Http, Headers, RequestOptions } from '@angular/http';
+import { Injectable, Inject } from "@angular/core";
+import { map } from 'rxjs/operators';
+import { Observable } from 'rxjs';
+import { User } from './models/User';
+import { Question } from './models/Question';
+import { TeamGroupDetail } from './models/TeamGroupDetail';
+import { TeamChannel } from './models/TeamChannel';
+import { Course } from './models/Course';
+import { Student } from './models/Student';
+import { environment } from './../environments/environment';
+import { UserCourseRole } from './models/UserCourseRoleModel';
+import { TutorialGroup } from './models/TutorialGroup';
+import { AuthService } from './auth.service';
+
+
+@Injectable()
+export class AppService {
+ http: Http;
+ baseUrl: string;
+ options: RequestOptions;
+
+ constructor(http: Http,
+ @Inject('BASE_URL') baseUrl: string,
+ private authService: AuthService) {
+ this.http = http;
+ this.baseUrl = environment.apiBaseUrl;
+
+ this.setHeaders();
+ }
+
+ setHeaders() {
+ let headers = new Headers({
+ 'Content-Type': 'application/json',
+ 'X-Frame-Options': 'SAMEORIGIN',
+ 'Authorization': 'Bearer ' + this.authService.token
+
+ });
+
+ this.options = new RequestOptions({ headers: headers });
+ }
+
+
+ initializeBotService(): Observable {
+ return this.http.post(this.baseUrl + 'InitializeBotService', "", this.options);
+ }
+
+ getUserAccess(upn: string): Observable {
+ return this.http.get(this.baseUrl + 'GetUserAccess?upn=' + upn, this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ getUserByUpn(upn: string): Observable {
+ return this.http.post(this.baseUrl + 'GetUserByUpn', JSON.stringify(upn), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ getAllQuestions(tenantId: string): Observable {
+ return this.http.post(this.baseUrl + 'GetAllQuestions', JSON.stringify(tenantId), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ getTeamGroupIdsWithQuestions(tenantId: string, upn: string): Observable {
+ return this.http.post(this.baseUrl + 'GetTeamGroupIdsWithQuestions', JSON.stringify({ tenantId: tenantId, upn: upn }), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ getOwnedTeams(tenantId: string, upn: string): Observable {
+ return this.http.post(this.baseUrl + 'GetOwnedTeams', JSON.stringify({ tenantId: tenantId, upn: upn }), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ getTeamGroupDetail(groupId: string): Observable {
+ return this.http.post(this.baseUrl + 'GetTeamGroupDetail', JSON.stringify(groupId), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ getTeamChannels(groupId: string): Observable {
+ return this.http.post(this.baseUrl + 'GetTeamChannels', JSON.stringify(groupId), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ getQuestionsByGroup(groupId: string): Observable {
+ return this.http.post(this.baseUrl + 'GetQuestionsByGroup', JSON.stringify(groupId), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ getQuestionsByTutorial(tenantId: string, code: string): Observable {
+ return this.http.post(this.baseUrl + 'GetQuestionsByTutorial', JSON.stringify({ tenantId: tenantId, code: code }), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ getCourses(): Observable {
+ return this.http.get(this.baseUrl + 'GetCourses', this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ saveCourse(course: Course): Observable {
+ return this.http.post(this.baseUrl + 'SaveCourse', course, this.options)// to actually just call Bot api
+ .pipe(map(res => res.json()));
+ }
+
+ deleteCourse(id: number): Observable {
+ return this.http.post(this.baseUrl + 'DeleteCourse', id, this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ addStudents(students: Student[]): Observable {
+ return this.http.post(this.baseUrl + 'AddStudents', students, this.options)// to actually just call Bot api
+ .pipe(map(res => res.json()));
+ }
+
+ getPredictiveQnAThreshold(): Observable {
+ return this.http.get(this.baseUrl + 'GetPredictiveQnAThreshold', this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ setPredictiveQnAThreshold(threshold: string): Observable {
+ return this.http.post(this.baseUrl + 'SetPredictiveQnAThreshold', JSON.stringify(threshold), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ searchAndGetTimeUrl(phrase: string): Observable {
+ return this.http.post(this.baseUrl + 'SearchAndGetTimeUrl', JSON.stringify(phrase), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ getUserCourseRoleMappingsByCourse(courseId: number): Observable {
+ return this.http.post(this.baseUrl + 'GetUserCourseRoleMappingsByCourse', JSON.stringify(courseId), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ deleteUserCourseRoleMapping(user: any): Observable {
+ return this.http.post(this.baseUrl + 'DeleteUserCourseRoleMapping', JSON.stringify(user), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ saveUserCourseRoleMapping(user: any): Observable {
+ return this.http.post(this.baseUrl + 'SaveUserCourseRoleMapping', JSON.stringify(user), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ refreshUsers(course: Course): Observable {
+ return this.http.post(this.baseUrl + 'RefreshUsers', JSON.stringify(course), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ getRoles(): Observable {
+ return this.http.get(this.baseUrl + 'GetRoles', this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ getTutorialsByCourse(courseId: number): Observable {
+ return this.http.post(this.baseUrl + 'GetTutorialsByCourse', JSON.stringify(courseId), this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ saveTutorial(tutorial: TutorialGroup): Observable {
+ return this.http.post(this.baseUrl + 'SaveTutorialGroup', tutorial, this.options)
+ .pipe(map(res => res.json()));
+ }
+
+ deleteTutorial(tutorial: TutorialGroup): Observable {
+ return this.http.post(this.baseUrl + 'DeleteTutorialGroup', tutorial, this.options)
+ .pipe(map(res => res.json()));
+ }
+}
diff --git a/Source/DashboardTabApp/src/app/auth.service.spec.ts b/Source/DashboardTabApp/src/app/auth.service.spec.ts
new file mode 100644
index 0000000..f3d964d
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/auth.service.spec.ts
@@ -0,0 +1,12 @@
+import { TestBed } from '@angular/core/testing';
+
+import { AuthService } from './auth.service';
+
+describe('AuthService', () => {
+ beforeEach(() => TestBed.configureTestingModule({}));
+
+ it('should be created', () => {
+ const service: AuthService = TestBed.get(AuthService);
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/Source/DashboardTabApp/src/app/auth.service.ts b/Source/DashboardTabApp/src/app/auth.service.ts
new file mode 100644
index 0000000..f428ecc
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/auth.service.ts
@@ -0,0 +1,166 @@
+import { Injectable } from '@angular/core';
+import * as microsoftTeams from '@microsoft/teams-js';
+import * as authContext from 'adal-angular/lib/adal';
+import { environment } from './../environments/environment';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthService {
+ context;
+ config;
+
+ token: string;
+
+ showSignInButton: boolean = false;
+ loggedIn: boolean = false;
+
+ private loadNav: () => void;
+ onAuthUpdate(fn: () => void) {
+ this.loadNav = fn;
+ }
+
+ constructor() {
+ this.config = {
+ clientId: environment.authConfig.clientId,
+ tenant: environment.authConfig.tenantId,
+ // redirectUri must be in the list of redirect URLs for the Azure AD app
+ redirectUri: window.location.origin + environment.authConfig.redirectUri,
+ cacheLocation: environment.authConfig.cacheLocation,
+ navigateToLoginRequestUrl: environment.authConfig.navigateToLoginRequestUrl,
+ popUp: environment.authConfig.popUp,
+ extraQueryParameters: environment.authConfig.extraQueryParameters,
+ postLogoutRedirectUri: window.location.origin
+ };
+ }
+
+ getToken() {
+ console.log("getToken");
+
+ let context = new authContext(this.config);
+ // try get cached token
+ let token = context.getCachedToken(this.config.clientId);
+ if (token) {
+ // cache token success
+ this.token = token;
+ this.loggedIn = true;
+ this.showSignInButton = false;
+
+ console.log("token saved");
+ this.loadNav();
+ } else {
+ console.log("no cachedToken");
+ // No token, or token is expired
+ var callback = (function (err1, idToken) {
+ if (err1) {
+ // token renew fail
+ this.showSignInButton = true;
+ this.loggedIn = false;
+
+ console.log("renew fail: " + err1);
+ } else {
+ // token renew success
+ this.token = idToken;
+ this.loggedIn = true;
+ this.showSignInButton = false;
+
+ console.log("renew success");
+ this.loadNav();
+ }
+ }).bind(this);
+ context._renewIdToken(callback);
+ }
+ }
+
+ signOut() {
+ let context = new authContext(this.config);
+ context.logOut();
+ }
+
+ signIn() {
+ // try get token from AAD
+ let context = new authContext(this.config);
+
+ var signInSuccessCallback = (function (result) {
+ // AuthenticationContext is a singleton
+ let config = {
+ clientId: this.config.clientId,
+ tenant: this.config.tenantId,
+ // redirectUri must be in the list of redirect URLs for the Azure AD app
+ redirectUri: window.location.origin + this.config.redirectUri,
+ cacheLocation: this.config.cacheLocation,
+ navigateToLoginRequestUrl: this.config.navigateToLoginRequestUrl,
+ extraQueryParameters: this.config.extraQueryParameters,
+ };
+ let context = new authContext(config);
+ let idToken = context.getCachedToken(config.clientId);
+ if (idToken) {
+ this.showSignInButton = false;
+ this.loggedIn = true;
+ this.token = idToken;
+
+ console.log("auth success");
+ this.loadNav();
+ } else {
+ this.loggedIn = false;
+ this.showSignInButton = true;
+ console.log("auth success but no token");
+ };
+ }).bind(this);
+
+ var signInFailCallback = (function (reason) {
+ this.loggedIn = false;
+ this.showSignInButton = true;
+ console.log("Login failed: " + reason);
+
+ if (reason === "CancelledByUser" || reason === "FailedToOpenWindow") {
+ console.log("Login was blocked by popup blocker or canceled by user.");
+ }
+ }).bind(this);
+
+ var msTeamsAuthenticate = (function () {
+ microsoftTeams.authentication.authenticate({
+ url: window.location.origin + environment.authConfig.popUpUri,
+ width: environment.authConfig.popUpWidth,
+ height: environment.authConfig.popUpHeight,
+ successCallback: signInSuccessCallback,
+ failureCallback: signInFailCallback
+ });
+ });
+
+ var acquireTokencallback = (function (err, idToken) {
+ // no token
+ if (err) {
+ console.log("acquire token failed: " + err);
+ //context.login();
+
+ microsoftTeams.initialize(msTeamsAuthenticate);
+
+ } else {
+ this.showSignInButton = false;
+ this.loggedIn = true;
+ this.token = idToken;
+
+ console.log("acquire token success");
+ this.loadNav();
+ }
+ }).bind(this);
+ context.acquireToken(environment.authConfig.instance, acquireTokencallback);
+ }
+
+ onRenewSuccess(idToken) {
+ // token renew success
+ this.token = idToken;
+ this.loggedIn = true;
+ this.showSignInButton = false;
+ console.log("renew success");
+ }
+
+ onRenewFailure(err1) {
+ // token renew fail
+ this.showSignInButton = true;
+ this.loggedIn = false;
+
+ console.log("renew fail" + err1);
+ }
+}
diff --git a/Source/DashboardTabApp/src/app/config/config.component.html b/Source/DashboardTabApp/src/app/config/config.component.html
new file mode 100644
index 0000000..b5f2889
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/config/config.component.html
@@ -0,0 +1,2 @@
+Hello!
+All ready to go! Click save to proceed.
diff --git a/Source/DashboardTabApp/src/app/config/config.component.ts b/Source/DashboardTabApp/src/app/config/config.component.ts
new file mode 100644
index 0000000..23dde17
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/config/config.component.ts
@@ -0,0 +1,42 @@
+import { OnInit, Component } from "@angular/core";
+import * as microsoftTeams from '@microsoft/teams-js';
+
+@Component({
+ selector: 'config',
+ templateUrl: './config.component.html'
+})
+export class ConfigComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit() {
+ console.log('ngOnInit');
+ // initialize teams
+ microsoftTeams.initialize();
+ // get context
+ microsoftTeams.getContext((context: microsoftTeams.Context) => {
+ console.log('getContext');
+ this.setValidityState(true);
+ });
+
+ microsoftTeams.settings.registerOnSaveHandler((saveEvent: microsoftTeams.settings.SaveEvent) => {
+ // Calculate host dynamically to enable local debugging
+ let host = "https://" + window.location.host;
+
+ microsoftTeams.settings.setSettings({
+ contentUrl: host + "/#/home",
+ suggestedDisplayName: "Questions",
+ removeUrl: host + "/remove",
+ entityId: "1"
+ });
+
+ saveEvent.notifySuccess();
+ });
+
+ }
+
+ public setValidityState(val: boolean) {
+ microsoftTeams.settings.setValidityState(val);
+ }
+
+}
diff --git a/Source/DashboardTabApp/src/app/course-provisioning-info-dialog/course-provisioning-info-dialog.component.css b/Source/DashboardTabApp/src/app/course-provisioning-info-dialog/course-provisioning-info-dialog.component.css
new file mode 100644
index 0000000..1963dd1
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/course-provisioning-info-dialog/course-provisioning-info-dialog.component.css
@@ -0,0 +1,3 @@
+/deep/ .col-sm-3 {
+ display: none;
+}
diff --git a/Source/DashboardTabApp/src/app/course-provisioning-info-dialog/course-provisioning-info-dialog.component.html b/Source/DashboardTabApp/src/app/course-provisioning-info-dialog/course-provisioning-info-dialog.component.html
new file mode 100644
index 0000000..681bab2
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/course-provisioning-info-dialog/course-provisioning-info-dialog.component.html
@@ -0,0 +1,21 @@
+
+ Course Provisioning Information
+
+
+
+
Table field details
+
+
+ PredictiveQnAServiceHost: Host property + “/” when the QnA maker is published. 1
+ PredictiveQnAKnowledgeBaseId: GUID part of the POST command
+ PredictiveQnAEndpointKey: GUID part of Authorization.
+ PredictiveQnAHttpEndpoint: Endpoint of the Cognitive Service.
+ PredictiveQnAHttpKey: Key of the Cognitive Service.
+ PredictiveQnAKnowledgeBaseName: Name of knowledgebase for the course on QnA Maker.
+ PredictiveQnAConfidenceThreshold: Integer that should be from 0-100 that reflects the confidence percentage an answer from QnA Maker must be if it is to be supplied as an answer to a question.
+
+
+
+
+ OK
+
diff --git a/Source/DashboardTabApp/src/app/course-provisioning-info-dialog/course-provisioning-info-dialog.component.spec.ts b/Source/DashboardTabApp/src/app/course-provisioning-info-dialog/course-provisioning-info-dialog.component.spec.ts
new file mode 100644
index 0000000..7451ee3
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/course-provisioning-info-dialog/course-provisioning-info-dialog.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CourseProvisioningInfoDialogComponent } from './course-provisioning-info-dialog.component';
+
+describe('CourseProvisioningInfoDialogComponent', () => {
+ let component: CourseProvisioningInfoDialogComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ CourseProvisioningInfoDialogComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CourseProvisioningInfoDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/Source/DashboardTabApp/src/app/course-provisioning-info-dialog/course-provisioning-info-dialog.component.ts b/Source/DashboardTabApp/src/app/course-provisioning-info-dialog/course-provisioning-info-dialog.component.ts
new file mode 100644
index 0000000..b4d95d4
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/course-provisioning-info-dialog/course-provisioning-info-dialog.component.ts
@@ -0,0 +1,21 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { window } from 'rxjs/operators';
+//import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; // in case we need to inject data to this page later on
+
+@Component({
+ selector: 'app-course-provisioning-info-dialog',
+ templateUrl: './course-provisioning-info-dialog.component.html',
+ styleUrls: ['./course-provisioning-info-dialog.component.css']
+})
+export class CourseProvisioningInfoDialogComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit() { }
+
+
+ onOKClick(): void {
+ close();
+ }
+
+}
diff --git a/Source/DashboardTabApp/src/app/courseadmin/courseadmin.component.css b/Source/DashboardTabApp/src/app/courseadmin/courseadmin.component.css
new file mode 100644
index 0000000..c815e61
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/courseadmin/courseadmin.component.css
@@ -0,0 +1,58 @@
+
+.k-link {
+ white-space: pre-line;
+ font-size: small;
+}
+
+.td {
+ font-size: smaller;
+}
+
+.k-command-cell {
+ display: flex;
+ padding-left: 5px !important;
+}
+
+tr {
+ white-space: pre;
+}
+
+.k-button k-grid-remove-command {
+ font-size: smaller;
+}
+
+input.mat-input-element {
+ text-overflow: ellipsis;
+ font-size: small;
+ max-width: 50%;
+}
+
+.mat-header-cell {
+ font-size: 12px;
+ background-color: aliceblue;
+ padding-right: 5px;
+ /*text-align: center;*/
+ /*padding-left: 5px;*/
+}
+
+.mat-cell:first-of-type, mat-footer-cell:first-of-type, mat-header-cell:first-of-type {
+ padding-left: 12px !important;
+}
+
+.lastColumn {
+ max-width: 10%;
+}
+
+.mat-button {
+ min-width: 50px!important;
+}
+
+.link {
+ color: blue;
+ text-decoration: underline;
+ cursor: pointer;
+}
+/*mat-cell:last-of-type, mat-footer-cell:last-of-type, mat-header-cell:last-of-type {
+ flex:none;
+ padding-right:0!important;
+}*/
diff --git a/Source/DashboardTabApp/src/app/courseadmin/courseadmin.component.html b/Source/DashboardTabApp/src/app/courseadmin/courseadmin.component.html
new file mode 100644
index 0000000..3adbaba
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/courseadmin/courseadmin.component.html
@@ -0,0 +1,97 @@
+Course Admin
+Course provisioning instructions
+
+
+ add New Course
+
+
+
+
+
+
+ Course Name
+
+ {{course.name}}
+
+
+
+
+ Service Host
+
+
+
+
+
+
+
+
+ KnowledgeBase Id
+
+
+
+
+
+
+
+
+ Endpoint Key
+
+
+
+
+
+
+
+
+ Http Endpoint
+
+
+
+
+
+
+
+
+ Http Key
+
+
+
+
+
+
+
+
+ KnowledgeBase Name
+
+
+
+
+
+
+
+
+ Confidence Threshold
+
+
+
+
+
+
+
+
+
+
+ delete
+ save
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/DashboardTabApp/src/app/courseadmin/courseadmin.component.ts b/Source/DashboardTabApp/src/app/courseadmin/courseadmin.component.ts
new file mode 100644
index 0000000..2f491d1
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/courseadmin/courseadmin.component.ts
@@ -0,0 +1,157 @@
+import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
+import { AppService } from '../app.service';
+import { Course } from '../models/Course';
+import { Observable } from 'rxjs';
+import { FormGroup, FormControl, Validators } from '@angular/forms';
+import { ViewEncapsulation, ViewChild } from '@angular/core';
+//import { TooltipDirective } from '@progress/kendo-angular-tooltip';
+import { MatTableDataSource, MatDialog } from '@angular/material';
+import { environment } from 'src/environments/environment';
+import { AddCourseDialogComponent } from '../add-course-dialog/add-course-dialog.component';
+import { GenericDialogComponent } from '../generic-dialog/generic-dialog.component';
+import { DeleteCourseDialogComponent } from '../delete-course-dialog/delete-course-dialog.component';
+import { CourseProvisioningInfoDialogComponent } from '../course-provisioning-info-dialog/course-provisioning-info-dialog.component';
+import { Router, ActivatedRoute } from '@angular/router';
+import { window } from 'rxjs/operators';
+
+
+@Component({
+ selector: 'courseadmin',
+ templateUrl: './courseadmin.component.html',
+ styleUrls: ['./courseadmin.component.css'],
+ encapsulation: ViewEncapsulation.None
+})
+
+
+export class CourseadminComponent implements OnInit {
+ @ViewChild('table', { static: false }) table: any;
+ appService: AppService;
+ courses: Course[];
+ displayedColumns = ['courseName', 'predictiveQnAServiceHost', 'predictiveQnAKnowledgeBaseId', 'predictiveQnAEndpointKey'
+ , 'predictiveQnAHttpEndpoint', 'predictiveQnAHttpKey', 'predictiveQnAKnowledgeBaseName', 'predictiveQnAConfidenceThreshold', 'deleteButton'];
+ dataSource;
+
+ public formGroup: FormGroup;
+
+ private editedRowIndex: number;
+ router: Router;
+
+ constructor(appService: AppService, public dialog: MatDialog, router: Router) {
+ this.appService = appService;
+ this.router = router;
+ }
+
+ ngOnInit() {
+ this.appService.getCourses()
+ .subscribe(courses => {
+ this.courses = courses;
+ this.dataSource = new MatTableDataSource(this.courses);
+ });
+ }
+
+ editCourse(course: any) {
+ if (course.id == 0) {
+ alert("Please save this course first before editing.");
+ } else {
+ this.router.navigate(['usertutorialsetup/'], { queryParams: course} );
+
+ }
+ console.log(course)
+ }
+
+ addRow() {
+
+ this.appService.getOwnedTeams(environment.tid, environment.upn).subscribe(ownedTeams => {
+ var teams: any = ownedTeams;
+ teams.value.forEach((t: any, index, array) => {
+ this.courses.forEach(c => {
+ if (t.displayName == c.name) {
+ array.splice(index, 1);
+ }
+ });
+ });
+ //check against teams already in the table
+ const dialogRef = this.dialog.open(AddCourseDialogComponent, {
+ width: '250px',
+ data: teams.value
+ });
+
+ dialogRef.afterClosed().subscribe(res => {
+ console.log("Dialog result: ", res)
+ if (res) {
+ var newCourse: Course = {
+ id: 0,
+ name: res.displayName,
+ predictiveQnAServiceHost: "",
+ predictiveQnAKnowledgeBaseId: "",
+ predictiveQnAEndpointKey: "",
+ predictiveQnAHttpEndpoint: "",
+ predictiveQnAHttpKey: "",
+ predictiveQnAKnowledgeBaseName: "",
+ predictiveQnAConfidenceThreshold: "",
+ deployedURL: "",
+ groupId: res.id,
+ edited: false
+ }
+ this.courses.push(newCourse);
+ this.dataSource = new MatTableDataSource(this.courses);
+ }
+ });
+ });
+
+ }
+
+ deleteRow(row: number) {
+ var courseToDeleteID = this.courses[row].id;
+ var courseName = this.dataSource.data[row].name;
+ const dialogRef = this.dialog.open(DeleteCourseDialogComponent, {
+ width: '250px',
+ data: { courseName: courseName, courseToDeleteID: courseToDeleteID }
+ });
+ dialogRef.afterClosed().subscribe(res => {
+ console.log("Dialog result: ", res)
+ if (res) {
+ if (res > 0) {
+ this.appService.deleteCourse(res)
+ .subscribe(courses => {
+ this.courses = courses;
+ this.courses.splice(row, 1);
+ this.dataSource = new MatTableDataSource(this.courses);
+ });
+ } else {
+ this.courses.splice(row, 1);
+ this.dataSource = new MatTableDataSource(this.courses);
+ }
+ }
+ });
+ }
+
+ saveRow(course: Course) {
+ //this.editService.save(course, isNew);
+ this.appService.saveCourse(course)
+ .subscribe(courses => {
+ if (courses != null) {// api returns null if an exception is caught
+ this.openDialog("Success", "Courses successfully saved.")
+
+ } else {
+ this.openDialog("Failure", "Courses were not saved, try again.")
+ }
+ this.courses = courses;
+ this.dataSource = new MatTableDataSource(this.courses);
+
+ });
+ }
+
+ openInstructions() {
+ var height = outerHeight * (4 / 5);
+ var width = outerWidth * (2 / 3);
+ open("#/courseinfo", "test", "height=" + height + ", width =" + width);
+ }
+
+ openDialog(outcome: string, message: string): void {
+ const dialogRef = this.dialog.open(GenericDialogComponent, {
+ width: '250px',
+ data: { outcome: outcome, message: message }
+ });
+ }
+}
diff --git a/Source/DashboardTabApp/src/app/delete-course-dialog/delete-course-dialog.component.html b/Source/DashboardTabApp/src/app/delete-course-dialog/delete-course-dialog.component.html
new file mode 100644
index 0000000..335ad6d
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/delete-course-dialog/delete-course-dialog.component.html
@@ -0,0 +1,8 @@
+Delete Course
+
+
Are you sure you want to delete {{courseData.courseName}}?
+
+
+ Yes
+ No
+
diff --git a/Source/DashboardTabApp/src/app/delete-course-dialog/delete-course-dialog.component.scss b/Source/DashboardTabApp/src/app/delete-course-dialog/delete-course-dialog.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/Source/DashboardTabApp/src/app/delete-course-dialog/delete-course-dialog.component.spec.ts b/Source/DashboardTabApp/src/app/delete-course-dialog/delete-course-dialog.component.spec.ts
new file mode 100644
index 0000000..d5cd693
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/delete-course-dialog/delete-course-dialog.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DeleteCourseDialogComponent } from './delete-course-dialog.component';
+
+describe('DeleteCourseDialogComponent', () => {
+ let component: DeleteCourseDialogComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ DeleteCourseDialogComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DeleteCourseDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/Source/DashboardTabApp/src/app/delete-course-dialog/delete-course-dialog.component.ts b/Source/DashboardTabApp/src/app/delete-course-dialog/delete-course-dialog.component.ts
new file mode 100644
index 0000000..e499910
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/delete-course-dialog/delete-course-dialog.component.ts
@@ -0,0 +1,27 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+
+
+@Component({
+ selector: 'app-delete-course-dialog',
+ templateUrl: './delete-course-dialog.component.html',
+ styleUrls: ['./delete-course-dialog.component.scss']
+})
+export class DeleteCourseDialogComponent implements OnInit {
+ courseData: any;
+
+ constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any) {
+ this.courseData = data;
+ }
+
+ ngOnInit() {
+ }
+
+ onYesClick(): void {
+ this.dialogRef.close(this.courseData.courseToDeleteID);
+ }
+
+ onNoClick(): void {
+ this.dialogRef.close();
+ }
+}
diff --git a/Source/DashboardTabApp/src/app/edit.service.ts b/Source/DashboardTabApp/src/app/edit.service.ts
new file mode 100644
index 0000000..c696afe
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/edit.service.ts
@@ -0,0 +1,79 @@
+import { Injectable } from '@angular/core';
+import { Observable, BehaviorSubject } from 'rxjs';
+import { HttpClient } from '@angular/common/http';
+
+import { tap, map } from 'rxjs/operators';
+import { AppService } from './app.service';
+
+const CREATE_ACTION = 'create';
+const UPDATE_ACTION = 'update';
+const REMOVE_ACTION = 'destroy';
+
+@Injectable()
+export class EditService extends BehaviorSubject {
+ appService: AppService;
+
+ constructor(private http: HttpClient, appService: AppService) {
+ super([]);
+ this.appService = appService;
+ }
+
+ private data: any[] = [];
+
+ public read() {
+ if (this.data.length) {
+ return super.next(this.data);
+ }
+
+ this.fetch()
+ .pipe(
+ tap(data => {
+ this.data = data;
+ })
+ )
+ .subscribe(data => {
+ super.next(data);
+ });
+ }
+
+ public save(data: any, isNew?: boolean) {
+ const action = isNew ? CREATE_ACTION : UPDATE_ACTION;
+
+ this.reset();
+
+ this.fetch(action, data)
+ .subscribe(() => this.read(), () => this.read());
+ }
+
+ public remove(data: any) {
+ this.reset();
+
+ this.fetch(REMOVE_ACTION, data)
+ .subscribe(() => this.read(), () => this.read());
+ }
+
+ public resetItem(dataItem: any) {
+ if (!dataItem) { return; }
+
+ // find orignal data item
+ const originalDataItem = this.data.find(item => item.ProductID === dataItem.ProductID);
+
+ // revert changes
+ Object.assign(originalDataItem, dataItem);
+
+ super.next(this.data);
+ }
+
+ private reset() {
+ this.data = [];
+ }
+
+ private fetch(action: string = '', data?: any): Observable {
+ return this.appService.getCourses()
+ .pipe(map(res => res));
+ }
+
+ private serializeModels(data?: any): string {
+ return data ? `&models=${JSON.stringify([data])}` : '';
+ }
+}
diff --git a/Source/DashboardTabApp/src/app/generic-dialog/generic-dialog.component.css b/Source/DashboardTabApp/src/app/generic-dialog/generic-dialog.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/Source/DashboardTabApp/src/app/generic-dialog/generic-dialog.component.html b/Source/DashboardTabApp/src/app/generic-dialog/generic-dialog.component.html
new file mode 100644
index 0000000..48d6dcc
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/generic-dialog/generic-dialog.component.html
@@ -0,0 +1,7 @@
+{{data.outcome}}
+
+
+ OK
+
diff --git a/Source/DashboardTabApp/src/app/generic-dialog/generic-dialog.component.spec.ts b/Source/DashboardTabApp/src/app/generic-dialog/generic-dialog.component.spec.ts
new file mode 100644
index 0000000..f2529c9
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/generic-dialog/generic-dialog.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { GenericDialogComponent } from './generic-dialog.component';
+
+describe('GenericDialogComponent', () => {
+ let component: GenericDialogComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ GenericDialogComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(GenericDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/Source/DashboardTabApp/src/app/generic-dialog/generic-dialog.component.ts b/Source/DashboardTabApp/src/app/generic-dialog/generic-dialog.component.ts
new file mode 100644
index 0000000..48c6f7b
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/generic-dialog/generic-dialog.component.ts
@@ -0,0 +1,21 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+
+@Component({
+ selector: 'app-generic-dialog',
+ templateUrl: './generic-dialog.component.html',
+ styleUrls: ['./generic-dialog.component.css']
+})
+export class GenericDialogComponent implements OnInit {
+
+ constructor(
+ public dialogRef: MatDialogRef,
+ @Inject(MAT_DIALOG_DATA) public data: any) { }
+
+ ngOnInit() { }
+
+
+ onNoClick(): void {
+ this.dialogRef.close();
+ }
+}
diff --git a/Source/DashboardTabApp/src/app/home/home.component.html b/Source/DashboardTabApp/src/app/home/home.component.html
new file mode 100644
index 0000000..90f7074
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/home/home.component.html
@@ -0,0 +1,3 @@
+
+
+Please sign in to continue
diff --git a/Source/DashboardTabApp/src/app/home/home.component.ts b/Source/DashboardTabApp/src/app/home/home.component.ts
new file mode 100644
index 0000000..527798a
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/home/home.component.ts
@@ -0,0 +1,25 @@
+
+///
+import { Component } from '@angular/core';
+import { AuthService } from '../auth.service';
+
+@Component({
+ selector: 'home',
+ templateUrl: './home.component.html'
+})
+export class HomeComponent {
+ isIframe: boolean;
+ title = 'app';
+
+ constructor(public authService: AuthService) {
+ this.isIframe = window !== window.parent && !window.opener;
+
+ //alert("home");
+ authService.getToken();
+
+ }
+
+ public SignIn(event: any) {
+ this.authService.signIn();
+ }
+}
diff --git a/Source/DashboardTabApp/src/app/models/Course.ts b/Source/DashboardTabApp/src/app/models/Course.ts
new file mode 100644
index 0000000..93d5b72
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/models/Course.ts
@@ -0,0 +1,14 @@
+export class Course {
+ id: number = 0;
+ name: string = "";
+ predictiveQnAServiceHost: string = "";
+ predictiveQnAKnowledgeBaseId: string = "";
+ predictiveQnAEndpointKey: string = "";
+ predictiveQnAHttpEndpoint: string = "";
+ predictiveQnAHttpKey: string = "";
+ predictiveQnAKnowledgeBaseName: string = "";
+ predictiveQnAConfidenceThreshold: string = "";
+ deployedURL: string = "";
+ groupId: string = "";
+ edited: boolean = false; // true if edited or new
+}
diff --git a/Source/DashboardTabApp/src/app/models/Question.ts b/Source/DashboardTabApp/src/app/models/Question.ts
new file mode 100644
index 0000000..c2998c6
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/models/Question.ts
@@ -0,0 +1,18 @@
+import { User } from "./User";
+
+export class Question {
+ id: number = 0;
+ teamId: string = "";
+ teamName: string = "";
+ conversationId: string = "";
+ messageId: string = "";
+ topic: string = "";
+ questionStatus: string = "";
+ questionText: string = "";
+ originalPoster: User = new User();
+ questionSubmitted: Date | undefined;
+ answerText: string = "";
+ answerPoster: User = new User();
+ questionAnswered: Date | undefined;
+ link: string = "";
+}
diff --git a/Source/DashboardTabApp/src/app/models/Student.ts b/Source/DashboardTabApp/src/app/models/Student.ts
new file mode 100644
index 0000000..3e4b7b9
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/models/Student.ts
@@ -0,0 +1,10 @@
+export class Student {
+ studentID: string = "";
+ firstName: string = "";
+ lastName: string = "";
+ username: string = "";
+ email: string = "";
+ role: string = "";
+ courseName: string = "";
+ tutorialGroupID: string = "";
+}
diff --git a/Source/DashboardTabApp/src/app/models/TeamChannel.ts b/Source/DashboardTabApp/src/app/models/TeamChannel.ts
new file mode 100644
index 0000000..a9d4a85
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/models/TeamChannel.ts
@@ -0,0 +1,5 @@
+export class TeamChannel {
+ id: string;
+ displayName: string;
+ description: string;
+}
diff --git a/Source/DashboardTabApp/src/app/models/TeamGroupDetail.ts b/Source/DashboardTabApp/src/app/models/TeamGroupDetail.ts
new file mode 100644
index 0000000..ff0eb24
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/models/TeamGroupDetail.ts
@@ -0,0 +1,11 @@
+import { SafeUrl } from "@angular/platform-browser";
+
+export class TeamGroupDetail {
+ id: string = "";
+ name: string = "";
+ displayName: string = "";
+ description: string = "";
+ webUrl: string = "";
+ photoByteUrl: string = "";
+ safePhotoByteUrl: SafeUrl;
+}
diff --git a/Source/DashboardTabApp/src/app/models/Tutorial.ts b/Source/DashboardTabApp/src/app/models/Tutorial.ts
new file mode 100644
index 0000000..f4e1a66
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/models/Tutorial.ts
@@ -0,0 +1,7 @@
+export class Tutorial {
+ id: number = 0;
+ code: string;
+ class: string;
+ location: string;
+
+}
diff --git a/Source/DashboardTabApp/src/app/models/TutorialGroup.ts b/Source/DashboardTabApp/src/app/models/TutorialGroup.ts
new file mode 100644
index 0000000..5a986ad
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/models/TutorialGroup.ts
@@ -0,0 +1,6 @@
+export class TutorialGroup {
+ id: number = 0;
+ courseId: number = 0;
+ code: string;
+ name: string;
+}
diff --git a/Source/DashboardTabApp/src/app/models/User.ts b/Source/DashboardTabApp/src/app/models/User.ts
new file mode 100644
index 0000000..52cd577
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/models/User.ts
@@ -0,0 +1,15 @@
+import { Tutorial } from "./Tutorial";
+
+export class User {
+ id: number = 0;
+ studentId: string = "";
+ firstName: string = "";
+ lastName: string = "";
+ userName: string = "";
+ email: string = "";
+ roleName: string = "";
+ tutorialGroupsString: string = "";
+ tutorialGroups: Tutorial[] = new Array();
+ fullName: string = "";
+ isAdmin: boolean = false;
+}
diff --git a/Source/DashboardTabApp/src/app/models/UserCourseRoleModel.ts b/Source/DashboardTabApp/src/app/models/UserCourseRoleModel.ts
new file mode 100644
index 0000000..2583c80
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/models/UserCourseRoleModel.ts
@@ -0,0 +1,10 @@
+export class UserCourseRole {
+ id: number = 0;
+ userId: number = 0;
+ courseId: number = 0;
+ roleId: number = 0;
+ userFullName: string;
+ courseName: string;
+ roleName: string;
+
+}
diff --git a/Source/DashboardTabApp/src/app/mystudents/mystudents.component.css b/Source/DashboardTabApp/src/app/mystudents/mystudents.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/Source/DashboardTabApp/src/app/mystudents/mystudents.component.html b/Source/DashboardTabApp/src/app/mystudents/mystudents.component.html
new file mode 100644
index 0000000..b4fb208
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/mystudents/mystudents.component.html
@@ -0,0 +1,32 @@
+My Students
+Demonstrator dashboard to see their students data
+
+
+ Your tutorial group(s):
+
+ Show all
+ {{tutorial.code}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/DashboardTabApp/src/app/mystudents/mystudents.component.ts b/Source/DashboardTabApp/src/app/mystudents/mystudents.component.ts
new file mode 100644
index 0000000..dc5b1b3
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/mystudents/mystudents.component.ts
@@ -0,0 +1,628 @@
+import { Component, OnInit } from '@angular/core';
+import { AppService } from '../app.service';
+import { Question } from '../models/Question';
+import { User } from '../models/User';
+
+import * as microsoftTeams from '@microsoft/teams-js';
+import * as AdaptiveCards from "adaptivecards";
+import * as markdownit from "markdown-it";
+import * as moment from 'moment-timezone';
+
+@Component({
+ selector: 'mystudents',
+ templateUrl: './mystudents.component.html',
+ styleUrls: ['./mystudents.component.css']
+})
+export class MyStudentsComponent implements OnInit {
+ appService: AppService;
+
+ currentUser: User;
+ userTutorialGroups: string[];
+
+ questions: Question[];
+ unansweredQuestions: Question[];
+ answeredQuestions: Question[];
+
+ context: microsoftTeams.Context;
+ selectedTutorial: string = "ALL";
+
+ constructor(appService: AppService) {
+ this.appService = appService;
+ }
+
+ ngOnInit(): void {
+ microsoftTeams.initialize();
+ // get context
+ microsoftTeams.getContext((context: microsoftTeams.Context) => {
+ this.context = context;
+ let tenantId = this.context.tid;
+ let currentUserEmail = this.context.upn;
+
+ this.appService.getUserByUpn(currentUserEmail)
+ .subscribe(user => {
+ this.currentUser = user;
+ }, error => console.error(error));
+
+ this.appService.getAllQuestions(tenantId)
+ .subscribe(questions => {
+ var cardHolderDiv;
+ this.questions = questions;
+
+ this.unansweredQuestions = this.questions
+ .filter(x => x.questionStatus.trim() == "unanswered")
+ .sort((a, b) => { return new Date(b.questionSubmitted).getTime() - new Date(a.questionSubmitted).getTime(); });
+ this.answeredQuestions = this.questions
+ .filter(x => x.questionStatus.trim() == "answered")
+ .sort((a, b) => { return new Date(b.questionAnswered).getTime() - new Date(a.questionAnswered).getTime(); });
+
+ // create cards --- performance??
+
+ /*** UNANSWERED ***/
+ var unansweredFragment = document.createDocumentFragment();
+ // iterate over questions
+ if (this.unansweredQuestions.length > 0) {
+ // iterate over questions
+ this.unansweredQuestions.forEach(q => {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.setAttribute("id", "unansweredCardHolder");
+ cardHolderDiv.setAttribute("class", "cardHolder");
+ cardHolderDiv.appendChild(this.createCard(q));
+ unansweredFragment.appendChild(cardHolderDiv);
+ });
+ } else {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.innerHTML = "There are no unanswered questions.
";
+ unansweredFragment.appendChild(cardHolderDiv);
+ }
+ // And finally insert it somewhere in your page:
+ document.getElementById("unansweredCardDiv").appendChild(unansweredFragment);
+
+ /*** ANSWERED ***/
+ var answeredFragment = document.createDocumentFragment();
+ if (this.answeredQuestions.length > 0) {
+ // iterate over questions
+ this.answeredQuestions.forEach(q => {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.setAttribute("id", "answeredCardHolder")
+ cardHolderDiv.setAttribute("class", "cardHolder")
+ cardHolderDiv.appendChild(this.createCard(q));
+ answeredFragment.appendChild(cardHolderDiv);
+ });
+ } else {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.innerHTML = "There are no answered questions.
";
+ answeredFragment.appendChild(cardHolderDiv);
+ }
+ // And finally insert it somewhere in your page:
+ document.getElementById("answeredCardDiv").appendChild(answeredFragment);
+ }, error => console.error(error));
+ });
+ }
+
+ createCard(question: Question): any {
+ let answerPosterName = "";
+ if (question.answerPoster != null)
+ answerPosterName = question.answerPoster.fullName;
+
+ var cardUnanswered = {
+ "$schema": "https://adaptivecards.io/schemas/adaptive-card.json",
+ "type": "AdaptiveCard",
+ "version": "1.0",
+ "style": "emphasis",
+ "body": [
+ {
+ "type": "Container",
+ "items": [
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "width": "stretch",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": question.topic,
+ "size": "medium"
+ },
+ {
+ "type": "TextBlock",
+ "text": question.questionText,
+ "weight": "bolder",
+ "wrap": true,
+ "size": "medium"
+ },
+ {
+ "type": "TextBlock",
+ "text": question.answerText,
+ "weight": "bolder",
+ "wrap": true,
+ "size": "medium",
+ "color": "good"
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": "Submitted: ",
+ "weight": "bolder",
+ "wrap": true
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": question.originalPoster.fullName,
+ "weight": "bolder",
+ "wrap": true
+ },
+ {
+ "type": "TextBlock",
+ "spacing": "none",
+ "text": moment.utc(question.questionSubmitted).local().format("DD MMM YYYY, hh:mm a"),
+ "isSubtle": true,
+ "wrap": true
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "actions": [
+ {
+ "type": "Action.OpenUrl",
+ "title": "View Conversation",
+ "url": question.link
+ }
+ ]
+ }
+
+ var cardAnswered = {
+ "$schema": "https://adaptivecards.io/schemas/adaptive-card.json",
+ "type": "AdaptiveCard",
+ "version": "1.0",
+ "style": "emphasis",
+ "body": [
+ {
+ "type": "Container",
+ "items": [
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "width": "stretch",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": question.topic,
+ "size": "medium"
+ },
+ {
+ "type": "TextBlock",
+ "text": question.questionText,
+ "weight": "bolder",
+ "wrap": true,
+ "size": "medium"
+ },
+ {
+ "type": "TextBlock",
+ "text": question.answerText,
+ "weight": "bolder",
+ "wrap": true,
+ "size": "medium",
+ "color": "good"
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": "Submitted: ",
+ "weight": "bolder",
+ "wrap": true
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": question.originalPoster.fullName,
+ "weight": "bolder",
+ "wrap": true
+ },
+ {
+ "type": "TextBlock",
+ "spacing": "none",
+ "text": moment.utc(question.questionSubmitted).local().format("DD MMM YYYY, hh:mm a"),
+ "isSubtle": true,
+ "wrap": true
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": "Answered: ",
+ "weight": "bolder",
+ "wrap": true
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": answerPosterName,
+ "weight": "bolder",
+ "wrap": true
+ },
+ {
+ "type": "TextBlock",
+ "spacing": "none",
+ "text": moment.utc(question.questionAnswered).local().format("DD MMM YYYY, hh:mm a"),
+ "isSubtle": true,
+ "wrap": true
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "actions": [
+ {
+ "type": "Action.OpenUrl",
+ "title": "View Conversation",
+ "url": question.link
+ }
+ ]
+ }
+
+ // Create an AdaptiveCard instance
+ var adaptiveCard = new AdaptiveCards.AdaptiveCard();
+
+ // Set its hostConfig property unless you want to use the default Host Config
+ // Host Config defines the style and behavior of a card
+ adaptiveCard.hostConfig = new AdaptiveCards.HostConfig({
+ "choiceSetInputValueSeparator": ",",
+ "supportsInteractivity": true,
+ "fontFamily": "Segoe UI",
+ "spacing": {
+ "small": 3,
+ "default": 8,
+ "medium": 20,
+ "large": 30,
+ "extraLarge": 40,
+ "padding": 20
+ },
+ "separator": {
+ "lineThickness": 1,
+ "lineColor": "#EEEEEE"
+ },
+ "fontSizes": {
+ "small": 12,
+ "default": 14,
+ "medium": 17,
+ "large": 21,
+ "extraLarge": 26
+ },
+ "fontWeights": {
+ "lighter": 200,
+ "default": 400,
+ "bolder": 600
+ },
+ "imageSizes": {
+ "small": 40,
+ "medium": 80,
+ "large": 160
+ },
+ "containerStyles": {
+ "default": {
+ "foregroundColors": {
+ "default": {
+ "default": "#333333",
+ "subtle": "#EE333333"
+ },
+ "dark": {
+ "default": "#000000",
+ "subtle": "#66000000"
+ },
+ "light": {
+ "default": "#FFFFFF",
+ "subtle": "#33000000"
+ },
+ "accent": {
+ "default": "#2E89FC",
+ "subtle": "#882E89FC"
+ },
+ "good": {
+ "default": "#54a254",
+ "subtle": "#DD54a254"
+ },
+ "warning": {
+ "default": "#e69500",
+ "subtle": "#DDe69500"
+ },
+ "attention": {
+ "default": "#cc3300",
+ "subtle": "#DDcc3300"
+ }
+ },
+ "backgroundColor": "#00000000"
+ },
+ "emphasis": {
+ "foregroundColors": {
+ "default": {
+ "default": "#333333",
+ "subtle": "#EE333333"
+ },
+ "dark": {
+ "default": "#000000",
+ "subtle": "#66000000"
+ },
+ "light": {
+ "default": "#FFFFFF",
+ "subtle": "#33000000"
+ },
+ "accent": {
+ "default": "#2E89FC",
+ "subtle": "#882E89FC"
+ },
+ "good": {
+ "default": "#54a254",
+ "subtle": "#DD54a254"
+ },
+ "warning": {
+ "default": "#e69500",
+ "subtle": "#DDe69500"
+ },
+ "attention": {
+ "default": "#cc3300",
+ "subtle": "#DDcc3300"
+ }
+ },
+ "backgroundColor": "#08000000"
+ }
+ },
+ "actions": {
+ "maxActions": 5,
+ "spacing": "Default",
+ "buttonSpacing": 10,
+ "showCard": {
+ "actionMode": "Inline",
+ "inlineTopMargin": 16,
+ "style": "emphasis"
+ },
+ "preExpandSingleShowCardAction": false,
+ "actionsOrientation": "Horizontal",
+ "actionAlignment": "Right"
+ },
+ "adaptiveCard": {
+ "allowCustomStyle": false
+ },
+ "imageSet": {
+ "imageSize": "Medium",
+ "maxImageHeight": 100
+ },
+ "factSet": {
+ "title": {
+ "size": "Default",
+ "color": "Default",
+ "isSubtle": false,
+ "weight": "Bolder",
+ "warp": true
+ },
+ "value": {
+ "size": "Default",
+ "color": "Default",
+ "isSubtle": false,
+ "weight": "Default",
+ "warp": true
+ },
+ "spacing": 10
+ } // More host config options
+ });
+
+ // Set the adaptive card's event handlers. onExecuteAction is invoked
+ // whenever an action is clicked in the card
+ adaptiveCard.onExecuteAction = function (action: AdaptiveCards.OpenUrlAction) {
+ window.open(action.url, "_blank");
+ }
+
+ // For markdown support
+ AdaptiveCards.AdaptiveCard.onProcessMarkdown = function (text) { return markdownit().render(text); }
+
+ // Parse the card payload
+ if (question.questionAnswered)
+ adaptiveCard.parse(cardAnswered);
+ else
+ adaptiveCard.parse(cardUnanswered);
+
+
+ // Render the card to an HTML element:
+ var renderedCard = adaptiveCard.render();
+
+ return renderedCard;
+ }
+ filterByCode(code): any {
+ this.selectedTutorial = code;
+
+ if (code === "ALL") {
+ this.appService.getAllQuestions(this.context.tid).subscribe(questions => {
+ var cardHolderDiv;
+ this.questions = questions;
+
+ this.unansweredQuestions = this.questions
+ .filter(x => x.questionStatus.trim() == "unanswered")
+ .sort((a, b) => { return new Date(b.questionSubmitted).getTime() - new Date(a.questionSubmitted).getTime(); });
+ this.answeredQuestions = this.questions
+ .filter(x => x.questionStatus.trim() == "answered")
+ .sort((a, b) => { return new Date(b.questionAnswered).getTime() - new Date(a.questionAnswered).getTime(); });
+
+ // create cards --- performance??
+
+ /*** UNANSWERED ***/
+ var unansweredFragment = document.createDocumentFragment();
+ // iterate over questions
+ if (this.unansweredQuestions.length > 0) {
+ // iterate over questions
+ this.unansweredQuestions.forEach(q => {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.setAttribute("id", "unansweredCardHolder");
+ cardHolderDiv.setAttribute("class", "cardHolder");
+ cardHolderDiv.appendChild(this.createCard(q));
+ unansweredFragment.appendChild(cardHolderDiv);
+ });
+ } else {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.innerHTML = "There are no unanswered questions.
";
+ unansweredFragment.appendChild(cardHolderDiv);
+ }
+ // Remove existing fragments
+ let myUnansweredNode = document.getElementById("unansweredCardDiv");
+ while (myUnansweredNode.firstElementChild) {
+ myUnansweredNode.removeChild(myUnansweredNode.firstElementChild);
+ }
+ // And finally insert it somewhere in your page:
+ myUnansweredNode.appendChild(unansweredFragment);
+
+ /*** ANSWERED ***/
+ var answeredFragment = document.createDocumentFragment();
+ if (this.answeredQuestions.length > 0) {
+ // iterate over questions
+ this.answeredQuestions.forEach(q => {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.setAttribute("id", "answeredCardHolder")
+ cardHolderDiv.setAttribute("class", "cardHolder")
+ cardHolderDiv.appendChild(this.createCard(q));
+ answeredFragment.appendChild(cardHolderDiv);
+ });
+ } else {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.innerHTML = "There are no answered questions.
";
+ answeredFragment.appendChild(cardHolderDiv);
+ }
+ // Remove existing fragments
+ let myAnsweredNode = document.getElementById("answeredCardDiv");
+ while (myAnsweredNode.firstElementChild) {
+ myAnsweredNode.removeChild(myAnsweredNode.firstElementChild);
+ }
+ // And finally insert it somewhere in your page:
+ myAnsweredNode.appendChild(answeredFragment);
+ }, error => console.error(error));
+ } else {
+ this.appService.getQuestionsByTutorial(this.context.tid, code).subscribe(questions => {
+ var cardHolderDiv;
+ this.questions = questions;
+
+ this.unansweredQuestions = this.questions
+ .filter(x => x.questionStatus.trim() == "unanswered")
+ .sort((a, b) => { return new Date(b.questionSubmitted).getTime() - new Date(a.questionSubmitted).getTime(); });
+ this.answeredQuestions = this.questions
+ .filter(x => x.questionStatus.trim() == "answered")
+ .sort((a, b) => { return new Date(b.questionAnswered).getTime() - new Date(a.questionAnswered).getTime(); });
+
+ // create cards --- performance??
+
+ /*** UNANSWERED ***/
+ var unansweredFragment = document.createDocumentFragment();
+ // iterate over questions
+ if (this.unansweredQuestions.length > 0) {
+ // iterate over questions
+ this.unansweredQuestions.forEach(q => {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.setAttribute("id", "unansweredCardHolder");
+ cardHolderDiv.setAttribute("class", "cardHolder");
+ cardHolderDiv.appendChild(this.createCard(q));
+ unansweredFragment.appendChild(cardHolderDiv);
+ });
+ } else {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.innerHTML = "There are no unanswered questions.
";
+ unansweredFragment.appendChild(cardHolderDiv);
+ }
+ // Remove existing fragments
+ let myUnansweredNode = document.getElementById("unansweredCardDiv");
+ while (myUnansweredNode.firstElementChild) {
+ myUnansweredNode.removeChild(myUnansweredNode.firstElementChild);
+ }
+ // And finally insert it somewhere in your page:
+ myUnansweredNode.appendChild(unansweredFragment);
+
+ /*** ANSWERED ***/
+ var answeredFragment = document.createDocumentFragment();
+ if (this.answeredQuestions.length > 0) {
+ // iterate over questions
+ this.answeredQuestions.forEach(q => {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.setAttribute("id", "answeredCardHolder")
+ cardHolderDiv.setAttribute("class", "cardHolder")
+ cardHolderDiv.appendChild(this.createCard(q));
+ answeredFragment.appendChild(cardHolderDiv);
+ });
+ } else {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.innerHTML = "There are no answered questions.
";
+ answeredFragment.appendChild(cardHolderDiv);
+ }
+ // Remove existing fragments
+ let myAnsweredNode = document.getElementById("answeredCardDiv");
+ while (myAnsweredNode.firstElementChild) {
+ myAnsweredNode.removeChild(myAnsweredNode.firstElementChild);
+ }
+ // And finally insert it somewhere in your page:
+ myAnsweredNode.appendChild(answeredFragment);
+ }, error => console.error(error));
+ }
+ }
+}
diff --git a/Source/DashboardTabApp/src/app/navmenu/navmenu.component.css b/Source/DashboardTabApp/src/app/navmenu/navmenu.component.css
new file mode 100644
index 0000000..2fd2b9d
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/navmenu/navmenu.component.css
@@ -0,0 +1,108 @@
+.glyphicon {
+ vertical-align: middle;
+ padding: 2px;
+ font-size: 28px;
+ color: #49494d;
+}
+
+li .glyphicon {
+ margin-right: 2px;
+}
+
+li.link-active {
+ display: flex;
+}
+
+ li.link-active .glyphicon {
+ color: white !important
+ }
+
+ /* Highlighting rules for nav menu items */
+ li.link-active a,
+ li.link-active a:hover,
+ li.link-active a:focus {
+ background-color: #6364a7;
+ color: white !important;
+ }
+
+/* Keep the nav menu independent of scrolling and on top of other items */
+.main-nav {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 1;
+}
+
+@media (min-width: 768px) {
+ /* On small screens, convert the nav menu to a vertical sidebar */
+ .main-nav {
+ height: 100%;
+ width: calc(20% - 20px);
+ }
+
+ .navbar {
+ border-radius: 0px;
+ border-width: 0px;
+ height: 100%;
+ }
+
+ .navbar-header {
+ float: none;
+ }
+
+ .navbar-header p:hover {
+ color: black
+ }
+
+ .navbar-brand {
+ color: black;
+ padding-left: 10px;
+ padding-top: 10px;
+ }
+
+ .navbar-collapse {
+ display: block;
+ border-top: 1px solid #444;
+ padding: 0px;
+ }
+
+ .navbar ul {
+ float: none;
+ }
+
+ .navbar li {
+ float: none;
+ font-size: 15px;
+ margin: 6px;
+ }
+
+ .navbar li a {
+ padding: 10px 16px;
+ border-radius: 4px;
+ color: black;
+ }
+
+ .navbar a {
+ /* If a menu item's text is too long, truncate it */
+ width: 100%;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .navbar-inverse {
+ background-color: #edebe9;
+ display: contents;
+ }
+
+
+}
+
+.navtext {
+ color: #49494d;
+}
+
+.ng-fa-icon {
+ padding-right: 10px;
+}
diff --git a/Source/DashboardTabApp/src/app/navmenu/navmenu.component.html b/Source/DashboardTabApp/src/app/navmenu/navmenu.component.html
new file mode 100644
index 0000000..717f66e
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/navmenu/navmenu.component.html
@@ -0,0 +1,62 @@
+
+
+
+
+
{{errorMessage}}
+
+
+
+
diff --git a/Source/DashboardTabApp/src/app/navmenu/navmenu.component.ts b/Source/DashboardTabApp/src/app/navmenu/navmenu.component.ts
new file mode 100644
index 0000000..e681211
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/navmenu/navmenu.component.ts
@@ -0,0 +1,196 @@
+import { Component, OnInit, Inject } from '@angular/core';
+import { User } from '../models/User';
+import { Observable } from 'rxjs';
+import { map } from 'rxjs/operators';
+
+import { DomSanitizer } from '@angular/platform-browser';
+//import { iconTypes, iconStyle } from 'msteams-ui-icons-core';
+
+import * as microsoftTeams from '@microsoft/teams-js'
+import { AppService } from '../app.service';
+import { TeamGroupDetail } from '../models/TeamGroupDetail';
+
+import { Ng4LoadingSpinnerService } from 'ng4-loading-spinner';
+import { Router, ActivatedRoute } from '@angular/router';
+import { AuthService } from '../auth.service';
+import { faChalkboardTeacher, faUsers, faUserPlus, faCogs, faUsersCog, faUserFriends, faSignInAlt, faSignOutAlt } from '@fortawesome/free-solid-svg-icons';
+import { environment } from 'src/environments/environment';
+
+
+@Component({
+ selector: 'nav-menu',
+ templateUrl: './navmenu.component.html',
+ styleUrls: ['./navmenu.component.css']
+})
+export class NavMenuComponent implements OnInit {
+
+ errorMessage: string = null;
+ context: microsoftTeams.Context;
+
+ isDemonstrator: boolean = false;
+ isLecturer: boolean = false;
+ isAdmin: boolean = false;
+
+ groupIds: string[];
+ teamGroupDetail: TeamGroupDetail[];
+
+ faChalkboardTeacher = faChalkboardTeacher;
+ faUsers = faUsers;
+ faUserPlus = faUserPlus;
+ faCogs = faCogs;
+ faSignInAlt = faSignInAlt;
+ faSignOutAlt = faSignOutAlt;
+ faUsersCog = faUsersCog;
+ faUserFriends = faUserFriends;
+
+ constructor(
+ private appService: AppService,
+ private router: Router,
+ public authService: AuthService,
+ private domSanitizer: DomSanitizer,
+ private spinnerService: Ng4LoadingSpinnerService) {
+
+
+ }
+
+ ngOnInit(): void {
+ environment.upn = this.GetParam("upn");
+ environment.tid = this.GetParam("tid");
+
+ if (environment.upn && environment.tid) {
+ this.spinnerService.show();
+ this.authService.onAuthUpdate(this.onAuthUpdate.bind(this));
+ }
+ else {
+ this.showError("Please ensure both upn and tid are specified in querystring");
+ }
+ }
+
+ onAuthUpdate() {
+ this.appService.setHeaders();
+
+ // Do any first-time initialisation (like bootstrapping the initial user)
+ this.appService.initializeBotService().subscribe(
+ () => {
+ this.populateNav();
+ },
+ (error) => {
+ this.showError("There was an error initializing the Bot service", error);
+ this.spinnerService.hide();
+ });
+ }
+
+
+ populateNav() {
+ var upn = environment.upn;
+ var tid = environment.tid;
+
+ var userFinished: boolean = false;
+ var groupFinished: boolean = false;
+
+ this.appService.getUserAccess(upn)
+ .subscribe(userAccess => {
+ this.isAdmin = userAccess.isGlobalAdmin;
+ this.isLecturer = userAccess.isLecturer;
+ this.isDemonstrator = userAccess.isDemonstrator;
+
+ // only hide spinner when both tasks are complete
+ userFinished = true;
+ if (groupFinished) {
+ this.spinnerService.hide();
+ }
+ },
+ (error) => {
+ this.showError("There was an error getting initial user access", error);
+ this.spinnerService.hide();
+ });
+
+ // this needs to change when we implement a solution for provisioning the bot for different teams.
+ // since there are very few teams, this is acceptable but it is in no way scalable.
+ this.appService.getTeamGroupIdsWithQuestions(tid, upn)
+ .subscribe(groupIds => {
+ this.groupIds = groupIds.sort();
+
+ var tgd = new Array();
+
+ this.groupIds.forEach(groupId => {
+ this.appService.getTeamGroupDetail(groupId).subscribe(group => {
+ group.safePhotoByteUrl = this.domSanitizer.bypassSecurityTrustUrl("data:image/png;base64," + group.photoByteUrl);
+ tgd.push(group);
+ if (tgd.length == groupIds.length) {
+ this.teamGroupDetail = tgd;
+ if (this.router.routerState.snapshot.url.indexOf('home') >= 0) {
+ this.router.navigate(['question/' + this.teamGroupDetail[0].id], { queryParams: { upn: environment.upn, tid: environment.tid } });
+ } else if (this.router.routerState.snapshot.url.indexOf('question') >= 0) {
+ let id = this.router.routerState.snapshot.url.split('/')[2].split('?')[0];
+ this.router.navigate(['question/' + id], { queryParams: { upn: environment.upn, tid: environment.tid } });
+ } else {
+ let root = this.router.routerState.snapshot.url.split('/')[1].split('?')[0];
+ this.router.navigate([root], { queryParams: { upn: environment.upn, tid: environment.tid } });
+ }
+
+ // only hide spinner when both tasks are complete
+ groupFinished = true;
+ if (userFinished) {
+ this.spinnerService.hide();
+ }
+ }
+ },
+ (error) => {
+ this.showError("There was an error getting group details", error);
+ this.spinnerService.hide();
+ });
+ });
+ },
+ (error) => {
+ this.showError("There was an error getting group details", error);
+ this.spinnerService.hide();
+ });
+ }
+
+ showError(errorMessage: string, error: any = null) {
+ this.errorMessage = errorMessage + (error ? error : "");
+ }
+
+ GetParam(name): string {
+ const results = new RegExp('[\\?&]' + name + '=([^]*)').exec(decodeURIComponent(window.location.href));
+ if (!results) {
+ return null;
+ }
+ return results[1] || null;
+ }
+
+ teamNav(teamId: string) {
+ this.router.navigate(['question/' + teamId], { queryParams: { upn: environment.upn, tid: environment.tid } });
+
+ }
+
+ myStudentNav() {
+ this.router.navigate(['mystudents/'], { queryParams: { upn: environment.upn, tid: environment.tid } });
+
+ }
+
+ courseAdminNav() {
+ this.router.navigate(['courseadmin/'], { queryParams: { upn: environment.upn, tid: environment.tid } });
+
+ }
+
+ addStudentNav() {
+ this.router.navigate(['app-useradmin/'], { queryParams: { upn: environment.upn, tid: environment.tid } });
+ }
+
+ tutorialAdminNav() {
+ this.router.navigate(['tutorialadmin/'], { queryParams: { upn: environment.upn, tid: environment.tid } });
+
+ }
+
+ settingsNav() {
+ this.router.navigate(['settings/'], { queryParams: { upn: environment.upn, tid: environment.tid } });
+
+ }
+
+ analyticsNav() {
+ this.router.navigate(['analytics/'], { queryParams: { upn: environment.upn, tid: environment.tid } });
+
+ }
+}
diff --git a/Source/DashboardTabApp/src/app/question/question.component.css b/Source/DashboardTabApp/src/app/question/question.component.css
new file mode 100644
index 0000000..97b261c
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/question/question.component.css
@@ -0,0 +1,51 @@
+.dropdown {
+ height: 50px;
+}
+
+.filterButtonTeamsCustom {
+ margin-right:10px;
+}
+
+.filterCollapseButton {
+ background-color: #16233A;
+ opacity: 0.52;
+ color: white;
+ cursor: pointer;
+ padding: 18px;
+ width: 100%;
+ border: none;
+ text-align: left;
+ outline: none;
+ font-size: 15px;
+}
+
+ .active, .filterCollapseButton:hover {
+ background-color: #16233A;
+ opacity:0.36;
+ }
+
+.filterCollapseContent {
+ overflow: hidden;
+ background-color: #edebe9;
+ padding: 18px;
+ width: 100%;
+}
+
+.plusminus{
+ float: right;
+}
+
+.filterButton {
+ float: right;
+}
+
+.table {
+ table-layout:fixed;
+ width:100%;
+}
+
+.table > .tr > .td {
+ word-wrap:break-word;
+}
+
+
diff --git a/Source/DashboardTabApp/src/app/question/question.component.html b/Source/DashboardTabApp/src/app/question/question.component.html
new file mode 100644
index 0000000..cffa3a0
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/question/question.component.html
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/DashboardTabApp/src/app/question/question.component.ts b/Source/DashboardTabApp/src/app/question/question.component.ts
new file mode 100644
index 0000000..948d3b5
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/question/question.component.ts
@@ -0,0 +1,654 @@
+import { Component, OnInit, OnDestroy } from '@angular/core';
+import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
+import { AppService } from '../app.service';
+import { Question } from '../models/Question';
+import { User } from '../models/User';
+
+//import * as $ from 'jquery';
+//import 'datatables.net';
+//import * as microsoftTeams from '@microsoft/teams-js';
+import * as AdaptiveCards from "adaptivecards";
+import * as markdownit from "markdown-it";
+import * as moment from 'moment-timezone';
+
+
+@Component({
+ selector: 'question',
+ templateUrl: './question.component.html',
+ styleUrls: ['./question.component.css']
+})
+export class QuestionComponent implements OnInit, OnDestroy {
+ appService: AppService;
+ route: ActivatedRoute;
+ router: Router;
+ navigationSubscription;
+
+ groupId: string;
+
+ //context: microsoftTeams.Context;
+
+ questions: Question[];
+ unansweredQuestions: Question[];
+ answeredQuestions: Question[];
+
+ filterContentVisible: boolean = false;
+ plusminus_classname = "plusminus glyphicon glyphicon-plus-sign"
+ topics: string[] = ["All"];
+ selectedTopic: string = "All";
+
+ answeredContentVisible: boolean = true;
+ unansweredContentVisible: boolean = true;
+
+
+ constructor(appService: AppService, route: ActivatedRoute, router: Router) {
+ this.appService = appService;
+ this.route = route;
+ this.router = router;
+
+ this.navigationSubscription = this.router.events.subscribe((e: any) => {
+ // If it is a NavigationEnd event re-initalise the component
+ if (e instanceof NavigationEnd) {
+ this.loadQuestions();
+ }
+ });
+ }
+
+ ngOnInit() {
+ console.log('ngOnInit');
+ }
+
+ ngOnDestroy() {
+ if (this.navigationSubscription) {
+ this.navigationSubscription.unsubscribe();
+ }
+ }
+
+ loadQuestions() {
+ try {
+ this.groupId = this.route.snapshot.paramMap.get("id");
+ console.log(this.groupId);
+ this.appService.getTeamChannels(this.groupId)
+ .subscribe(teamChannels => {
+ let newTopics = new Array();
+ newTopics.push("All");
+ teamChannels.forEach(c => {
+ newTopics.push(c.displayName);
+ });
+
+ this.topics = newTopics;
+ });
+
+ this.appService.getQuestionsByGroup(this.groupId)
+ .subscribe(questions => {
+ var cardHolderDiv;
+ this.questions = questions;
+
+ this.unansweredQuestions = this.questions
+ .filter(x => x.questionStatus.trim() == "unanswered")
+ .sort((a, b) => { return new Date(b.questionSubmitted).getTime() - new Date(a.questionSubmitted).getTime(); });
+ this.answeredQuestions = this.questions
+ .filter(x => x.questionStatus.trim() == "answered")
+ .sort((a, b) => { return new Date(b.questionAnswered).getTime() - new Date(a.questionAnswered).getTime(); });
+
+ // create cards --- performance??
+
+ /*** UNANSWERED ***/
+ var unansweredFragment = document.createDocumentFragment();
+ // iterate over questions
+ if (this.unansweredQuestions.length > 0) {
+ // iterate over questions
+ this.unansweredQuestions.forEach(q => {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.setAttribute("id", "unansweredCardHolder");
+ cardHolderDiv.setAttribute("class", "cardHolder");
+ cardHolderDiv.appendChild(this.createCard(q));
+ unansweredFragment.appendChild(cardHolderDiv);
+ });
+ } else {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.setAttribute("class", "cardHolder");
+ cardHolderDiv.innerHTML = "There are no unanswered questions.
";
+ unansweredFragment.appendChild(cardHolderDiv);
+ }
+ // Remove existing fragments
+ let myUnansweredNode = document.getElementById("unansweredCardDiv");
+ while (myUnansweredNode.firstElementChild) {
+ myUnansweredNode.removeChild(myUnansweredNode.firstElementChild);
+ }
+ // And finally insert it somewhere in your page:
+ myUnansweredNode.appendChild(unansweredFragment);
+
+ /*** ANSWERED ***/
+ var answeredFragment = document.createDocumentFragment();
+ if (this.answeredQuestions.length > 0) {
+ // iterate over questions
+ this.answeredQuestions.forEach(q => {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.setAttribute("id", "answeredCardHolder")
+ cardHolderDiv.setAttribute("class", "cardHolder")
+ cardHolderDiv.appendChild(this.createCard(q));
+ answeredFragment.appendChild(cardHolderDiv);
+ });
+ } else {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.innerHTML = "There are no answered questions.
";
+ cardHolderDiv.setAttribute("class", "cardHolder");
+ answeredFragment.appendChild(cardHolderDiv);
+ }
+ // Remove existing fragments
+ let myAnsweredNode = document.getElementById("answeredCardDiv");
+ while (myAnsweredNode.firstElementChild) {
+ myAnsweredNode.removeChild(myAnsweredNode.firstElementChild);
+ }
+ // And finally insert it somewhere in your page:
+ myAnsweredNode.appendChild(answeredFragment);
+ }, error => console.error(error));
+ //});
+ } catch (error) {
+ console.error("try-catch: " + error);
+ }
+ }
+
+
+ createCard(question: Question): any {
+ let answerPosterName = "";
+ if (question.answerPoster != null)
+ answerPosterName = question.answerPoster.fullName;
+
+ var cardUnanswered = {
+ "$schema": "https://adaptivecards.io/schemas/adaptive-card.json",
+ "type": "AdaptiveCard",
+ "version": "1.0",
+ "style": "emphasis",
+ "body": [
+ {
+ "type": "Container",
+ "items": [
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "width": "stretch",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": question.topic,
+ "size": "medium"
+ },
+ {
+ "type": "TextBlock",
+ "text": question.questionText,
+ "weight": "bolder",
+ "wrap": true,
+ "size": "medium"
+ },
+ {
+ "type": "TextBlock",
+ "text": question.answerText,
+ "weight": "bolder",
+ "wrap": true,
+ "size": "medium",
+ "color": "good"
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": "Submitted: ",
+ "weight": "bolder",
+ "wrap": true
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": question.originalPoster.fullName,
+ "weight": "bolder",
+ "wrap": true
+ },
+ {
+ "type": "TextBlock",
+ "spacing": "none",
+ "text": moment.utc(question.questionSubmitted).local().format("DD MMM YYYY, hh:mm a"),
+ "isSubtle": true,
+ "wrap": true
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "actions": [
+ {
+ "type": "Action.OpenUrl",
+ "title": "View Conversation",
+ "url": question.link
+ }
+ ]
+ }
+
+ var cardAnswered = {
+ "$schema": "https://adaptivecards.io/schemas/adaptive-card.json",
+ "type": "AdaptiveCard",
+ "version": "1.0",
+ "style": "emphasis",
+ "body": [
+ {
+ "type": "Container",
+ "items": [
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "width": "stretch",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": question.topic,
+ "size": "medium"
+ },
+ {
+ "type": "TextBlock",
+ "text": question.questionText,
+ "weight": "bolder",
+ "wrap": true,
+ "size": "medium"
+ },
+ {
+ "type": "TextBlock",
+ "text": question.answerText,
+ "weight": "bolder",
+ "wrap": true,
+ "size": "medium",
+ "color": "good"
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": "Submitted: ",
+ "weight": "bolder",
+ "wrap": true
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": question.originalPoster.fullName,
+ "weight": "bolder",
+ "wrap": true
+ },
+ {
+ "type": "TextBlock",
+ "spacing": "none",
+ "text": moment.utc(question.questionSubmitted).local().format("DD MMM YYYY, hh:mm a"),
+ "isSubtle": true,
+ "wrap": true
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": "Answered: ",
+ "weight": "bolder",
+ "wrap": true
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "width": "auto",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": answerPosterName,
+ "weight": "bolder",
+ "wrap": true
+ },
+ {
+ "type": "TextBlock",
+ "spacing": "none",
+ "text": moment.utc(question.questionAnswered).local().format("DD MMM YYYY, hh:mm a"),
+ "isSubtle": true,
+ "wrap": true
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "actions": [
+ {
+ "type": "Action.OpenUrl",
+ "title": "View Conversation",
+ "url": question.link
+ }
+ ]
+ }
+
+ // Create an AdaptiveCard instance
+ var adaptiveCard = new AdaptiveCards.AdaptiveCard();
+
+ // Set its hostConfig property unless you want to use the default Host Config
+ // Host Config defines the style and behavior of a card
+ adaptiveCard.hostConfig = new AdaptiveCards.HostConfig({
+ "choiceSetInputValueSeparator": ",",
+ "supportsInteractivity": true,
+ "fontFamily": "Segoe UI",
+ "spacing": {
+ "small": 3,
+ "default": 8,
+ "medium": 20,
+ "large": 30,
+ "extraLarge": 40,
+ "padding": 20
+ },
+ "separator": {
+ "lineThickness": 1,
+ "lineColor": "#EEEEEE"
+ },
+ "fontSizes": {
+ "small": 12,
+ "default": 14,
+ "medium": 17,
+ "large": 21,
+ "extraLarge": 26
+ },
+ "fontWeights": {
+ "lighter": 200,
+ "default": 400,
+ "bolder": 600
+ },
+ "imageSizes": {
+ "small": 40,
+ "medium": 80,
+ "large": 160
+ },
+ "containerStyles": {
+ "default": {
+ "foregroundColors": {
+ "default": {
+ "default": "#333333",
+ "subtle": "#EE333333"
+ },
+ "dark": {
+ "default": "#000000",
+ "subtle": "#66000000"
+ },
+ "light": {
+ "default": "#FFFFFF",
+ "subtle": "#33000000"
+ },
+ "accent": {
+ "default": "#2E89FC",
+ "subtle": "#882E89FC"
+ },
+ "good": {
+ "default": "#54a254",
+ "subtle": "#DD54a254"
+ },
+ "warning": {
+ "default": "#e69500",
+ "subtle": "#DDe69500"
+ },
+ "attention": {
+ "default": "#cc3300",
+ "subtle": "#DDcc3300"
+ }
+ },
+ "backgroundColor": "#00000000"
+ },
+ "emphasis": {
+ "foregroundColors": {
+ "default": {
+ "default": "#333333",
+ "subtle": "#EE333333"
+ },
+ "dark": {
+ "default": "#000000",
+ "subtle": "#66000000"
+ },
+ "light": {
+ "default": "#FFFFFF",
+ "subtle": "#33000000"
+ },
+ "accent": {
+ "default": "#2E89FC",
+ "subtle": "#882E89FC"
+ },
+ "good": {
+ "default": "#54a254",
+ "subtle": "#DD54a254"
+ },
+ "warning": {
+ "default": "#e69500",
+ "subtle": "#DDe69500"
+ },
+ "attention": {
+ "default": "#cc3300",
+ "subtle": "#DDcc3300"
+ }
+ },
+ "backgroundColor": "#08000000"
+ }
+ },
+ "actions": {
+ "maxActions": 5,
+ "spacing": "Default",
+ "buttonSpacing": 10,
+ "showCard": {
+ "actionMode": "Inline",
+ "inlineTopMargin": 16,
+ "style": "emphasis"
+ },
+ "preExpandSingleShowCardAction": false,
+ "actionsOrientation": "Horizontal",
+ "actionAlignment": "Right"
+ },
+ "adaptiveCard": {
+ "allowCustomStyle": false
+ },
+ "imageSet": {
+ "imageSize": "Medium",
+ "maxImageHeight": 100
+ },
+ "factSet": {
+ "title": {
+ "size": "Default",
+ "color": "Default",
+ "isSubtle": false,
+ "weight": "Bolder",
+ "warp": true
+ },
+ "value": {
+ "size": "Default",
+ "color": "Default",
+ "isSubtle": false,
+ "weight": "Default",
+ "warp": true
+ },
+ "spacing": 10
+ } // More host config options
+ });
+
+ // Set the adaptive card's event handlers. onExecuteAction is invoked
+ // whenever an action is clicked in the card
+ adaptiveCard.onExecuteAction = function (action: AdaptiveCards.OpenUrlAction) {
+ window.open(action.url, "_blank");
+ }
+
+ // For markdown support
+ AdaptiveCards.AdaptiveCard.onProcessMarkdown = function (text) { return markdownit().render(text); }
+
+ // Parse the card payload
+ if (question.questionAnswered)
+ adaptiveCard.parse(cardAnswered);
+ else
+ adaptiveCard.parse(cardUnanswered);
+
+
+ // Render the card to an HTML element:
+ var renderedCard = adaptiveCard.render();
+
+ return renderedCard;
+ }
+
+ /*********** BUTTONS ***********/
+
+ public showHideUnanswered(event: any) {
+ this.unansweredContentVisible = !this.unansweredContentVisible;
+ }
+
+ public showHideAnswered(event: any) {
+ this.answeredContentVisible = !this.answeredContentVisible;
+ }
+
+ public showHideContent(event: any) {
+ this.filterContentVisible = !this.filterContentVisible;
+
+ if (this.filterContentVisible)
+ this.plusminus_classname = "plusminus glyphicon glyphicon-minus-sign";
+ else
+ this.plusminus_classname = "plusminus glyphicon glyphicon-plus-sign";
+ }
+
+ public applyFilters(event: any) {
+ this.appService.getQuestionsByGroup(this.groupId)
+ .subscribe(questions => {
+ var postfilter = questions;
+
+ if (this.selectedTopic != "All")
+ postfilter = postfilter.filter(q => q.topic.trim() == this.selectedTopic.trim());
+
+ //if (this.selectedStatus != "All") {
+ // console.log(this.selectedStatus.toLowerCase());
+ // console.log(postfilter[0]);
+ // postfilter = postfilter.filter(q => q.questionStatus.trim() == this.selectedStatus.toLowerCase().trim());
+ //}
+
+ this.questions = postfilter;
+
+ this.unansweredQuestions = this.questions
+ .filter(x => x.questionStatus.trim() == "unanswered")
+ .sort((a, b) => { return new Date(b.questionSubmitted).getTime() - new Date(a.questionSubmitted).getTime(); });
+ this.answeredQuestions = this.questions
+ .filter(x => x.questionStatus.trim() == "answered")
+ .sort((a, b) => { return new Date(b.questionAnswered).getTime() - new Date(a.questionAnswered).getTime(); });
+ // create cards --- performance??
+
+
+ /*** UNANSWERED ***/
+ var unansweredFragment = document.createDocumentFragment();
+ var cardHolderDiv;
+
+ if (this.unansweredQuestions.length > 0) {
+ // iterate over questions
+ this.unansweredQuestions.forEach(q => {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.setAttribute("id", "unansweredCardHolder");
+ cardHolderDiv.setAttribute("class", "cardHolder");
+ cardHolderDiv.appendChild(this.createCard(q));
+ unansweredFragment.appendChild(cardHolderDiv);
+ });
+ } else {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.setAttribute("class", "cardHolder");
+ cardHolderDiv.innerHTML = "There are no unanswered questions.
";
+ unansweredFragment.appendChild(cardHolderDiv);
+ }
+ // Remove existing fragments
+ let myUnansweredNode = document.getElementById("unansweredCardDiv");
+ while (myUnansweredNode.firstElementChild) {
+ myUnansweredNode.removeChild(myUnansweredNode.firstElementChild);
+ }
+ // And finally insert it somewhere in your page:
+ myUnansweredNode.appendChild(unansweredFragment);
+
+ /*** ANSWERED ***/
+ var answeredFragment = document.createDocumentFragment();
+ if (this.answeredQuestions.length > 0) {
+ // iterate over questions
+ this.answeredQuestions.forEach(q => {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.setAttribute("id", "answeredCardHolder")
+ cardHolderDiv.setAttribute("class", "cardHolder")
+ cardHolderDiv.appendChild(this.createCard(q));
+ answeredFragment.appendChild(cardHolderDiv);
+ });
+ } else {
+ cardHolderDiv = document.createElement("div");
+ cardHolderDiv.innerHTML = "There are no answered questions.
";
+ cardHolderDiv.setAttribute("class", "cardHolder");
+ answeredFragment.appendChild(cardHolderDiv);
+ }
+ // Remove existing fragments
+ let myAnsweredNode = document.getElementById("answeredCardDiv");
+ while (myAnsweredNode.firstElementChild) {
+ myAnsweredNode.removeChild(myAnsweredNode.firstElementChild);
+ }
+ // And finally insert it somewhere in your page:
+ myAnsweredNode.appendChild(answeredFragment);
+ }, error => console.error(error));
+
+ }
+
+ public resetFilters(event: any) {
+ this.selectedTopic = "All";
+ //this.selectedStatus = "All";
+ }
+}
+
+
diff --git a/Source/DashboardTabApp/src/app/silent-end/silent-end.component.html b/Source/DashboardTabApp/src/app/silent-end/silent-end.component.html
new file mode 100644
index 0000000..e69de29
diff --git a/Source/DashboardTabApp/src/app/silent-end/silent-end.component.scss b/Source/DashboardTabApp/src/app/silent-end/silent-end.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/Source/DashboardTabApp/src/app/silent-end/silent-end.component.spec.ts b/Source/DashboardTabApp/src/app/silent-end/silent-end.component.spec.ts
new file mode 100644
index 0000000..e0bd4e6
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/silent-end/silent-end.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SilentEndComponent } from './silent-end.component';
+
+describe('SilentEndComponent', () => {
+ let component: SilentEndComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ SilentEndComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SilentEndComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/Source/DashboardTabApp/src/app/silent-end/silent-end.component.ts b/Source/DashboardTabApp/src/app/silent-end/silent-end.component.ts
new file mode 100644
index 0000000..1df78b6
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/silent-end/silent-end.component.ts
@@ -0,0 +1,47 @@
+import { Component, OnInit } from '@angular/core';
+///
+import 'expose-loader?AuthenticationContext!../../../node_modules/adal-angular/lib/adal.js'
+import * as AuthenticationContext from 'adal-angular/lib/adal'
+//let createAuthContextFn: adal.AuthenticationContextStatic = AuthenticationContext;
+import * as microsoftTeams from '@microsoft/teams-js'
+import { environment } from 'src/environments/environment';
+@Component({
+ selector: 'app-silent-end',
+ templateUrl: './silent-end.component.html',
+ styleUrls: ['./silent-end.component.scss']
+})
+export class SilentEndComponent implements OnInit {
+
+
+ constructor() {
+ //alert("silent end")
+ microsoftTeams.initialize(function () {
+ let config = {
+ clientId: environment.authConfig.clientId,
+ tenant: environment.authConfig.tenantId,
+ // redirectUri must be in the list of redirect URLs for the Azure AD app
+ redirectUri: window.location.origin + environment.authConfig.redirectUri,
+ cacheLocation: environment.authConfig.cacheLocation,
+ navigateToLoginRequestUrl: environment.authConfig.navigateToLoginRequestUrl,
+ };
+ let authContext = new AuthenticationContext(config);
+ if (authContext.isCallback(window.location.hash)) {
+ authContext.handleWindowCallback();
+ // Only call notifySuccess or notifyFailure if this page is in the authentication popup
+ if (window.parent === window) {
+ if (authContext.getCachedUser()) {
+ microsoftTeams.authentication.notifySuccess();
+ } else {
+ microsoftTeams.authentication.notifyFailure(authContext.getLoginError());
+ }
+ }
+ }
+ });
+ // ADAL.js configuration
+
+ }
+
+ ngOnInit() {
+ }
+
+}
diff --git a/Source/DashboardTabApp/src/app/silent-start/silent-start.component.html b/Source/DashboardTabApp/src/app/silent-start/silent-start.component.html
new file mode 100644
index 0000000..e69de29
diff --git a/Source/DashboardTabApp/src/app/silent-start/silent-start.component.scss b/Source/DashboardTabApp/src/app/silent-start/silent-start.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/Source/DashboardTabApp/src/app/silent-start/silent-start.component.spec.ts b/Source/DashboardTabApp/src/app/silent-start/silent-start.component.spec.ts
new file mode 100644
index 0000000..b9bbf30
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/silent-start/silent-start.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SilentStartComponent } from './silent-start.component';
+
+describe('SilentStartComponent', () => {
+ let component: SilentStartComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ SilentStartComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SilentStartComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/Source/DashboardTabApp/src/app/silent-start/silent-start.component.ts b/Source/DashboardTabApp/src/app/silent-start/silent-start.component.ts
new file mode 100644
index 0000000..85dc2cd
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/silent-start/silent-start.component.ts
@@ -0,0 +1,60 @@
+import { Component, OnInit } from '@angular/core';
+///
+import 'expose-loader?AuthenticationContext!../../../node_modules/adal-angular/lib/adal.js'
+import * as AuthenticationContext from 'adal-angular/lib/adal'
+//let createAuthContextFn: adal.AuthenticationContextStatic = AuthenticationContext;
+import * as microsoftTeams from '@microsoft/teams-js'
+import { environment } from 'src/environments/environment';
+@Component({
+ selector: 'app-silent-start',
+ templateUrl: './silent-start.component.html',
+ styleUrls: ['./silent-start.component.scss']
+})
+export class SilentStartComponent implements OnInit {
+
+ constructor() {
+ microsoftTeams.initialize();
+ // Get the tab context, and use the information to navigate to Azure AD login page
+ microsoftTeams.getContext(function (context) {
+ // ADAL.js configuration
+ // Setup extra query parameters for ADAL
+ // - openid and profile scope adds profile information to the id_token
+ // - login_hint provides the expected user name
+ let config = {
+ clientId: environment.authConfig.clientId,
+ tenant: environment.authConfig.tenantId,
+ // redirectUri must be in the list of redirect URLs for the Azure AD app
+ redirectUri: window.location.origin + environment.authConfig.redirectUri,
+ cacheLocation: environment.authConfig.cacheLocation,
+ navigateToLoginRequestUrl: environment.authConfig.navigateToLoginRequestUrl,
+ //popUp: true,
+ extraQueryParameters: environment.authConfig.extraQueryParameters,
+ displayCall: null
+ };
+
+ if (context.upn) {
+ config.extraQueryParameters = "scope=openid+profile&login_hint=" + encodeURIComponent(context.upn);
+ } else {
+ config.extraQueryParameters = "scope=openid+profile";
+ }
+
+ // Use a custom displayCall function to add extra query parameters to the url before navigating to it
+
+ config.displayCall = function (urlNavigate) {
+ if (urlNavigate) {
+ if (config.extraQueryParameters) {
+ urlNavigate += "&" + config.extraQueryParameters;
+ }
+ window.location.replace(urlNavigate);
+ }
+ }
+ // Navigate to the AzureAD login page
+ let authContext = new AuthenticationContext(config);
+ authContext.login();
+ });
+ }
+
+ ngOnInit() {
+ }
+
+}
diff --git a/Source/DashboardTabApp/src/app/tabcontrol/tab.ts b/Source/DashboardTabApp/src/app/tabcontrol/tab.ts
new file mode 100644
index 0000000..6a18363
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/tabcontrol/tab.ts
@@ -0,0 +1,19 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+ selector: 'tab',
+ styles: [`
+ .pane{
+ padding: 1em;
+ }
+ `],
+ template: `
+
+
+
+ `
+})
+export class Tab {
+ @Input('tabTitle') title: string;
+ @Input('tabActive') active = false;
+}
diff --git a/Source/DashboardTabApp/src/app/tabcontrol/tabs.ts b/Source/DashboardTabApp/src/app/tabcontrol/tabs.ts
new file mode 100644
index 0000000..8ed9f82
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/tabcontrol/tabs.ts
@@ -0,0 +1,42 @@
+import { Component, ContentChildren, QueryList, AfterContentInit, Output, EventEmitter } from '@angular/core';
+import { Tab } from './tab';
+
+@Component({
+ selector: 'tabs',
+ template: `
+
+
+ `,
+ //styleUrls: ['./bootstrap.min.css']
+
+})
+export class Tabs implements AfterContentInit {
+ @Output('tabChanged') changed: EventEmitter = new EventEmitter();
+ @ContentChildren(Tab) tabs: QueryList;
+
+ // contentChildren are set
+ ngAfterContentInit() {
+ // get all active tabs
+ //let activeTabs = this.tabs.filter((tab) => tab.active);
+
+ //// if there is no active tab set, activate the first
+ //if (activeTabs.length === 0) {
+ // this.selectTab(this.tabs.first);
+ //}
+ }
+
+ selectTab(tab: Tab) {
+ // deactivate all tabs
+ this.tabs.toArray().forEach(tab => tab.active = false);
+
+ // activate the tab the user has clicked on.
+ tab.active = true;
+ this.changed.emit(tab.title);
+ }
+
+}
+
diff --git a/Source/DashboardTabApp/src/app/tutorialadmin/tutorialadmin.component.css b/Source/DashboardTabApp/src/app/tutorialadmin/tutorialadmin.component.css
new file mode 100644
index 0000000..0ac20af
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/tutorialadmin/tutorialadmin.component.css
@@ -0,0 +1,22 @@
+/*.firstColumn, .lastColumn {
+ min-width: 25%;
+ max-width: 25%;
+ word-break: break-word;
+}
+
+.innerColumns {
+ padding-left: 5px;
+ max-width: 12.5%;
+ min-width: 12.5%;
+}
+
+.mat-cell:first-of-type, mat-footer-cell:first-of-type, mat-header-cell:first-of-type {
+ padding-left: 10px !important;
+}
+
+.mat-cell:last-of-type, mat-footer-cell:last-of-type, mat-header-cell:last-of-type {
+ padding-right: 0px !important;
+}*/
+.mat-cell:last-of-type, mat-footer-cell:last-of-type, mat-header-cell:last-of-type {
+padding-right: 0px !important;
+}
diff --git a/Source/DashboardTabApp/src/app/tutorialadmin/tutorialadmin.component.html b/Source/DashboardTabApp/src/app/tutorialadmin/tutorialadmin.component.html
new file mode 100644
index 0000000..f45bb54
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/tutorialadmin/tutorialadmin.component.html
@@ -0,0 +1,59 @@
+Tutorial Group Administration
+
+ Use the table below to administer tutorials by course.
+
+
+ Select a course to begin
+
+
+
+
+ Select Course
+
+
+
+ {{course.name}}
+
+
+
+
+
+
+
+ add New Tutorial
+
+
+
+
+
+
+ Tutorial Code
+
+
+
+
+
+
+
+
+ Tutorial Name
+
+
+
+
+
+
+
+
+ Actions
+
+ delete
+ save
+
+
+
+
+
+
+
+
diff --git a/Source/DashboardTabApp/src/app/tutorialadmin/tutorialadmin.component.ts b/Source/DashboardTabApp/src/app/tutorialadmin/tutorialadmin.component.ts
new file mode 100644
index 0000000..6ccbc8f
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/tutorialadmin/tutorialadmin.component.ts
@@ -0,0 +1,108 @@
+import { Component, OnInit } from '@angular/core';
+import { Course } from '../models/Course';
+import { UserCourseRole } from '../models/UserCourseRoleModel';
+import { AppService } from '../app.service';
+import { MatTableDataSource, MatDialog } from '@angular/material';
+import { Tutorial } from '../models/Tutorial';
+import { TutorialGroup } from '../models/TutorialGroup';
+import { GenericDialogComponent } from '../generic-dialog/generic-dialog.component';
+
+@Component({
+ selector: 'tutorialadmin',
+ templateUrl: './tutorialadmin.component.html',
+ styleUrls: ['./tutorialadmin.component.css']
+})
+export class TutorialAdminComponent implements OnInit {
+ userCourseRoleMappings: UserCourseRole[];
+ courseList: Course[];
+ appService: AppService;
+ displayedColumns = ['tutorialcode', 'name', 'actions'];
+ tutorials: TutorialGroup[];
+ dataSource;
+ selectedCourseName: any;
+ selectedCourse: any;
+
+ constructor(appService: AppService, public dialog: MatDialog) {
+ this.appService = appService;
+
+ }
+
+ ngOnInit() {
+ this.appService.getCourses()
+ .subscribe(courses => {
+ this.courseList = courses;
+ });
+ }
+
+ updateTutorialMappingTable(course) {
+ console.log(course);
+ this.appService.getTutorialsByCourse(course.id)
+ .subscribe(tutorials => {
+ console.log(tutorials);
+ this.selectedCourse = course;
+ this.tutorials = tutorials;
+ this.dataSource = new MatTableDataSource(this.tutorials);
+ });
+ }
+ addRow() {
+ var newTutorial: TutorialGroup = {
+ id: 0,
+ courseId: this.selectedCourse.id,
+ code: "",
+ name: ""
+ }
+ this.tutorials.push(newTutorial);
+ this.dataSource = new MatTableDataSource(this.tutorials);
+
+ }
+
+ deleteRow(tutorial: TutorialGroup, row: number) {
+ var tutorialToDelete = tutorial;
+
+ //const dialogRef = this.dialog.open(DeleteCourseDialogComponent, {
+ // width: '250px',
+ // data: { courseName: courseName, courseToDeleteID: tutorialToDelete }
+ //});
+ // dialogRef.afterClosed().subscribe(res => {
+ // console.log("Dialog result: ", res)
+ // if (res) {
+ //if (res > 0) {
+ this.appService.deleteTutorial(tutorialToDelete)
+ .subscribe(tutorials => {
+ this.tutorials = tutorials;
+ this.tutorials.splice(row, 1);
+ this.dataSource = new MatTableDataSource(this.tutorials);
+ });
+ // } else {
+ // this.courses.splice(row, 1);
+ // this.dataSource = new MatTableDataSource(this.courses);
+ // }
+ // }
+ // });
+ }
+
+ saveRow(row: number) {
+ //this.editService.save(course, isNew);
+ var tutorial = this.tutorials[row];
+ this.appService.saveTutorial(tutorial)
+ .subscribe(tutorials => {
+ if (tutorials != null) {// api returns null if an exception is caught
+ this.openDialog("Success", "Tutorials successfully saved.")
+
+ } else {
+ this.openDialog("Failure", "Tutorials were not saved, try again.")
+ }
+ this.tutorials = tutorials;
+ this.dataSource = new MatTableDataSource(this.tutorials);
+
+ });
+ }
+
+ openDialog(outcome: string, message: string): void {
+ const dialogRef = this.dialog.open(GenericDialogComponent, {
+ width: '250px',
+ data: { outcome: outcome, message: message }
+ });
+ }
+
+}
diff --git a/Source/DashboardTabApp/src/app/user-tutorial-dialog/user-tutorial-dialog.component.html b/Source/DashboardTabApp/src/app/user-tutorial-dialog/user-tutorial-dialog.component.html
new file mode 100644
index 0000000..8b820ae
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/user-tutorial-dialog/user-tutorial-dialog.component.html
@@ -0,0 +1,17 @@
+{{user.fullName}}
+
+
Select/remove tutorials for this user.
+
+
+
+ OK
+ Cancel
+
diff --git a/Source/DashboardTabApp/src/app/user-tutorial-dialog/user-tutorial-dialog.component.scss b/Source/DashboardTabApp/src/app/user-tutorial-dialog/user-tutorial-dialog.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/Source/DashboardTabApp/src/app/user-tutorial-dialog/user-tutorial-dialog.component.spec.ts b/Source/DashboardTabApp/src/app/user-tutorial-dialog/user-tutorial-dialog.component.spec.ts
new file mode 100644
index 0000000..bbfae24
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/user-tutorial-dialog/user-tutorial-dialog.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { UserTutorialDialogComponent } from './user-tutorial-dialog.component';
+
+describe('UserTutorialDialogComponent', () => {
+ let component: UserTutorialDialogComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ UserTutorialDialogComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(UserTutorialDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/Source/DashboardTabApp/src/app/user-tutorial-dialog/user-tutorial-dialog.component.ts b/Source/DashboardTabApp/src/app/user-tutorial-dialog/user-tutorial-dialog.component.ts
new file mode 100644
index 0000000..88b9fa7
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/user-tutorial-dialog/user-tutorial-dialog.component.ts
@@ -0,0 +1,38 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { FormGroup, FormBuilder, FormControl } from '@angular/forms';
+@Component({
+ selector: 'app-user-tutorial-dialog',
+ templateUrl: './user-tutorial-dialog.component.html',
+ styleUrls: ['./user-tutorial-dialog.component.scss']
+})
+export class UserTutorialDialogComponent implements OnInit {
+ user: any;
+ tutorials: any[] = [];
+ userTutorials: any[] = [];
+ selectedTutorials: any;
+ tutorialForm: FormGroup;
+
+ constructor(public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any, private formBuilder: FormBuilder) {
+ this.user = data.user;
+ this.tutorials = data.tutorials;
+ this.userTutorials = this.user.tutorialGroups;
+ this.selectedTutorials = this.userTutorials;
+ this.tutorialForm = this.formBuilder.group({
+ tutorials: new FormControl(this.userTutorials)
+ });
+ }
+
+ ngOnInit() {
+ }
+
+ onOkClick(): void {
+ this.user.tutorialGroups = this.selectedTutorials;
+ this.dialogRef.close(this.user);
+ }
+
+ onCancelClick(): void {
+ this.dialogRef.close();
+ }
+
+}
diff --git a/Source/DashboardTabApp/src/app/useradmin/useradmin.component.css b/Source/DashboardTabApp/src/app/useradmin/useradmin.component.css
new file mode 100644
index 0000000..a07e593
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/useradmin/useradmin.component.css
@@ -0,0 +1,38 @@
+.firstColumn {
+ min-width: 25%;
+ max-width: 25%;
+ word-break: break-word;
+}
+
+.lastColumn {
+ min-width: 15%;
+ max-width: 15%;
+ word-break: break-word;
+ justify-content: center;
+}
+
+.innerColumns {
+ padding-left: 5px;
+ max-width: 12.5%;
+ min-width: 12.5%;
+}
+
+.tutorialGroupColumn {
+ padding-left: 10px;
+ max-width: 22.5%;
+ min-width: 22.5%;
+}
+
+.mat-cell:first-of-type, mat-footer-cell:first-of-type, mat-header-cell:first-of-type {
+ padding-left: 10px !important;
+}
+
+.mat-cell:last-of-type, mat-footer-cell:last-of-type, mat-header-cell:last-of-type {
+ padding-right: 0px !important;
+}
+
+.link {
+ color: blue;
+ text-decoration: underline;
+ cursor: pointer;
+}
diff --git a/Source/DashboardTabApp/src/app/useradmin/useradmin.component.html b/Source/DashboardTabApp/src/app/useradmin/useradmin.component.html
new file mode 100644
index 0000000..fe9aa54
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/useradmin/useradmin.component.html
@@ -0,0 +1,88 @@
+User Administration
+
+ Select Course
+
+
+
+ {{course.name}}
+
+
+
+
+
+
+
+
+ Sync Users From Teams
+
+
+
+
+
+
+ Username
+
+ {{user.userName}}
+
+
+
+
+ First Name
+
+ {{user.firstName}}
+
+
+
+
+ Last Name
+
+ {{user.lastName}}
+
+
+
+
+ Role
+
+
+
+
+ {{role.name}}
+
+
+
+
+
+
+ Tutorial Groups
+
+ {{user.tutorialGroupsString != undefined ? user.tutorialGroupsString : 'Click to manage user tutorial groups' }}
+
+
+
+
+ Actions
+
+
+ delete
+ save
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/DashboardTabApp/src/app/useradmin/useradmin.component.ts b/Source/DashboardTabApp/src/app/useradmin/useradmin.component.ts
new file mode 100644
index 0000000..848d772
--- /dev/null
+++ b/Source/DashboardTabApp/src/app/useradmin/useradmin.component.ts
@@ -0,0 +1,182 @@
+import { Component, OnInit, ViewChild, ElementRef, ViewEncapsulation } from '@angular/core';
+import { Student } from '../models/Student';
+import { AppService } from '../app.service';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA, MatTableDataSource } from '@angular/material';
+import { GenericDialogComponent } from '../generic-dialog/generic-dialog.component';
+import { Course } from '../models/Course';
+import { UserTutorialDialogComponent } from '../user-tutorial-dialog/user-tutorial-dialog.component';
+import { TutorialGroup } from '../models/TutorialGroup';
+
+@Component({
+ selector: 'app-useradmin',
+ templateUrl: './useradmin.component.html',
+ styleUrls: ['./useradmin.component.css'],
+ encapsulation: ViewEncapsulation.None
+})
+export class UserAdmin implements OnInit {
+ @ViewChild('studentFile', { static: false }) studentFile: ElementRef;
+ studentsToUpload: any;
+ studentsToAdd: Student[];
+ appService: AppService;
+ selectedCourse: any;
+ selectedCourseName: any;
+ courseList: Course[];
+ roleList: any;
+ displayedColumns = ['userName', 'firstName', 'lastName', 'role'
+ , 'tutorialGroups', 'actions'];
+ dataSource;
+ tutorials: TutorialGroup[];
+ userList: any[];
+
+ constructor(appService: AppService, public dialog: MatDialog) {
+ this.appService = appService;
+ this.appService.getRoles().subscribe(roles => {
+ this.roleList = roles;
+ console.log(this.roleList);
+ });
+ }
+
+ ngOnInit() {
+ this.appService.getCourses()
+ .subscribe(courses => {
+ this.courseList = courses;
+ });
+ }
+
+ handleFileInput(input: HTMLInputElement) {
+ const files = input.files;
+ if (files && files.length) {
+ const fileToRead = files[0];
+ const fileReader = new FileReader();
+ fileReader.onload = () => {
+ const textFromFileLoaded = fileReader.result;
+ const lines = textFromFileLoaded.split('\n');
+ var count = 1;
+ this.studentsToAdd = [];
+ lines.forEach(element => {
+ if (count == 1) {// the reader doesn't give a line count so I just skip the first one
+ count++;
+ } else {
+ var line = element.split(',');
+ var student: Student = {
+ studentID: line[0],
+ firstName: line[1],
+ lastName: line[2],
+ username: line[3],
+ email: line[4],
+ role: line[5],
+ courseName: this.selectedCourseName,
+ tutorialGroupID: (line[6]) ? line[6].trim() : ''
+ };
+ if (student.firstName != undefined)// skip the last line
+ this.studentsToAdd.push(student);
+ }
+ });
+ if (this.studentsToAdd.length > 0) {
+ //call app service to add students
+ this.appService.addStudents(this.studentsToAdd).subscribe(students => {
+ if (students != null) {// api returns null if an exception is caught
+ this.openDialog("Success", "Students successfully added/updated.")
+
+ } else {
+ this.openDialog("Failure", "Students were not added/updated. Please check your .csv file and try again.")
+ }
+ })
+ }
+ };
+ fileReader.readAsText(fileToRead, "UTF-8");
+ this.studentFile.nativeElement.value = "";
+ }
+ }
+
+ updateUserTable(course) {
+ console.log(course);
+ if (this.selectedCourse == undefined || course.name != this.selectedCourse.name) {
+ this.selectedCourse = course;
+ this.appService.getUserCourseRoleMappingsByCourse(course.id)
+ .subscribe(users => {
+ console.log(users);
+ this.userList = users;
+ this.dataSource = new MatTableDataSource(users);
+ this.appService.getTutorialsByCourse(course.id)
+ .subscribe(tutorials => {
+ console.log(tutorials);
+ this.tutorials = tutorials;
+ });
+ });
+ }
+ }
+
+
+ manageUserTutorial(user) {
+ if (user.id == 0) {
+ alert("Please save this user first before editing.");
+ } else {
+ const dialogRef = this.dialog.open(UserTutorialDialogComponent, {
+ width: '500px',
+ height: '700px',
+ data: { user: user, tutorials: this.tutorials }
+ });
+ dialogRef.afterClosed().subscribe(res => {
+ if (res) {
+ var index = this.userList.findIndex(user => user.id == res.id);
+ if (index > -1) {
+ var newTutString = "";
+ if (res.tutorialGroups.length > 0) {
+ for (var i = 0; i < res.tutorialGroups.length; i++) {
+ newTutString += res.tutorialGroups[i].code + ", ";
+ }
+ newTutString = newTutString.substring(0, newTutString.length - 2);
+ }
+ res.tutorialGroupsString = newTutString;
+ this.userList[index] = res;
+ this.dataSource = new MatTableDataSource(this.userList);
+ }
+ console.log(res);
+ }
+ });
+ }
+ console.log(user)
+ }
+
+ refreshUsers() {
+ this.appService.refreshUsers(this.selectedCourse).subscribe(users => {
+ console.log(users)
+ if (users) {
+ this.dataSource = new MatTableDataSource(users);
+ }
+ });
+ }
+
+ deleteRow(user: any, index: number) {
+ this.appService.deleteUserCourseRoleMapping(user)
+ .subscribe(users => {
+ this.userList = users;
+ this.userList.splice(index, 1);
+ this.dataSource = new MatTableDataSource(this.userList);
+ });
+ }
+
+
+ saveRow(user: any, index: number) {
+ this.appService.saveUserCourseRoleMapping(user)
+ .subscribe(users => {
+ if (users != null) {// api returns null if an exception is caught
+ this.openDialog("Success", "User successfully saved.")
+
+ } else {
+ this.openDialog("Failure", "User was not saved, try again.")
+ }
+ this.userList = users;
+ this.dataSource = new MatTableDataSource(this.userList);
+
+ });
+ }
+ openDialog(outcome: string, message: string): void {
+ const dialogRef = this.dialog.open(GenericDialogComponent, {
+ width: '250px',
+ data: { outcome: outcome, message: message }
+ });
+ }
+
+}
diff --git a/Source/DashboardTabApp/src/assets/.gitkeep b/Source/DashboardTabApp/src/assets/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/Source/DashboardTabApp/src/assets/MyStudents-neg.png b/Source/DashboardTabApp/src/assets/MyStudents-neg.png
new file mode 100644
index 0000000..505f4fe
Binary files /dev/null and b/Source/DashboardTabApp/src/assets/MyStudents-neg.png differ
diff --git a/Source/DashboardTabApp/src/assets/MyStudents.png b/Source/DashboardTabApp/src/assets/MyStudents.png
new file mode 100644
index 0000000..74d8808
Binary files /dev/null and b/Source/DashboardTabApp/src/assets/MyStudents.png differ
diff --git a/Source/DashboardTabApp/src/assets/StudentUploadTemplate.csv b/Source/DashboardTabApp/src/assets/StudentUploadTemplate.csv
new file mode 100644
index 0000000..b1945e5
--- /dev/null
+++ b/Source/DashboardTabApp/src/assets/StudentUploadTemplate.csv
@@ -0,0 +1 @@
+Student ID,First Name,Last Name,Username,Email,Role,Tutorial Group ID
diff --git a/Source/DashboardTabApp/src/assets/course info.png b/Source/DashboardTabApp/src/assets/course info.png
new file mode 100644
index 0000000..487e596
Binary files /dev/null and b/Source/DashboardTabApp/src/assets/course info.png differ
diff --git a/Source/DashboardTabApp/src/assets/csvIcon.png b/Source/DashboardTabApp/src/assets/csvIcon.png
new file mode 100644
index 0000000..a61494f
Binary files /dev/null and b/Source/DashboardTabApp/src/assets/csvIcon.png differ
diff --git a/Source/DashboardTabApp/src/assets/favicon.ico b/Source/DashboardTabApp/src/assets/favicon.ico
new file mode 100644
index 0000000..3c41273
Binary files /dev/null and b/Source/DashboardTabApp/src/assets/favicon.ico differ
diff --git a/Source/DashboardTabApp/src/assets/icons8-conference-96.png b/Source/DashboardTabApp/src/assets/icons8-conference-96.png
new file mode 100644
index 0000000..17ed769
Binary files /dev/null and b/Source/DashboardTabApp/src/assets/icons8-conference-96.png differ
diff --git a/Source/DashboardTabApp/src/browserslist b/Source/DashboardTabApp/src/browserslist
new file mode 100644
index 0000000..8e09ab4
--- /dev/null
+++ b/Source/DashboardTabApp/src/browserslist
@@ -0,0 +1,9 @@
+# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
+# For additional information regarding the format and rule options, please see:
+# https://github.com/browserslist/browserslist#queries
+# For IE 9-11 support, please uncomment the last line of the file and adjust as needed
+> 0.5%
+last 2 versions
+Firefox ESR
+not dead
+# IE 9-11
\ No newline at end of file
diff --git a/Source/DashboardTabApp/src/environments/environment.prod.ts b/Source/DashboardTabApp/src/environments/environment.prod.ts
new file mode 100644
index 0000000..c4a9dca
--- /dev/null
+++ b/Source/DashboardTabApp/src/environments/environment.prod.ts
@@ -0,0 +1,23 @@
+// do not populate the following:
+// - token
+// - upn
+// - tid
+export const environment = {
+ production: true,
+ token: "",
+ upn: "",
+ tid: "",
+ authConfig: {
+ instance: "https://login.microsoftonline.com/",
+ tenantId: "",
+ clientId: "",
+ redirectUri: "/app-silent-end",
+ cacheLocation: "localStorage",
+ navigateToLoginRequestUrl: false,
+ extraQueryParameters: "",
+ popUp: true,
+ popUpUri: "/app-silent-start",
+ popUpWidth: 600,
+ popUpHeight: 535
+ }
+};
diff --git a/Source/DashboardTabApp/src/environments/environment.ts b/Source/DashboardTabApp/src/environments/environment.ts
new file mode 100644
index 0000000..c5769c9
--- /dev/null
+++ b/Source/DashboardTabApp/src/environments/environment.ts
@@ -0,0 +1,34 @@
+// This file can be replaced during build by using the `fileReplacements` array.
+// `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
+// The list of file replacements can be found in `angular.json`.
+
+export const environment = {
+ production: false,
+ apiBaseUrl: "https://qbot-api.azurewebsites.net/api/Request/",
+
+ authConfig: {
+ instance: "https://login.microsoftonline.com/",
+ tenantId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
+ clientId: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
+ redirectUri: "/app-silent-end",
+ cacheLocation: "localStorage",
+ navigateToLoginRequestUrl: false,
+ extraQueryParameters: "",
+ popUp: true,
+ popUpUri: "/app-silent-start",
+ popUpWidth: 600,
+ popUpHeight: 535
+ },
+
+ // do not populate the following:
+ upn: "",
+ tid: "",
+};
+
+/*
+ * In development mode, to ignore zone related error stack frames such as
+ * `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can
+ * import the following file, but please comment it out in production mode
+ * because it will have performance impact when throw error
+ */
+// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
diff --git a/Source/DashboardTabApp/src/favicon.ico b/Source/DashboardTabApp/src/favicon.ico
new file mode 100644
index 0000000..8081c7c
Binary files /dev/null and b/Source/DashboardTabApp/src/favicon.ico differ
diff --git a/Source/DashboardTabApp/src/index.html b/Source/DashboardTabApp/src/index.html
new file mode 100644
index 0000000..b22a258
--- /dev/null
+++ b/Source/DashboardTabApp/src/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ DashboardTabApp
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/DashboardTabApp/src/karma.conf.js b/Source/DashboardTabApp/src/karma.conf.js
new file mode 100644
index 0000000..b6e0042
--- /dev/null
+++ b/Source/DashboardTabApp/src/karma.conf.js
@@ -0,0 +1,31 @@
+// Karma configuration file, see link for more information
+// https://karma-runner.github.io/1.0/config/configuration-file.html
+
+module.exports = function (config) {
+ config.set({
+ basePath: '',
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
+ plugins: [
+ require('karma-jasmine'),
+ require('karma-chrome-launcher'),
+ require('karma-jasmine-html-reporter'),
+ require('karma-coverage-istanbul-reporter'),
+ require('@angular-devkit/build-angular/plugins/karma')
+ ],
+ client: {
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
+ },
+ coverageIstanbulReporter: {
+ dir: require('path').join(__dirname, '../coverage'),
+ reports: ['html', 'lcovonly'],
+ fixWebpackSourcePaths: true
+ },
+ reporters: ['progress', 'kjhtml'],
+ port: 9876,
+ colors: true,
+ logLevel: config.LOG_INFO,
+ autoWatch: true,
+ browsers: ['Chrome'],
+ singleRun: false
+ });
+};
\ No newline at end of file
diff --git a/Source/DashboardTabApp/src/main.ts b/Source/DashboardTabApp/src/main.ts
new file mode 100644
index 0000000..91ec6da
--- /dev/null
+++ b/Source/DashboardTabApp/src/main.ts
@@ -0,0 +1,12 @@
+import { enableProdMode } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+import { environment } from './environments/environment';
+
+if (environment.production) {
+ enableProdMode();
+}
+
+platformBrowserDynamic().bootstrapModule(AppModule)
+ .catch(err => console.log(err));
diff --git a/Source/DashboardTabApp/src/polyfills.ts b/Source/DashboardTabApp/src/polyfills.ts
new file mode 100644
index 0000000..f46a154
--- /dev/null
+++ b/Source/DashboardTabApp/src/polyfills.ts
@@ -0,0 +1,80 @@
+/**
+ * This file includes polyfills needed by Angular and is loaded before the app.
+ * You can add your own extra polyfills to this file.
+ *
+ * This file is divided into 2 sections:
+ * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
+ * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
+ * file.
+ *
+ * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
+ * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
+ * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
+ *
+ * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
+ */
+
+/***************************************************************************************************
+ * BROWSER POLYFILLS
+ */
+
+/** IE9, IE10 and IE11 requires all of the following polyfills. **/
+// import 'core-js/es6/symbol';
+// import 'core-js/es6/object';
+// import 'core-js/es6/function';
+// import 'core-js/es6/parse-int';
+// import 'core-js/es6/parse-float';
+// import 'core-js/es6/number';
+// import 'core-js/es6/math';
+// import 'core-js/es6/string';
+// import 'core-js/es6/date';
+// import 'core-js/es6/array';
+// import 'core-js/es6/regexp';
+// import 'core-js/es6/map';
+// import 'core-js/es6/weak-map';
+// import 'core-js/es6/set';
+
+/** IE10 and IE11 requires the following for NgClass support on SVG elements */
+// import 'classlist.js'; // Run `npm install --save classlist.js`.
+
+/** IE10 and IE11 requires the following for the Reflect API. */
+// import 'core-js/es6/reflect';
+
+
+/** Evergreen browsers require these. **/
+// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
+import 'core-js/es/reflect';
+
+
+/**
+ * Web Animations `@angular/platform-browser/animations`
+ * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
+ * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
+ **/
+// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
+
+/**
+ * By default, zone.js will patch all possible macroTask and DomEvents
+ * user can disable parts of macroTask/DomEvents patch by setting following flags
+ */
+
+ // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
+ // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
+ // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
+
+ /*
+ * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
+ * with the following flag, it will bypass `zone.js` patch for IE/Edge
+ */
+// (window as any).__Zone_enable_cross_context_check = true;
+
+/***************************************************************************************************
+ * Zone JS is required by default for Angular itself.
+ */
+import 'zone.js/dist/zone'; // Included with Angular CLI.
+
+
+
+/***************************************************************************************************
+ * APPLICATION IMPORTS
+ */
diff --git a/Source/DashboardTabApp/src/styles.css b/Source/DashboardTabApp/src/styles.css
new file mode 100644
index 0000000..a397843
--- /dev/null
+++ b/Source/DashboardTabApp/src/styles.css
@@ -0,0 +1,105 @@
+/* You can add global styles to this file, and also import other style files */
+@import "~@angular/material/prebuilt-themes/indigo-pink.css";
+body {
+ background-color: #edebe9;
+}
+
+
+
+.teamsTitle {
+ font-family: 'Segoe UI';
+}
+
+.teamsText {
+ font-family: 'Segoe UI';
+}
+
+#mainFilterContainer {
+ border-radius: 3px;
+ margin-bottom: 10px;
+}
+
+.nav-tabs {
+ font-family: 'Segoe UI';
+ border-bottom: none;
+ background-color: transparent;
+}
+
+ .nav-tabs > li:hover {
+ background-color: transparent;
+ }
+
+ .nav-tabs > li > a {
+ color: #16233A;
+ background-color: transparent;
+ }
+
+ .nav-tabs > li > a:hover {
+ border-top: none;
+ border-left: none;
+ border-right: none;
+ border-bottom-color: #16233A;
+ border-bottom-style: solid;
+ border-bottom-width: medium;
+ background-color: transparent;
+ color: #16233A;
+ }
+
+ .nav-tabs > li.active > a,
+ .nav-tabs > li.active > a:focus,
+ .nav-tabs > li.active > a:hover {
+ border-top: none;
+ border-left: none;
+ border-right: none;
+ border-bottom-color: #6364a7;
+ border-bottom-style: solid;
+ border-bottom-width: medium;
+ background-color: transparent;
+ color: #6364a7;
+ }
+
+ .nav-tabs > li > a.nav-icon {
+ margin: 5px;
+ }
+
+#collapseOne,
+#collapseTwo {
+ padding: 10px;
+}
+
+.questionsCollapseButton {
+ text-align: start;
+ width: 100%;
+ height: 100%;
+}
+
+.cardDiv > * {
+ /*background-color: #EEF1F5;*/
+ background-color: white;
+ display: block;
+ margin: 10px 0;
+}
+
+.cardHolder {
+ /*border-top-style:solid;*/
+ border-radius: 3px;
+ border-width: thin;
+ border-color: #6364a7;
+}
+
+.ac-pushButton {
+ padding: 0px 24px;
+ height: 32px;
+ border-radius: 3px;
+ color: white;
+ background-color: #6364a7;
+ border:none;
+}
+
+body { margin: 0; }
+
+html, body { height: 100%; }
+body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
+
+body { margin: 0; }
+
diff --git a/Source/DashboardTabApp/src/test.ts b/Source/DashboardTabApp/src/test.ts
new file mode 100644
index 0000000..1631789
--- /dev/null
+++ b/Source/DashboardTabApp/src/test.ts
@@ -0,0 +1,20 @@
+// This file is required by karma.conf.js and loads recursively all the .spec and framework files
+
+import 'zone.js/dist/zone-testing';
+import { getTestBed } from '@angular/core/testing';
+import {
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting
+} from '@angular/platform-browser-dynamic/testing';
+
+declare const require: any;
+
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting()
+);
+// Then we find all the tests.
+const context = require.context('./', true, /\.spec\.ts$/);
+// And load the modules.
+context.keys().map(context);
diff --git a/Source/DashboardTabApp/src/tsconfig.app.json b/Source/DashboardTabApp/src/tsconfig.app.json
new file mode 100644
index 0000000..722c370
--- /dev/null
+++ b/Source/DashboardTabApp/src/tsconfig.app.json
@@ -0,0 +1,12 @@
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../out-tsc/app",
+ "module": "es2015",
+ "types": []
+ },
+ "exclude": [
+ "src/test.ts",
+ "**/*.spec.ts"
+ ]
+}
diff --git a/Source/DashboardTabApp/src/tsconfig.spec.json b/Source/DashboardTabApp/src/tsconfig.spec.json
new file mode 100644
index 0000000..8f7cede
--- /dev/null
+++ b/Source/DashboardTabApp/src/tsconfig.spec.json
@@ -0,0 +1,19 @@
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../out-tsc/spec",
+ "module": "commonjs",
+ "types": [
+ "jasmine",
+ "node"
+ ]
+ },
+ "files": [
+ "test.ts",
+ "polyfills.ts"
+ ],
+ "include": [
+ "**/*.spec.ts",
+ "**/*.d.ts"
+ ]
+}
diff --git a/Source/DashboardTabApp/src/tslint.json b/Source/DashboardTabApp/src/tslint.json
new file mode 100644
index 0000000..52e2c1a
--- /dev/null
+++ b/Source/DashboardTabApp/src/tslint.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../tslint.json",
+ "rules": {
+ "directive-selector": [
+ true,
+ "attribute",
+ "app",
+ "camelCase"
+ ],
+ "component-selector": [
+ true,
+ "element",
+ "app",
+ "kebab-case"
+ ]
+ }
+}
diff --git a/Source/DashboardTabApp/src/web.config b/Source/DashboardTabApp/src/web.config
new file mode 100644
index 0000000..665f7c6
--- /dev/null
+++ b/Source/DashboardTabApp/src/web.config
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/DashboardTabApp/tsconfig.json b/Source/DashboardTabApp/tsconfig.json
new file mode 100644
index 0000000..ef44e28
--- /dev/null
+++ b/Source/DashboardTabApp/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "compileOnSave": false,
+ "compilerOptions": {
+ "baseUrl": "./",
+ "outDir": "./dist/out-tsc",
+ "sourceMap": true,
+ "declaration": false,
+ "moduleResolution": "node",
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "target": "es5",
+ "typeRoots": [
+ "node_modules/@types"
+ ],
+ "lib": [
+ "es2017",
+ "dom"
+ ]
+ }
+}
diff --git a/Source/DashboardTabApp/tslint.json b/Source/DashboardTabApp/tslint.json
new file mode 100644
index 0000000..3ea984c
--- /dev/null
+++ b/Source/DashboardTabApp/tslint.json
@@ -0,0 +1,130 @@
+{
+ "rulesDirectory": [
+ "node_modules/codelyzer"
+ ],
+ "rules": {
+ "arrow-return-shorthand": true,
+ "callable-types": true,
+ "class-name": true,
+ "comment-format": [
+ true,
+ "check-space"
+ ],
+ "curly": true,
+ "deprecation": {
+ "severity": "warn"
+ },
+ "eofline": true,
+ "forin": true,
+ "import-blacklist": [
+ true,
+ "rxjs/Rx"
+ ],
+ "import-spacing": true,
+ "indent": [
+ true,
+ "spaces"
+ ],
+ "interface-over-type-literal": true,
+ "label-position": true,
+ "max-line-length": [
+ true,
+ 140
+ ],
+ "member-access": false,
+ "member-ordering": [
+ true,
+ {
+ "order": [
+ "static-field",
+ "instance-field",
+ "static-method",
+ "instance-method"
+ ]
+ }
+ ],
+ "no-arg": true,
+ "no-bitwise": true,
+ "no-console": [
+ true,
+ "debug",
+ "info",
+ "time",
+ "timeEnd",
+ "trace"
+ ],
+ "no-construct": true,
+ "no-debugger": true,
+ "no-duplicate-super": true,
+ "no-empty": false,
+ "no-empty-interface": true,
+ "no-eval": true,
+ "no-inferrable-types": [
+ true,
+ "ignore-params"
+ ],
+ "no-misused-new": true,
+ "no-non-null-assertion": true,
+ "no-shadowed-variable": true,
+ "no-string-literal": false,
+ "no-string-throw": true,
+ "no-switch-case-fall-through": true,
+ "no-trailing-whitespace": true,
+ "no-unnecessary-initializer": true,
+ "no-unused-expression": true,
+ "no-use-before-declare": true,
+ "no-var-keyword": true,
+ "object-literal-sort-keys": false,
+ "one-line": [
+ true,
+ "check-open-brace",
+ "check-catch",
+ "check-else",
+ "check-whitespace"
+ ],
+ "prefer-const": true,
+ "quotemark": [
+ true,
+ "single"
+ ],
+ "radix": true,
+ "semicolon": [
+ true,
+ "always"
+ ],
+ "triple-equals": [
+ true,
+ "allow-null-check"
+ ],
+ "typedef-whitespace": [
+ true,
+ {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ }
+ ],
+ "unified-signatures": true,
+ "variable-name": false,
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type"
+ ],
+ "no-output-on-prefix": true,
+ "use-input-property-decorator": true,
+ "use-output-property-decorator": true,
+ "use-host-property-decorator": true,
+ "no-input-rename": true,
+ "no-output-rename": true,
+ "use-life-cycle-interface": true,
+ "use-pipe-transform-interface": true,
+ "component-class-suffix": true,
+ "directive-class-suffix": true
+ }
+}
diff --git a/Source/EncryptionHelper/CryptoTransform.cs b/Source/EncryptionHelper/CryptoTransform.cs
new file mode 100644
index 0000000..99b2402
--- /dev/null
+++ b/Source/EncryptionHelper/CryptoTransform.cs
@@ -0,0 +1,477 @@
+using System;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace EncryptionHelper
+{
+ public class CryptoTransform
+ {
+ #region Private members
+ // If hashing algorithm is not specified, use SHA-1.
+ private static string DEFAULT_HASH_ALGORITHM = "SHA256";
+
+ // If key size is not specified, use the longest 256-bit key.
+ private static int DEFAULT_KEY_SIZE = 256;
+
+ // Do not allow salt to be longer than 255 bytes, because we have only
+ // 1 byte to store its length.
+ private static int MAX_ALLOWED_SALT_LEN = 255;
+
+ // Do not allow salt to be smaller than 4 bytes, because we use the first
+ // 4 bytes of salt to store its length.
+ private static int MIN_ALLOWED_SALT_LEN = 4;
+
+ // Random salt value will be between 4 and 8 bytes long.
+ private static int DEFAULT_MIN_SALT_LEN = MIN_ALLOWED_SALT_LEN;
+ private static int DEFAULT_MAX_SALT_LEN = 8;
+
+ public static int minSaltLen
+ {
+ get; set;
+ }
+ public static int maxSaltLen
+ {
+ get; set;
+ }
+
+ public static ICryptoTransform encryptor
+ {
+ get; set;
+ }
+ public static ICryptoTransform decryptor
+ {
+ get; set;
+ }
+ // These members will be used to perform encryption and decryption.
+ #endregion
+
+ #region Constructors
+ ///
+ /// Use this constructor if you are planning to perform encryption/
+ /// decryption with 256-bit key, derived using 1 password iteration,
+ /// hashing without salt, no initialization vector, electronic codebook
+ /// (ECB) mode, SHA-1 hashing algorithm, and 4-to-8 byte long salt.
+ ///
+ ///
+ /// Passphrase from which a pseudo-random password will be derived.
+ /// The derived password will be used to generate the encryption key.
+ /// Passphrase can be any string. In this example we assume that the
+ /// passphrase is an ASCII string. Passphrase value must be kept in
+ /// secret.
+ ///
+ ///
+ /// This constructor is not recommended because it does not use
+ /// initialization vector and uses the ECB cipher mode, which is less
+ /// secure than the CBC mode.
+ ///
+ public CryptoTransform(string passPhrase) :
+ this(passPhrase, null)
+ {
+ }
+
+ ///
+ /// Use this constructor if you are planning to perform encryption/
+ /// decryption with 256-bit key, derived using 1 password iteration,
+ /// hashing without salt, cipher block chaining (CBC) mode, SHA-1
+ /// hashing algorithm, and 4-to-8 byte long salt.
+ ///
+ ///
+ /// Passphrase from which a pseudo-random password will be derived.
+ /// The derived password will be used to generate the encryption key.
+ /// Passphrase can be any string. In this example we assume that the
+ /// passphrase is an ASCII string. Passphrase value must be kept in
+ /// secret.
+ ///
+ ///
+ /// Initialization vector (IV). This value is required to encrypt the
+ /// first block of plaintext data. For RijndaelManaged class IV must be
+ /// exactly 16 ASCII characters long. IV value does not have to be kept
+ /// in secret.
+ ///
+ public CryptoTransform(string passPhrase,
+ string initVector) :
+ this(passPhrase, initVector, -1)
+ {
+ }
+
+ ///
+ /// Use this constructor if you are planning to perform encryption/
+ /// decryption with 256-bit key, derived using 1 password iteration,
+ /// hashing without salt, cipher block chaining (CBC) mode, SHA-1
+ /// hashing algorithm, and 0-to-8 byte long salt.
+ ///
+ ///
+ /// Passphrase from which a pseudo-random password will be derived.
+ /// The derived password will be used to generate the encryption key
+ /// Passphrase can be any string. In this example we assume that the
+ /// passphrase is an ASCII string. Passphrase value must be kept in
+ /// secret.
+ ///
+ ///
+ /// Initialization vector (IV). This value is required to encrypt the
+ /// first block of plaintext data. For RijndaelManaged class IV must be
+ /// exactly 16 ASCII characters long. IV value does not have to be kept
+ /// in secret.
+ ///
+ ///
+ /// Min size (in bytes) of randomly generated salt which will be added at
+ /// the beginning of plain text before encryption is performed. When this
+ /// value is less than 4, the default min value will be used (currently 4
+ /// bytes).
+ ///
+ public CryptoTransform(string passPhrase,
+ string initVector,
+ int minSaltLen) :
+ this(passPhrase, initVector, minSaltLen, -1)
+ {
+ }
+
+ ///
+ /// Use this constructor if you are planning to perform encryption/
+ /// decryption with 256-bit key, derived using 1 password iteration,
+ /// hashing without salt, cipher block chaining (CBC) mode, SHA-1
+ /// hashing algorithm. Use the minSaltLen and maxSaltLen parameters to
+ /// specify the size of randomly generated salt.
+ ///
+ ///
+ /// Passphrase from which a pseudo-random password will be derived.
+ /// The derived password will be used to generate the encryption key.
+ /// Passphrase can be any string. In this example we assume that the
+ /// passphrase is an ASCII string. Passphrase value must be kept in
+ /// secret.
+ ///
+ ///
+ /// Initialization vector (IV). This value is required to encrypt the
+ /// first block of plaintext data. For RijndaelManaged class IV must be
+ /// exactly 16 ASCII characters long. IV value does not have to be kept
+ /// in secret.
+ ///
+ ///
+ /// Min size (in bytes) of randomly generated salt which will be added at
+ /// the beginning of plain text before encryption is performed. When this
+ /// value is less than 4, the default min value will be used (currently 4
+ /// bytes).
+ ///
+ ///
+ /// Max size (in bytes) of randomly generated salt which will be added at
+ /// the beginning of plain text before encryption is performed. When this
+ /// value is negative or greater than 255, the default max value will be
+ /// used (currently 8 bytes). If max value is 0 (zero) or if it is smaller
+ /// than the specified min value (which can be adjusted to default value),
+ /// salt will not be used and plain text value will be encrypted as is.
+ /// In this case, salt will not be processed during decryption either.
+ ///
+ public CryptoTransform(string passPhrase,
+ string initVector,
+ int minSaltLen,
+ int maxSaltLen) :
+ this(passPhrase, initVector, minSaltLen, maxSaltLen, -1)
+ {
+ }
+
+ ///
+ /// Use this constructor if you are planning to perform encryption/
+ /// decryption using the key derived from 1 password iteration,
+ /// hashing without salt, cipher block chaining (CBC) mode, and
+ /// SHA-1 hashing algorithm.
+ ///
+ ///
+ /// Passphrase from which a pseudo-random password will be derived.
+ /// The derived password will be used to generate the encryption key.
+ /// Passphrase can be any string. In this example we assume that the
+ /// passphrase is an ASCII string. Passphrase value must be kept in
+ /// secret.
+ ///
+ ///
+ /// Initialization vector (IV). This value is required to encrypt the
+ /// first block of plaintext data. For RijndaelManaged class IV must be
+ /// exactly 16 ASCII characters long. IV value does not have to be kept
+ /// in secret.
+ ///
+ ///
+ /// Min size (in bytes) of randomly generated salt which will be added at
+ /// the beginning of plain text before encryption is performed. When this
+ /// value is less than 4, the default min value will be used (currently 4
+ /// bytes).
+ ///
+ ///
+ /// Max size (in bytes) of randomly generated salt which will be added at
+ /// the beginning of plain text before encryption is performed. When this
+ /// value is negative or greater than 255, the default max value will be
+ /// used (currently 8 bytes). If max value is 0 (zero) or if it is smaller
+ /// than the specified min value (which can be adjusted to default value),
+ /// salt will not be used and plain text value will be encrypted as is.
+ /// In this case, salt will not be processed during decryption either.
+ ///
+ ///
+ /// Size of symmetric key (in bits): 128, 192, or 256.
+ ///
+ public CryptoTransform(string passPhrase,
+ string initVector,
+ int minSaltLen,
+ int maxSaltLen,
+ int keySize) :
+ this(passPhrase, initVector, minSaltLen, maxSaltLen, keySize, null)
+ {
+ }
+
+ ///
+ /// Use this constructor if you are planning to perform encryption/
+ /// decryption using the key derived from 1 password iteration, hashing
+ /// without salt, and cipher block chaining (CBC) mode.
+ ///
+ ///
+ /// Passphrase from which a pseudo-random password will be derived.
+ /// The derived password will be used to generate the encryption key.
+ /// Passphrase can be any string. In this example we assume that the
+ /// passphrase is an ASCII string. Passphrase value must be kept in
+ /// secret.
+ ///
+ ///
+ /// Initialization vector (IV). This value is required to encrypt the
+ /// first block of plaintext data. For RijndaelManaged class IV must be
+ /// exactly 16 ASCII characters long. IV value does not have to be kept
+ /// in secret.
+ ///
+ ///
+ /// Min size (in bytes) of randomly generated salt which will be added at
+ /// the beginning of plain text before encryption is performed. When this
+ /// value is less than 4, the default min value will be used (currently 4
+ /// bytes).
+ ///
+ ///
+ /// Max size (in bytes) of randomly generated salt which will be added at
+ /// the beginning of plain text before encryption is performed. When this
+ /// value is negative or greater than 255, the default max value will be
+ /// used (currently 8 bytes). If max value is 0 (zero) or if it is smaller
+ /// than the specified min value (which can be adjusted to default value),
+ /// salt will not be used and plain text value will be encrypted as is.
+ /// In this case, salt will not be processed during decryption either.
+ ///
+ ///
+ /// Size of symmetric key (in bits): 128, 192, or 256.
+ ///
+ ///
+ /// Hashing algorithm: "MD5" or "SHA1". SHA1 is recommended.
+ ///
+ public CryptoTransform(string passPhrase,
+ string initVector,
+ int minSaltLen,
+ int maxSaltLen,
+ int keySize,
+ string hashAlgorithm) :
+ this(passPhrase, initVector, minSaltLen, maxSaltLen, keySize,
+ hashAlgorithm, null)
+ {
+ }
+
+ ///
+ /// Use this constructor if you are planning to perform encryption/
+ /// decryption using the key derived from 1 password iteration, and
+ /// cipher block chaining (CBC) mode.
+ ///
+ ///
+ /// Passphrase from which a pseudo-random password will be derived.
+ /// The derived password will be used to generate the encryption key.
+ /// Passphrase can be any string. In this example we assume that the
+ /// passphrase is an ASCII string. Passphrase value must be kept in
+ /// secret.
+ ///
+ ///
+ /// Initialization vector (IV). This value is required to encrypt the
+ /// first block of plaintext data. For RijndaelManaged class IV must be
+ /// exactly 16 ASCII characters long. IV value does not have to be kept
+ /// in secret.
+ ///
+ ///
+ /// Min size (in bytes) of randomly generated salt which will be added at
+ /// the beginning of plain text before encryption is performed. When this
+ /// value is less than 4, the default min value will be used (currently 4
+ /// bytes).
+ ///
+ ///
+ /// Max size (in bytes) of randomly generated salt which will be added at
+ /// the beginning of plain text before encryption is performed. When this
+ /// value is negative or greater than 255, the default max value will be
+ /// used (currently 8 bytes). If max value is 0 (zero) or if it is smaller
+ /// than the specified min value (which can be adjusted to default value),
+ /// salt will not be used and plain text value will be encrypted as is.
+ /// In this case, salt will not be processed during decryption either.
+ ///
+ ///
+ /// Size of symmetric key (in bits): 128, 192, or 256.
+ ///
+ ///
+ /// Hashing algorithm: "MD5" or "SHA1". SHA1 is recommended.
+ ///
+ ///
+ /// Salt value used for password hashing during key generation. This is
+ /// not the same as the salt we will use during encryption. This parameter
+ /// can be any string.
+ ///
+ public CryptoTransform(string passPhrase,
+ string initVector,
+ int minSaltLen,
+ int maxSaltLen,
+ int keySize,
+ string hashAlgorithm,
+ string saltValue) :
+ this(passPhrase, initVector, minSaltLen, maxSaltLen, keySize,
+ hashAlgorithm, saltValue, 1)
+ {
+ }
+
+ ///
+ /// Use this constructor if you are planning to perform encryption/
+ /// decryption with the key derived from the explicitly specified
+ /// parameters.
+ ///
+ ///
+ /// Passphrase from which a pseudo-random password will be derived.
+ /// The derived password will be used to generate the encryption key
+ /// Passphrase can be any string. In this example we assume that the
+ /// passphrase is an ASCII string. Passphrase value must be kept in
+ /// secret.
+ ///
+ ///
+ /// Initialization vector (IV). This value is required to encrypt the
+ /// first block of plaintext data. For RijndaelManaged class IV must be
+ /// exactly 16 ASCII characters long. IV value does not have to be kept
+ /// in secret.
+ ///
+ ///
+ /// Min size (in bytes) of randomly generated salt which will be added at
+ /// the beginning of plain text before encryption is performed. When this
+ /// value is less than 4, the default min value will be used (currently 4
+ /// bytes).
+ ///
+ ///
+ /// Max size (in bytes) of randomly generated salt which will be added at
+ /// the beginning of plain text before encryption is performed. When this
+ /// value is negative or greater than 255, the default max value will be
+ /// used (currently 8 bytes). If max value is 0 (zero) or if it is smaller
+ /// than the specified min value (which can be adjusted to default value),
+ /// salt will not be used and plain text value will be encrypted as is.
+ /// In this case, salt will not be processed during decryption either.
+ ///
+ ///
+ /// Size of symmetric key (in bits): 128, 192, or 256.
+ ///
+ ///
+ /// Hashing algorithm: "MD5" or "SHA1". SHA1 is recommended.
+ ///
+ ///
+ /// Salt value used for password hashing during key generation. This is
+ /// not the same as the salt we will use during encryption. This parameter
+ /// can be any string.
+ ///
+ ///
+ /// Number of iterations used to hash password. More iterations are
+ /// considered more secure but may take longer.
+ ///
+ public CryptoTransform(string passPhrase,
+ string initVector,
+ int minSaltLen,
+ int maxSaltLen,
+ int keySize,
+ string hashAlgorithm,
+ string saltValue,
+ int passwordIterations)
+ {
+ // Save min salt length; set it to default if invalid value is passed.
+ if (minSaltLen < MIN_ALLOWED_SALT_LEN)
+ CryptoTransform.minSaltLen = DEFAULT_MIN_SALT_LEN;
+ else
+ CryptoTransform.minSaltLen = minSaltLen;
+
+ // Save max salt length; set it to default if invalid value is passed.
+ if (maxSaltLen < 0 || maxSaltLen > MAX_ALLOWED_SALT_LEN)
+ CryptoTransform.maxSaltLen = DEFAULT_MAX_SALT_LEN;
+ else
+ CryptoTransform.maxSaltLen = maxSaltLen;
+
+ // Set the size of cryptographic key.
+ if (keySize <= 0)
+ keySize = DEFAULT_KEY_SIZE;
+
+ // Set the name of algorithm. Make sure it is in UPPER CASE and does
+ // not use dashes, e.g. change "sha-1" to "SHA1".
+ if (hashAlgorithm == null)
+ hashAlgorithm = DEFAULT_HASH_ALGORITHM;
+ else
+ hashAlgorithm = hashAlgorithm.ToUpper().Replace("-", "");
+
+ // Initialization vector converted to a byte array.
+ byte[] initVectorBytes = null;
+
+ // Salt used for password hashing (to generate the key, not during
+ // encryption) converted to a byte array.
+ byte[] saltValueBytes = null;
+
+ // Get bytes of initialization vector.
+ if (initVector == null)
+ initVectorBytes = new byte[0];
+ else
+ initVectorBytes = Encoding.ASCII.GetBytes(initVector);
+
+ // Get bytes of salt (used in hashing).
+ if (saltValue == null)
+ saltValueBytes = new byte[0];
+ else
+ saltValueBytes = Encoding.ASCII.GetBytes(saltValue);
+
+ // Generate password, which will be used to derive the key.
+ PasswordDeriveBytes password = new PasswordDeriveBytes(
+ passPhrase,
+ saltValueBytes,
+ hashAlgorithm,
+ passwordIterations);
+
+ // Convert key to a byte array adjusting the size from bits to bytes.
+ byte[] keyBytes = password.GetBytes(keySize / 8);
+
+ // Initialize Rijndael key object.
+ RijndaelManaged symmetricKey = new RijndaelManaged();
+
+ // If we do not have initialization vector, we cannot use the CBC mode.
+ // The only alternative is the ECB mode (which is not as good).
+ if (initVectorBytes.Length == 0)
+ symmetricKey.Mode = CipherMode.ECB;
+ else
+ symmetricKey.Mode = CipherMode.CBC;
+
+ // Create encryptor and decryptor, which we will use for cryptographic
+ // operations.
+ CryptoTransform.encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
+ CryptoTransform.decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
+ }
+
+ public string Encrypt(string textToEncrypt)
+ {
+ try
+ {
+
+ Encrypt e = new Encrypt();
+ return e.EncryptString(textToEncrypt);
+ }
+ catch (Exception e)
+ {
+ return string.Empty;
+ }
+ }
+
+ public string Decrypt(string textToDecrypt)
+ {
+ try
+ {
+ Decrypt d = new Decrypt();
+ return d.DecryptString(textToDecrypt);
+ }
+ catch (Exception e)
+ {
+ return string.Empty;
+ }
+ }
+ #endregion
+ }
+}
diff --git a/Source/EncryptionHelper/Decrypt.cs b/Source/EncryptionHelper/Decrypt.cs
new file mode 100644
index 0000000..3c0c7e0
--- /dev/null
+++ b/Source/EncryptionHelper/Decrypt.cs
@@ -0,0 +1,109 @@
+using System;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace EncryptionHelper
+{
+ public class Decrypt
+ {
+ public string DecryptString(string cipherText)
+ {
+ return DecryptBytes(Convert.FromBase64String(cipherText));
+ }
+
+ ///
+ /// Decrypts a byte array containing cipher text value and generates a
+ /// string result.
+ ///
+ ///
+ /// Byte array containing encrypted data.
+ ///
+ ///
+ /// Decrypted string value.
+ ///
+ private string DecryptBytes(byte[] cipherTextBytes)
+ {
+ return Encoding.UTF8.GetString(DecryptToBytes(cipherTextBytes));
+ }
+
+ ///
+ /// Decrypts a base64-encoded cipher text value and generates a byte array
+ /// of plain text data.
+ ///
+ ///
+ /// Base64-encoded cipher text string to be decrypted.
+ ///
+ ///
+ /// Byte array containing decrypted value.
+ ///
+ private byte[] DecryptToBytes(string cipherText)
+ {
+ return DecryptToBytes(Convert.FromBase64String(cipherText));
+ }
+
+ ///
+ /// Decrypts a base64-encoded cipher text value and generates a byte array
+ /// of plain text data.
+ ///
+ ///
+ /// Byte array containing encrypted data.
+ ///
+ ///
+ /// Byte array containing decrypted value.
+ ///
+ private byte[] DecryptToBytes(byte[] cipherTextBytes)
+ {
+ byte[] decryptedBytes = null;
+ byte[] plainTextBytes = null;
+ int decryptedByteCount = 0;
+ int saltLen = 0;
+
+ MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
+
+ // Since we do not know how big decrypted value will be, use the same
+ // size as cipher text. Cipher text is always longer than plain text
+ // (in block cipher encryption), so we will just use the number of
+ // decrypted data byte after we know how big it is.
+ decryptedBytes = new byte[cipherTextBytes.Length];
+
+ // Let's make cryptographic operations thread-safe.
+ lock (this)
+ {
+ // To perform decryption, we must use the Read mode.
+ CryptoStream cryptoStream = new CryptoStream(
+ memoryStream,
+ CryptoTransform.decryptor,
+ CryptoStreamMode.Read);
+
+ // Decrypting data and get the count of plain text bytes.
+ decryptedByteCount = cryptoStream.Read(decryptedBytes,
+ 0,
+ decryptedBytes.Length);
+ // Release memory.
+ memoryStream.Close();
+ cryptoStream.Close();
+ }
+
+ // If we are using salt, get its length from the first 4 bytes of plain
+ // text data.
+ if (CryptoTransform.maxSaltLen > 0 && CryptoTransform.maxSaltLen >= CryptoTransform.minSaltLen)
+ {
+ saltLen = (decryptedBytes[0] & 0x03) |
+ (decryptedBytes[1] & 0x0c) |
+ (decryptedBytes[2] & 0x30) |
+ (decryptedBytes[3] & 0xc0);
+ }
+
+ // Allocate the byte array to hold the original plain text (without salt).
+ plainTextBytes = new byte[decryptedByteCount - saltLen];
+
+ // Copy original plain text discarding the salt value if needed.
+ Array.Copy(decryptedBytes, saltLen, plainTextBytes,
+ 0, decryptedByteCount - saltLen);
+
+ // Return original plain text value.
+ return plainTextBytes;
+ }
+ }
+}
diff --git a/Source/EncryptionHelper/Encrypt.cs b/Source/EncryptionHelper/Encrypt.cs
new file mode 100644
index 0000000..b3efc95
--- /dev/null
+++ b/Source/EncryptionHelper/Encrypt.cs
@@ -0,0 +1,91 @@
+using System;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace EncryptionHelper
+{
+ public class Encrypt
+ {
+ public string EncryptString(string plainText)
+ {
+ return EncryptBytes(Encoding.UTF8.GetBytes(plainText));
+ }
+
+ ///
+ /// Encrypts a byte array generating a base64-encoded string.
+ ///
+ ///
+ /// Plain text bytes to be encrypted.
+ ///
+ ///
+ /// Cipher text formatted as a base64-encoded string.
+ ///
+ private string EncryptBytes(byte[] plainTextBytes)
+ {
+ return Convert.ToBase64String(EncryptToBytes(plainTextBytes));
+ }
+
+ ///
+ /// Encrypts a string value generating a byte array of cipher text.
+ ///
+ ///
+ /// Plain text string to be encrypted.
+ ///
+ ///
+ /// Cipher text formatted as a byte array.
+ ///
+ private byte[] EncryptToBytes(string plainText)
+ {
+ return EncryptToBytes(Encoding.UTF8.GetBytes(plainText));
+ }
+
+ ///
+ /// Encrypts a byte array generating a byte array of cipher text.
+ ///
+ ///
+ /// Plain text bytes to be encrypted.
+ ///
+ ///
+ /// Cipher text formatted as a byte array.
+ ///
+ private byte[] EncryptToBytes(byte[] plainTextBytes)
+ {
+ // Add salt at the beginning of the plain text bytes (if needed).
+ byte[] plainTextBytesWithSalt = Helper.AddSalt(plainTextBytes);
+
+ // Encryption will be performed using memory stream.
+ MemoryStream memoryStream = new MemoryStream();
+
+ // Let's make cryptographic operations thread-safe.
+ //lock (this)
+ //{
+ // To perform encryption, we must use the Write mode.
+ CryptoStream cryptoStream = new CryptoStream(
+ memoryStream,
+ CryptoTransform.encryptor,
+ CryptoStreamMode.Write);
+
+ if (cryptoStream != null)
+ {
+ // Start encrypting data.
+ cryptoStream.Write(plainTextBytesWithSalt,
+ 0,
+ plainTextBytesWithSalt.Length);
+ }
+ // Finish the encryption operation.
+ cryptoStream.FlushFinalBlock();
+
+ // Move encrypted data from memory into a byte array.
+ byte[] cipherTextBytes = memoryStream.ToArray();
+
+ // Close memory streams.
+ memoryStream.Close();
+ cryptoStream.Close();
+
+ // Return encrypted data.
+ return cipherTextBytes;
+ //}
+ }
+ }
+}
diff --git a/Source/EncryptionHelper/EncryptionHelper.csproj b/Source/EncryptionHelper/EncryptionHelper.csproj
new file mode 100644
index 0000000..7b08a49
--- /dev/null
+++ b/Source/EncryptionHelper/EncryptionHelper.csproj
@@ -0,0 +1,71 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {8392407D-7934-4D2A-B0F0-BD6E866A2E38}
+ Library
+ Properties
+ EncryptionHelper
+ EncryptionHelper
+ v4.5
+ 512
+ SAK
+ SAK
+ SAK
+ SAK
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ bin\Release.CQU\
+ TRACE
+ true
+ pdbonly
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/EncryptionHelper/Helper.cs b/Source/EncryptionHelper/Helper.cs
new file mode 100644
index 0000000..d78d717
--- /dev/null
+++ b/Source/EncryptionHelper/Helper.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Security.Cryptography;
+
+namespace EncryptionHelper
+{
+ public static class Helper
+ {
+ public const string PASSPHRASE = "Pas5pr@se1"; // can be any string
+ public const string INITVECTOR = "@1B2c3D4e5F6g7H1"; // must be 16 bytes
+
+ // Use these members to save min and max salt lengths.
+ public static int minSaltLen = -1;
+ public static int maxSaltLen = -1;
+ public static byte[] AddSalt(byte[] plainTextBytes)
+ {
+ // The max salt value of 0 (zero) indicates that we should not use
+ // salt. Also do not use salt if the max salt value is smaller than
+ // the min value.
+ if (maxSaltLen == 0 || maxSaltLen < minSaltLen)
+ return plainTextBytes;
+
+ // Generate the salt.
+ byte[] saltBytes = GenerateSalt();
+
+ // Allocate array which will hold salt and plain text bytes.
+ byte[] plainTextBytesWithSalt = new byte[plainTextBytes.Length +
+ saltBytes.Length];
+ // First, copy salt bytes.
+ Array.Copy(saltBytes, plainTextBytesWithSalt, saltBytes.Length);
+
+ // Append plain text bytes to the salt value.
+ Array.Copy(plainTextBytes, 0,
+ plainTextBytesWithSalt, saltBytes.Length,
+ plainTextBytes.Length);
+
+ return plainTextBytesWithSalt;
+ }
+
+ ///
+ /// Generates an array holding cryptographically strong bytes.
+ ///
+ ///
+ /// Array of randomly generated bytes.
+ ///
+ ///
+ /// Salt size will be defined at random or exactly as specified by the
+ /// minSlatLen and maxSaltLen parameters passed to the object constructor.
+ /// The first four bytes of the salt array will contain the salt length
+ /// split into four two-bit pieces.
+ ///
+ private static byte[] GenerateSalt()
+ {
+ // We don't have the length, yet.
+ int saltLen = 0;
+
+ // If min and max salt values are the same, it should not be random.
+ if (CryptoTransform.minSaltLen == CryptoTransform.maxSaltLen)
+ saltLen = minSaltLen;
+ // Use random number generator to calculate salt length.
+ else
+ saltLen = GenerateRandomNumber(CryptoTransform.minSaltLen, CryptoTransform.maxSaltLen);
+
+ // Allocate byte array to hold our salt.
+ byte[] salt = new byte[saltLen];
+
+ // Populate salt with cryptographically strong bytes.
+ RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
+
+ rng.GetNonZeroBytes(salt);
+
+ // Split salt length (always one byte) into four two-bit pieces and
+ // store these pieces in the first four bytes of the salt array.
+ salt[0] = (byte)((salt[0] & 0xfc) | (saltLen & 0x03));
+ salt[1] = (byte)((salt[1] & 0xf3) | (saltLen & 0x0c));
+ salt[2] = (byte)((salt[2] & 0xcf) | (saltLen & 0x30));
+ salt[3] = (byte)((salt[3] & 0x3f) | (saltLen & 0xc0));
+
+ return salt;
+ }
+
+ ///
+ /// Generates random integer.
+ ///
+ ///
+ /// Min value (inclusive).
+ ///
+ ///
+ /// Max value (inclusive).
+ ///
+ ///
+ /// Random integer value between the min and max values (inclusive).
+ ///
+ ///
+ /// This methods overcomes the limitations of .NET Framework's Random
+ /// class, which - when initialized multiple times within a very short
+ /// period of time - can generate the same "random" number.
+ ///
+ private static int GenerateRandomNumber(int minValue, int maxValue)
+ {
+ // We will make up an integer seed from 4 bytes of this array.
+ byte[] randomBytes = new byte[4];
+
+ // Generate 4 random bytes.
+ RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
+ rng.GetBytes(randomBytes);
+
+ // Convert four random bytes into a positive integer value.
+ int seed = ((randomBytes[0] & 0x7f) << 24) |
+ (randomBytes[1] << 16) |
+ (randomBytes[2] << 8) |
+ (randomBytes[3]);
+
+ // Now, this looks more like real randomization.
+ Random random = new Random(seed);
+
+ // Calculate a random number.
+ return random.Next(minValue, maxValue + 1);
+ }
+
+
+ }
+}
diff --git a/Source/EncryptionHelper/Properties/AssemblyInfo.cs b/Source/EncryptionHelper/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..04b72ee
--- /dev/null
+++ b/Source/EncryptionHelper/Properties/AssemblyInfo.cs
@@ -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("EncryptionHelper")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("EncryptionHelper")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[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("8392407d-7934-4d2a-b0f0-bd6e866a2e38")]
+
+// 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")]
diff --git a/Source/GlobalSuppressions.cs b/Source/GlobalSuppressions.cs
new file mode 100644
index 0000000..fbbf0dc
--- /dev/null
+++ b/Source/GlobalSuppressions.cs
@@ -0,0 +1,7 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+//
+
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1629:Documentation text should end with a period", Justification = "Convention")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1200:Using directives should be placed correctly", Justification = "")]
+[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:Prefix local calls with this", Justification = "")]
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/App_Start/FilterConfig.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/App_Start/FilterConfig.cs
new file mode 100644
index 0000000..646b629
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/App_Start/FilterConfig.cs
@@ -0,0 +1,13 @@
+using System.Web;
+using System.Web.Mvc;
+
+namespace Microsoft.Teams.Apps.QBot.Bot
+{
+ public class FilterConfig
+ {
+ public static void RegisterGlobalFilters(GlobalFilterCollection filters)
+ {
+ filters.Add(new HandleErrorAttribute());
+ }
+ }
+}
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/App_Start/RouteConfig.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/App_Start/RouteConfig.cs
new file mode 100644
index 0000000..53ac272
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/App_Start/RouteConfig.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+using System.Web.Routing;
+
+namespace Microsoft.Teams.Apps.QBot.Bot
+{
+ public class RouteConfig
+ {
+ public static void RegisterRoutes(RouteCollection routes)
+ {
+ routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
+ routes.MapMvcAttributeRoutes();
+
+ }
+ }
+}
+
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/App_Start/WebApiConfig.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/App_Start/WebApiConfig.cs
new file mode 100644
index 0000000..32ef443
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/App_Start/WebApiConfig.cs
@@ -0,0 +1,37 @@
+using System.Web.Http;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Serialization;
+
+namespace Microsoft.Teams.Apps.QBot.Bot
+{
+ public static class WebApiConfig
+ {
+ public static void Register(HttpConfiguration config)
+ {
+ // Json settings
+ config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
+ config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
+ config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter { CamelCaseText = true });
+ config.Formatters.JsonFormatter.SerializerSettings.Formatting = Formatting.Indented;
+ config.EnableCors();
+ JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
+ {
+ ContractResolver = new CamelCasePropertyNamesContractResolver(),
+ Formatting = Newtonsoft.Json.Formatting.Indented,
+ NullValueHandling = NullValueHandling.Ignore,
+ };
+
+ // Web API configuration and services
+
+ // Web API routes
+ config.MapHttpAttributeRoutes();
+
+ config.Routes.MapHttpRoute(
+ name: "DefaultApi",
+ routeTemplate: "api/{controller}/{id}",
+ defaults: new { id = RouteParameter.Optional }
+ );
+ }
+ }
+}
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/ApplicationInsights.config b/Source/Microsoft.Teams.Apps.QBot.Bot/ApplicationInsights.config
new file mode 100644
index 0000000..cdcf7f7
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/ApplicationInsights.config
@@ -0,0 +1,136 @@
+
+
+
+ b8e77531-6035-4773-9a14-883984411fb6
+
+
+
+
+
+
+
+
+ search|spider|crawl|Bot|Monitor|AlwaysOn
+
+
+
+
+
+
+
+
+
+
+
+
+
+ core.windows.net
+ core.chinacloudapi.cn
+ core.cloudapi.de
+ core.usgovcloudapi.net
+ localhost
+ 127.0.0.1
+
+
+ Microsoft.Azure.EventHubs
+ Microsoft.Azure.ServiceBus
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Microsoft.VisualStudio.Web.PageInspector.Runtime.Tracing.RequestDataHttpHandler
+ System.Web.StaticFileHandler
+ System.Web.Handlers.AssemblyResourceLoader
+ System.Web.Optimization.BundleHandler
+ System.Web.Script.Services.ScriptHandlerFactory
+ System.Web.Handlers.TraceHandler
+ System.Web.Services.Discovery.DiscoveryRequestHandler
+ System.Web.HttpDebugHandler
+
+
+
+
+
+
+
+
+
+
+ 5
+ Event
+
+
+ 5
+ Event
+
+
+
+
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Connected Services/Application Insights/ConnectedService.json b/Source/Microsoft.Teams.Apps.QBot.Bot/Connected Services/Application Insights/ConnectedService.json
new file mode 100644
index 0000000..64d3356
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Connected Services/Application Insights/ConnectedService.json
@@ -0,0 +1,7 @@
+{
+ "ProviderId": "Microsoft.ApplicationInsights.ConnectedService.ConnectedServiceProvider",
+ "Version": "8.12.10405.1",
+ "GettingStartedDocument": {
+ "Uri": "https://go.microsoft.com/fwlink/?LinkID=613413"
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Controllers/HomeController.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Controllers/HomeController.cs
new file mode 100644
index 0000000..9de9a3d
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Controllers/HomeController.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+using Microsoft.Teams.Apps.QBot.Bot.utility;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Controllers
+{
+ [RoutePrefix("home")]
+ public class HomeController : Controller
+ {
+ // GET: Home
+ [HttpGet]
+ [Route("")]
+ public ActionResult Index()
+ {
+ return View();
+ }
+
+ [HttpGet]
+ [Route("selectanswer")]
+ public ActionResult SelectAnswer()
+ {
+ var payload = Request.QueryString["json"];
+
+ ViewBag.Payload = HttpUtility.HtmlDecode(payload);
+ return View();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Controllers/MessagesController.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Controllers/MessagesController.cs
new file mode 100644
index 0000000..28e68eb
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Controllers/MessagesController.cs
@@ -0,0 +1,787 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+using System.Web.Http;
+
+using AdaptiveCards;
+
+using Antares.Bot.Channels;
+
+using Microsoft.Bot.Builder.Dialogs;
+using Microsoft.Bot.Connector;
+using Microsoft.Bot.Connector.Teams;
+using Microsoft.Bot.Connector.Teams.Models;
+using Microsoft.Teams.Apps.QBot.Bot.Services;
+using Microsoft.Teams.Apps.QBot.Bot.utility;
+using Microsoft.Teams.Apps.QBot.Model;
+using Microsoft.Teams.Apps.QBot.Model.Teams;
+
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+
+namespace Microsoft.Teams.Apps.QBot.Bot
+{
+ [BotAuthentication]
+ public class MessagesController : ApiController
+ {
+ ///
+ /// POST: api/Messages
+ /// Receive a message from a user and reply to it
+ ///
+ public async Task Post([FromBody]Microsoft.Bot.Connector.Activity activity)
+ {
+ var activityType = GetActivityTypeFrom(activity);
+
+ if (activityType == ActivityTypes.Message)
+ {
+ try
+ {
+ await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ }
+ }
+ else if (activityType == ActivityTypes.Invoke)
+ {
+ return await HandleInvokeMessages(activity);
+ }
+ else
+ {
+ await HandleSystemMessage(activity);
+ }
+
+ var response = Request.CreateResponse(HttpStatusCode.OK);
+ return response;
+ }
+
+ private async Task HandleInvokeMessages(Microsoft.Bot.Connector.Activity message)
+ {
+ string invokeType = (message.Value as dynamic)["type"];
+ string command = (message.Value as dynamic)["commandId"];
+
+ if (invokeType == Constants.ACTIVITY_SELECT_ANSWER)
+ {
+ await HandleSelectAnswerFromCard(message);
+ }
+ else if (invokeType == Constants.ACTIVITY_BOT_HELPFUL)
+ {
+ await HandleBotHelpful(message);
+ }
+ else if (invokeType == Constants.ACTIVITY_BOT_NOT_HELPFUL)
+ {
+ await HandleBotNotHelpful(message);
+ }
+ else if (invokeType == Constants.ACTIVITY_MARKED_ANSWERED)
+ {
+ await HandleMarkedAnswerFromCard(message);
+ }
+ else
+ {
+ if (command == Constants.ACTIVITY_SELECT_ANSWER)
+ {
+ return await HandleSelectAnswerFromMessageAction(message);
+ }
+ }
+
+ return Request.CreateResponse(HttpStatusCode.OK);
+ }
+
+ private async Task HandleBotHelpful(Microsoft.Bot.Connector.Activity activity)
+ {
+ ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
+
+ // Question has been answered
+ // store answer in db.
+
+ // get question details
+ int questionId = Convert.ToInt32((activity.Value as dynamic)["questionId"]);
+ string answer = (activity.Value as dynamic)["answer"];
+ int answerId = Convert.ToInt32((activity.Value as dynamic)["qnaId"]);
+ var question = SQLService.GetQuestion(questionId);
+
+ // get user details
+ var channelData = activity.GetChannelData();
+ var members = await connector.Conversations.GetConversationMembersAsync(channelData.Team.Id);
+
+ var teamsMembers = members.AsTeamsChannelAccounts();
+ var currentUser = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault();
+ var studentUPN = currentUser.UserPrincipalName;
+ var isUserAdmin = SQLService.IsUserAdmin(studentUPN);
+
+ // store question in qna
+ string teamId = channelData.Team.Id;
+ TeamDetails teamDetails;
+ try
+ {
+ teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId);
+ }
+ catch (Exception e)
+ {
+ teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId);
+ Trace.TraceError(e.ToString());
+ }
+
+ var teamName = teamDetails.Name;
+ var courseID = SQLService.GetCourseIDByName(teamName.Trim());
+
+ // check if user can set question status
+ if (isUserAdmin || (studentUPN == question.OriginalPoster.Email) || (studentUPN == question.OriginalPoster.UserName)) // double check question to course? not sure
+ {
+ var answeredBy = SQLService.GetBotUser(courseID);
+
+ // update question model
+ question.QuestionStatus = Constants.QUESTION_STATUS_ANSWERED;
+ question.QuestionAnswered = DateTime.Now;
+ question.AnswerText = answer;
+ question.AnswerPoster = answeredBy;
+
+ SQLService.CreateOrUpdateQuestion(question);
+
+ // update old activity
+ Microsoft.Bot.Connector.Activity updatedReply = activity.CreateReply();
+
+ var card = new AdaptiveCard();
+ var answerBlock = new AdaptiveTextBlock("Answer: " + question.AnswerText.ReplaceLinksWithMarkdown());
+ answerBlock.Weight = AdaptiveTextWeight.Bolder;
+ answerBlock.Size = AdaptiveTextSize.Medium;
+ answerBlock.Wrap = true;
+
+ var markedBlock = new AdaptiveTextBlock($"Marked as " + question.QuestionStatus + " by " + currentUser.Name);
+ markedBlock.Wrap = true;
+
+ var answeredBlock = new AdaptiveTextBlock("Answered by: " + question.AnswerPoster.FullName);
+ answeredBlock.Weight = AdaptiveTextWeight.Bolder;
+ answeredBlock.Wrap = true;
+
+ card.Body.Add(answerBlock);
+ card.Body.Add(answeredBlock);
+ card.Body.Add(markedBlock);
+
+ Attachment attachment = new Attachment()
+ {
+ ContentType = AdaptiveCard.ContentType,
+ Content = card,
+ };
+
+ updatedReply.Attachments.Add(attachment);
+
+ await connector.Conversations.UpdateActivityAsync(activity.Conversation.Id, activity.ReplyToId, updatedReply);
+ var predictiveQnAService = new PredictiveQnAService(courseID);
+ var res = await predictiveQnAService.UpdateQnAPair(new List { question.QuestionText }, null, answer, answerId);
+ }
+ }
+
+ private async Task HandleBotNotHelpful(Microsoft.Bot.Connector.Activity activity)
+ {
+ ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
+
+ // tag demonstrators, regular workflow
+
+ // get question details
+ int questionId = Convert.ToInt32((activity.Value as dynamic)["QuestionId"]);
+ var question = SQLService.GetQuestion(questionId);
+
+ // get user details
+ var channelData = activity.GetChannelData();
+ var members = await connector.Conversations.GetConversationMembersAsync(channelData.Team.Id);
+
+ var teamsMembers = members.AsTeamsChannelAccounts();
+ var currentUser = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault();
+ var studentUPN = currentUser.UserPrincipalName;
+ var isUserAdmin = SQLService.IsUserAdmin(studentUPN);
+ string teamId = (activity.ChannelData as dynamic)["team"]["id"].ToString();
+ TeamDetails teamDetails;
+ try
+ {
+ teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId);
+ }
+ catch (Exception e)
+ {
+ teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId);
+ Trace.TraceError(e.ToString());
+ }
+
+ var teamName = teamDetails.Name;
+ var courseID = SQLService.GetCourseIDByName(teamName.Trim());
+
+ // check if user can set question status
+ if (isUserAdmin || (studentUPN == question.OriginalPoster.Email) || (studentUPN == question.OriginalPoster.UserName))
+ {
+ // find replies
+ string channelId = (activity.ChannelData as dynamic)["channel"]["id"].ToString();
+ var conversationId = activity.Conversation.Id;
+ string messageId = conversationId.Split('=')[1];
+
+ string originalStudentUpn = (activity.Value as dynamic)["UserUpn"];
+ var student = SQLService.GetUser(originalStudentUpn);
+
+ var adminsOnTeams = new List();
+ if (student != null)
+ {
+ if (student.Role != null && student.Role.Name != Constants.STUDENT_ROLE)
+ {
+ // Not a student - notify lecturer
+ var lecturers = SQLService.GetUsersByRole(Constants.LECTURER_ROLE, courseID);
+
+ foreach (var admin in lecturers)
+ {
+ var adminOnTeams = teamsMembers.Where(x =>
+ (x.Email == admin.Email || x.Email == admin.UserName || x.UserPrincipalName == admin.UserName || x.UserPrincipalName == admin.Email) &&
+ (x.Email != student.Email && x.Email != student.UserName && x.UserPrincipalName != student.UserName && x.UserPrincipalName != student.Email)
+ ).FirstOrDefault();
+ if (adminOnTeams != null)
+ {
+ adminsOnTeams.Add(adminOnTeams);
+ }
+ }
+ }
+ else
+ {
+ // Is a student
+ if (student.TutorialGroups != null && student.TutorialGroups.Count > 0)
+ {
+ // Notify demonstrator
+ var tutorialAdmins = new List();
+ foreach (var tutorialGroup in student.TutorialGroups)
+ {
+ tutorialAdmins.AddRange(SQLService.GetDemonstrators(courseID));
+ }
+
+
+ if (tutorialAdmins != null)
+ {
+ foreach (var admin in tutorialAdmins)
+ {
+ var adminOnTeams = teamsMembers.Where(x =>
+ (x.Email == admin.Email || x.Email == admin.UserName || x.UserPrincipalName == admin.UserName || x.UserPrincipalName == admin.Email) &&
+ (x.Email != student.Email && x.Email != student.UserName && x.UserPrincipalName != student.UserName && x.UserPrincipalName != student.Email)
+ ).FirstOrDefault();
+ if (adminOnTeams != null)
+ {
+ adminsOnTeams.Add(adminOnTeams);
+ }
+ }
+ }
+ }
+ else
+ {
+ // student without tutorial class?
+ var allAdmins = SQLService.GetAllAdmins(student.CourseId).Distinct();
+
+ if (allAdmins != null)
+ {
+ foreach (var admin in allAdmins)
+ {
+ var adminOnTeams = teamsMembers.Where(x =>
+ (x.Email == admin.Email || x.Email == admin.UserName || x.UserPrincipalName == admin.UserName || x.UserPrincipalName == admin.Email) &&
+ (x.Email != student.Email && x.Email != student.UserName && x.UserPrincipalName != student.UserName && x.UserPrincipalName != student.Email)
+ ).FirstOrDefault();
+ if (adminOnTeams != null)
+ {
+ adminsOnTeams.Add(adminOnTeams);
+ }
+ }
+ }
+ }
+
+ }
+ }
+ else
+ {
+ // User not in database
+ // Notify lecturer
+ var lecturers = SQLService.GetUsersByRole(Constants.LECTURER_ROLE, courseID);
+
+ foreach (var admin in lecturers)
+ {
+ var adminOnTeams = teamsMembers.Where(x =>
+ (x.Email == admin.Email || x.Email == admin.UserName || x.UserPrincipalName == admin.UserName || x.UserPrincipalName == admin.Email) &&
+ (x.Email != student.Email && x.Email != student.UserName && x.UserPrincipalName != student.UserName && x.UserPrincipalName != student.Email)
+ ).FirstOrDefault();
+ if (adminOnTeams != null)
+ {
+ adminsOnTeams.Add(adminOnTeams);
+ }
+ }
+ }
+
+ // update old activity
+ Microsoft.Bot.Connector.Activity updatedReply = activity.CreateReply();
+
+
+ var actionJson = "{\"Type\":\"" + Constants.ACTIVITY_SELECT_ANSWER + "\",\"QuestionId\": \"" + questionId + "\"}";
+
+ var card = new HeroCard()
+ {
+ Text = "Sorry I couldn't answer your question, I've tagged your demonstrators.",
+ };
+
+ updatedReply.Attachments.Add(card.ToAttachment());
+
+ try
+ {
+ await connector.Conversations.UpdateActivityAsync(activity.Conversation.Id, activity.ReplyToId, updatedReply);
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ }
+
+ // create new tagging reply
+ Microsoft.Bot.Connector.Activity newReply = activity.CreateReply();
+
+ // Tag Admins
+ foreach (var admin in adminsOnTeams)
+ {
+ newReply.AddMentionToText(admin, MentionTextLocation.AppendText);
+ }
+
+ var newActionJson = "{\"type\":\"" + Constants.ACTIVITY_SELECT_ANSWER + "\",\"questionId\": \"" + questionId + "\"}";
+
+ var newCard = new HeroCard()
+ {
+ Buttons = new List()
+ {
+ new CardAction(ActivityTypes.Invoke, "Select an answer", value: newActionJson),
+ },
+ };
+
+ newReply.Attachments.Add(newCard.ToAttachment());
+
+ try
+ {
+ var response = await connector.Conversations.ReplyToActivityAsync(activity.Conversation.Id, activity.ReplyToId, newReply);
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ }
+ }
+ }
+
+ private async Task HandleSelectAnswerFromCard(Microsoft.Bot.Connector.Activity activity)
+ {
+ ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
+
+ // get question details
+ int questionId = Convert.ToInt32((activity.Value as dynamic)["questionId"]);
+ var question = SQLService.GetQuestion(questionId);
+
+ // get user details
+ var channelData = activity.GetChannelData();
+ var members = await connector.Conversations.GetConversationMembersAsync(channelData.Team.Id);
+
+ var teamsMembers = members.AsTeamsChannelAccounts();
+ var currentUser = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault();
+ var studentUPN = currentUser.UserPrincipalName;
+
+ // var isUserAdmin = SharePointServices.IsUserAdmin(studentUPN);
+ var isUserAdmin = SQLService.IsUserAdmin(studentUPN);
+
+ // check if user can set question status
+ if (isUserAdmin || (studentUPN == question.OriginalPoster.Email) || (studentUPN == question.OriginalPoster.UserName))
+ {
+ // find replies
+ string teamId = (activity.ChannelData as dynamic)["team"]["id"].ToString();
+ string channelId = (activity.ChannelData as dynamic)["channel"]["id"].ToString();
+ var conversationId = activity.Conversation.Id;
+ string messageId = conversationId.Split('=')[1];
+
+ // update old activity
+ Microsoft.Bot.Connector.Activity updatedReply = activity.CreateReply();
+
+ var replies = await GetAllReplies(question.GroupId, channelId, messageId);
+ var adaptiveCardChoices = new List();
+ if (replies != null && replies.Count > 0)
+ {
+ foreach (var reply in replies)
+ {
+ adaptiveCardChoices.Add(new AdaptiveChoice()
+ {
+ Title = MicrosoftTeamsChannelHelper.StripMentionAndHtml(reply.Body.Content),
+ Value = JsonConvert.SerializeObject(reply),
+ });
+ }
+
+ var bodyTextBlock = new AdaptiveTextBlock() { Text = "Select an answer" };
+ var bodyChoice = new AdaptiveChoiceSetInput()
+ {
+ Id = "Answer",
+ Style = AdaptiveChoiceInputStyle.Compact,
+ IsMultiSelect = false,
+ Choices = adaptiveCardChoices,
+ };
+
+ var adaptiveCardAnswerSubmit = new AdaptiveCardAnswerSubmit(Constants.ACTIVITY_MARKED_ANSWERED, bodyChoice.Value, questionId.ToString());
+ var adaptiveCardAnswerString = JsonConvert.SerializeObject(adaptiveCardAnswerSubmit);
+ var actionJson = "{\"type\":\"" + Constants.ACTIVITY_SELECT_ANSWER + "\",\"questionId\": \"" + questionId.ToString() + "\"}";
+
+ var adaptiveCard = new AdaptiveCard()
+ {
+ Actions = new List()
+ {
+ new AdaptiveSubmitAction()
+ {
+ Title = "Save",
+ DataJson = adaptiveCardAnswerString,
+ },
+ new AdaptiveSubmitAction()
+ {
+ Title = "Refresh",
+ DataJson = actionJson,
+ },
+ },
+ };
+
+ adaptiveCard.Body.Add(bodyTextBlock);
+ adaptiveCard.Body.Add(bodyChoice);
+
+ var attachment = new Attachment()
+ {
+ ContentType = AdaptiveCard.ContentType,
+ Content = adaptiveCard,
+ };
+
+ updatedReply.Attachments.Add(attachment);
+
+ try
+ {
+ // await connector.Conversations.UpdateActivityAsync(updatedReply);
+ updatedReply.Id = activity.ReplyToId;
+ var response = await connector.Conversations.UpdateActivityAsync(activity.Conversation.Id, activity.ReplyToId, updatedReply);
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ }
+ }
+ }
+ }
+
+ private async Task HandleMarkedAnswerFromCard(Microsoft.Bot.Connector.Activity activity)
+ {
+ ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
+
+ // Handle answer payload
+ var adaptiveCardAnswerJson = activity.Value.ToString();
+ var adaptiveCardAnswer = JsonConvert.DeserializeObject(adaptiveCardAnswerJson);
+
+ string selectedReplyJson = adaptiveCardAnswer.Answer;
+ string questionId = adaptiveCardAnswer.QuestionId;
+
+ if (string.IsNullOrEmpty(selectedReplyJson))
+ {
+ Microsoft.Bot.Connector.Activity newReply = activity.CreateReply();
+ newReply.Text = "There seems to be an issue saving the answer.";
+ await connector.Conversations.ReplyToActivityAsync(activity.Conversation.Id, activity.ReplyToId, newReply);
+ }
+ else
+ {
+ var selectedReply = JsonConvert.DeserializeObject(selectedReplyJson);
+ var question = SQLService.GetQuestion(Convert.ToInt32(questionId));
+
+ // get user details
+ var channelData = activity.GetChannelData();
+ var members = await connector.Conversations.GetConversationMembersAsync(channelData.Team.Id);
+
+ var teamsMembers = members.AsTeamsChannelAccounts();
+ var currentUser = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault();
+ var studentUPN = currentUser.UserPrincipalName;
+ var isUserAdmin = SQLService.IsUserAdmin(studentUPN);
+ string teamId = channelData.Team.Id;
+ TeamDetails teamDetails;
+ try
+ {
+ teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId);
+ }
+ catch (Exception e)
+ {
+ teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId);
+ Trace.TraceError(e.ToString());
+ }
+ var teamName = teamDetails.Name;
+ var courseID = SQLService.GetCourseIDByName(teamName.Trim());
+
+ // check if user can set question status
+ if (isUserAdmin || (studentUPN == question.OriginalPoster.Email) || (studentUPN == question.OriginalPoster.UserName))
+ {
+ var selectedReplyUser = teamsMembers.Where(x => x.ObjectId == selectedReply.From.User.Id).FirstOrDefault();
+ var answeredBy = SQLService.GetUser(selectedReplyUser.UserPrincipalName);
+
+ // update question model
+ question.QuestionStatus = Constants.QUESTION_STATUS_ANSWERED;
+ question.QuestionAnswered = DateTime.Now;
+ question.AnswerText = MicrosoftTeamsChannelHelper.StripMentionAndHtml(selectedReply.Body.Content);
+ question.AnswerPoster = answeredBy;
+
+ SQLService.CreateOrUpdateQuestion(question);
+
+ // update old activity
+ Microsoft.Bot.Connector.Activity updatedReply = activity.CreateReply();
+
+ var card = new AdaptiveCard();
+ var answer = new AdaptiveTextBlock("Answer: " + question.AnswerText.ReplaceLinksWithMarkdown());
+ answer.Weight = AdaptiveTextWeight.Bolder;
+ answer.Size = AdaptiveTextSize.Medium;
+ answer.Wrap = true;
+
+ var marked = new AdaptiveTextBlock($"Marked as " + question.QuestionStatus + " by " + currentUser.Name);
+ marked.Wrap = true;
+
+ var answered = new AdaptiveTextBlock("Answered by: " + question.AnswerPoster.FullName);
+ answered.Weight = AdaptiveTextWeight.Bolder;
+ answered.Wrap = true;
+
+ card.Body.Add(answer);
+ card.Body.Add(answered);
+ card.Body.Add(marked);
+
+ Attachment attachment = new Attachment()
+ {
+ ContentType = AdaptiveCard.ContentType,
+ Content = card,
+ };
+
+ updatedReply.Attachments.Add(attachment);
+
+ await connector.Conversations.UpdateActivityAsync(activity.Conversation.Id, activity.ReplyToId, updatedReply);
+ var predictiveQnAService = new PredictiveQnAService(courseID);
+ var res = await predictiveQnAService.AddQnAPair(question.QuestionText, question.AnswerText);
+ }
+ }
+ }
+
+ private async Task HandleSelectAnswerFromMessageAction(Microsoft.Bot.Connector.Activity activity)
+ {
+ ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
+
+ TeamsMessage selectedReply = JsonConvert.DeserializeObject(JsonConvert.SerializeObject((activity.Value as dynamic)["messagePayload"]));
+
+ if (selectedReply.From.User == null)
+ {
+ return Request.CreateResponse(HttpStatusCode.OK);
+ }
+
+ var question = SQLService.GetQuestionByMessageId(selectedReply.ReplyToId);
+
+ if (question == null)
+ {
+ return Request.CreateResponse(HttpStatusCode.OK);
+ }
+
+ // get user details
+ var channelData = activity.GetChannelData();
+ var members = await connector.Conversations.GetConversationMembersAsync(channelData.Team.Id);
+ var teamsMembers = members.AsTeamsChannelAccounts();
+ var currentUser = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault();
+ var studentUPN = currentUser.UserPrincipalName;
+ var isUserAdmin = SQLService.IsUserAdmin(studentUPN);
+
+ // check if user can set question status
+ if (isUserAdmin || (studentUPN == question.OriginalPoster.Email) || (studentUPN == question.OriginalPoster.UserName))
+ {
+ var selectedReplyUser = teamsMembers.Where(x => x.ObjectId == selectedReply.From.User.Id).FirstOrDefault();
+ var answeredBy = SQLService.GetUser(selectedReplyUser.UserPrincipalName);
+
+ // update question model
+ question.QuestionStatus = Constants.QUESTION_STATUS_ANSWERED;
+ question.QuestionAnswered = DateTime.Now;
+ question.AnswerText = MicrosoftTeamsChannelHelper.StripMentionAndHtml(selectedReply.Body.Content);
+ question.AnswerPoster = answeredBy;
+
+ SQLService.CreateOrUpdateQuestion(question);
+
+ Microsoft.Bot.Connector.Activity updatedReply = activity.CreateReply();
+
+ var card = new AdaptiveCard();
+ var answerBlock = new AdaptiveTextBlock("Answer: " + question.AnswerText.ReplaceLinksWithMarkdown());
+ answerBlock.Weight = AdaptiveTextWeight.Bolder;
+ answerBlock.Size = AdaptiveTextSize.Medium;
+ answerBlock.Wrap = true;
+
+ var markedBlock = new AdaptiveTextBlock($"Marked as " + question.QuestionStatus + " by " + currentUser.Name);
+ markedBlock.Wrap = true;
+
+ var answeredBlock = new AdaptiveTextBlock("Answered by: " + question.AnswerPoster.FullName);
+ answeredBlock.Weight = AdaptiveTextWeight.Bolder;
+ answeredBlock.Wrap = true;
+
+ card.Body.Add(answerBlock);
+ card.Body.Add(answeredBlock);
+ card.Body.Add(markedBlock);
+
+ Attachment attachment = new Attachment()
+ {
+ ContentType = AdaptiveCard.ContentType,
+ Content = card,
+ };
+
+ updatedReply.Attachments.Add(attachment);
+
+ if (question.AnswerCardActivityId == null)
+ {
+ var r = await connector.Conversations.ReplyToActivityAsync(updatedReply.Conversation.Id, updatedReply.ReplyToId, updatedReply);
+
+ question.AnswerCardActivityId = r.Id;
+ SQLService.CreateOrUpdateQuestion(question);
+
+ }
+ else
+ {
+ updatedReply.ReplyToId = question.AnswerCardActivityId;
+ var r = await connector.Conversations.UpdateActivityAsync(updatedReply.Conversation.Id, updatedReply.ReplyToId, updatedReply);
+ question.AnswerCardActivityId = r.Id;
+ SQLService.CreateOrUpdateQuestion(question);
+
+ }
+ }
+
+ var baseUrl = ServiceHelper.BaseUrl;
+ var taskInfo = new Models.TaskInfo();
+
+ taskInfo.Title = "Select Answer";
+ taskInfo.Height = 300;
+ taskInfo.Width = 400;
+ taskInfo.Url = baseUrl + @"/home/selectanswer?json=" + "Answer Updated";
+
+ Models.TaskEnvelope taskEnvelope = new Models.TaskEnvelope
+ {
+ Task = new Models.Task()
+ {
+ Type = Models.TaskType.Continue,
+ TaskInfo = taskInfo,
+ },
+ };
+ return Request.CreateResponse(HttpStatusCode.OK, taskEnvelope);
+ }
+
+ private async Task HandleSystemMessage(Microsoft.Bot.Connector.Activity message)
+ {
+ if (message.Type == ActivityTypes.DeleteUserData)
+ {
+ // Implement user deletion here
+ // If we handle user deletion, return a real message
+ }
+ else if (message.Type == ActivityTypes.ConversationUpdate)
+ {
+ // Handle conversation state changes, like members being added and removed
+ // Use Activity.MembersAdded and Activity.MembersRemoved and Activity.Action for info
+ // Not available in all channels
+ if (message.ChannelId == "msteams")
+ {
+ var addedBot = false;
+ for (int i = 0; i < message.MembersAdded.Count; i++)
+ {
+ if (message.MembersAdded[i].Id == message.Recipient.Id)
+ {
+ addedBot = true;
+ break;
+ }
+ }
+
+ if (addedBot)
+ {
+ var reply = message.CreateReply("Hi, I'm here to learn and help answer your questions! Just add '@Question' to your queries :)");
+ ConnectorClient connector = new ConnectorClient(new Uri(message.ServiceUrl));
+ await connector.Conversations.ReplyToActivityAsync(reply);
+ }
+ }
+
+ }
+ else if (message.Type == ActivityTypes.ContactRelationUpdate)
+ {
+ // Handle add/remove from contact lists
+ // Activity.From + Activity.Action represent what happened
+ }
+ else if (message.Type == ActivityTypes.Typing)
+ {
+ // Handle knowing tha the user is typing
+ }
+
+ return null;
+ }
+
+ private async Task> GetAllReplies(string teamsId, string channelId, string messageId)
+ {
+ var authority = ServiceHelper.Authority;
+ var resource = ServiceHelper.GraphResource;
+
+ var authService = new AuthService(authority);
+ var authResult = await authService.AuthenticateSilently(resource);
+
+ var graphService = new GraphService();
+ var teamsMessages = await graphService.GetRepliesToMessage(authResult.AccessToken, teamsId, channelId, messageId);
+
+ return teamsMessages.Where(x => x.From.Application == null && !string.IsNullOrEmpty(MicrosoftTeamsChannelHelper.StripMentionAndHtml(x.Body.Content))).ToList();
+ }
+
+ private string GetActivityTypeFrom(Microsoft.Bot.Connector.Activity activity)
+ {
+ if (activity.Type == ActivityTypes.Invoke)
+ {
+ return ActivityTypes.Invoke;
+ }
+ else if (activity.Type == ActivityTypes.Message)
+ {
+ var invokeType = string.Empty;
+ try
+ {
+ // need to determine if its an invoke disguised as a message
+ invokeType = (activity.Value as dynamic)["type"];
+ }
+ catch (Exception ex)
+ {
+ invokeType = string.Empty;
+ }
+
+ if (!string.IsNullOrEmpty(invokeType))
+ {
+ if (invokeType == Constants.ACTIVITY_SELECT_ANSWER
+ || invokeType == Constants.ACTIVITY_BOT_HELPFUL
+ || invokeType == Constants.ACTIVITY_BOT_NOT_HELPFUL
+ || invokeType == Constants.ACTIVITY_MARKED_ANSWERED)
+ {
+ return ActivityTypes.Invoke;
+ }
+ else
+ {
+ return ActivityTypes.Message;
+ }
+ }
+ else
+ {
+ return ActivityTypes.Message;
+ }
+ }
+
+ return activity.Type;
+ }
+ }
+
+ [Serializable]
+ public class AdaptiveCardAnswerSubmit
+ {
+ [JsonProperty("type")]
+ public string Type { get; set; }
+
+ [JsonProperty("answer")]
+ public string Answer { get; set; }
+
+ [JsonProperty("questionId")]
+ public string QuestionId { get; set; }
+
+ public AdaptiveCardAnswerSubmit(string type, string answer, string questionId)
+ {
+ Type = type;
+ Answer = answer;
+ QuestionId = questionId;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Controllers/RequestController.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Controllers/RequestController.cs
new file mode 100644
index 0000000..843b2a1
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Controllers/RequestController.cs
@@ -0,0 +1,588 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Claims;
+using System.Threading.Tasks;
+using System.Web;
+using System.Web.Http;
+using System.Web.Http.Cors;
+
+using Microsoft.Teams.Apps.QBot.Bot.Services;
+using Microsoft.Teams.Apps.QBot.Data;
+using Microsoft.Teams.Apps.QBot.Model;
+using Microsoft.Teams.Apps.QBot.Model.Graph;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Controllers
+{
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [RoutePrefix("api/Request")]
+ public class RequestController : ApiController
+ {
+ [HttpPost]
+ [Route("InitializeBotService")]
+ public async Task InitializeBotService()
+ {
+ if (SQLService.NoUsers())
+ {
+ // Bootstraps the initial admin user for QBot system
+ string upn = null;
+ string firstName = null;
+ string lastName = null;
+ string email = null;
+
+ var claimsIdentity = HttpContext.Current.User.Identity as ClaimsIdentity;
+ if (claimsIdentity != null)
+ {
+ upn = claimsIdentity.Claims.Where(c => c.Type == "name").Select(c => c.Value).FirstOrDefault();
+ firstName = claimsIdentity.Claims.Where(c => c.Type == ClaimTypes.GivenName).Select(c => c.Value).FirstOrDefault();
+ lastName = claimsIdentity.Claims.Where(c => c.Type == ClaimTypes.Surname).Select(c => c.Value).FirstOrDefault();
+ email = claimsIdentity.Claims.Where(c => c.Type == ClaimTypes.Email).Select(c => c.Value).FirstOrDefault();
+ }
+
+ if (string.IsNullOrEmpty(upn))
+ {
+ throw new Exception("Error bootstrapping initial Bot admin account - Could not get current user claim");
+ }
+
+ // First user in the system, they are made as global admin
+ SQLService.AddGlobalAdminUser(upn, firstName, lastName, email);
+ }
+
+ return Ok();
+ }
+
+ [HttpGet]
+ [Route("GetUserAccess")]
+ public async Task GetUserAccess(string upn)
+ {
+ return SQLService.GetUserAccess(upn);
+ }
+
+ ///
+ /// Gets all Questions for all Courses within the given tenant
+ ///
+ /// Tenant ID
+ /// List of Questions
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("GetAllQuestions")]
+ public List GetAllQuestions([FromBody]string tenantId)
+ {
+ var questions = SQLService.GetAllQuestions(tenantId);
+
+ return questions;
+ }
+
+ ///
+ /// Gets all Questions for the given Group
+ ///
+ /// Office 365 Group ID
+ /// List of Questions
+ [HttpPost]
+ [Route("GetQuestionsByGroup")]
+ public List GetQuestionsByGroup([FromBody]string groupId)
+ {
+ var questions = SQLService.GetQuestionsByGroup(groupId);
+
+ return questions;
+ }
+
+ ///
+ /// Gets all Questions for the given Tutorial Group
+ ///
+ /// Contains Tenant ID and Tutorial Group Code
+ /// List of Questions
+ [HttpPost]
+ [Route("GetQuestionsByTutorial")]
+ public List GetQuestionsByTutorial([FromBody]dynamic obj)
+ {
+ var tenantId = obj["tenantId"].ToObject();
+ var code = obj["code"].ToObject();
+ var questions = SQLService.GetAllQuestionsByTutorial(tenantId, code);
+
+ return questions;
+ }
+
+ ///
+ /// Get a User by their User Principal Name
+ ///
+ /// User Principal Name
+ /// User record
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("GetUserByUpn")]
+ public UserCourseRoleMappingModel GetUserByUpn([FromBody]string upn)
+ {
+ var user = SQLService.GetUser(upn);
+
+ return user;
+ }
+
+ ///
+ /// Gets list of Students for a given Tutorial Group
+ ///
+ /// The Tutorial Group Code
+ /// User record
+ [HttpPost]
+ [Route("GetStudentsByTutorial")]
+ public List GetStudentsByTutorial([FromBody]string tutorialCode)
+ {
+ var users = SQLService.GetStudents(tutorialCode);
+
+ return users;
+ }
+
+ ///
+ /// Gets a list of all O365 Group Ids for which the given user is a member of, which also contains questions
+ ///
+ /// Parameter contains the Tenant ID and UPN
+ /// List of Team Group IDs where a question is asked
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("GetTeamGroupIdsWithQuestions")]
+ public async Task> GetTeamGroupIdsWithQuestions([FromBody]dynamic obj)
+ {
+ try
+ {
+ var tenantId = obj["tenantId"].ToObject();
+ var upn = obj["upn"].ToObject();
+
+ var authService = new AuthService(ServiceHelper.Authority);
+ var authResult = await authService.AuthenticateSilently(ServiceHelper.GraphResource);
+ if (authResult != null)
+ {
+ var graphService = new GraphService();
+ var memberOf = await graphService.GetGroupMemberOf(authResult.AccessToken, upn);
+ var groupIds = SQLService.GetTeamGroupIdsWithQuestions(tenantId, memberOf);
+
+ return groupIds;
+ }
+
+ return null;
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Gets details such as name, description, photo, etc about a specific Team
+ ///
+ /// The O365 Group ID
+ /// List of Groups
+ [HttpPost]
+ [Route("GetTeamGroupDetail")]
+ public async Task GetTeamGroupDetail([FromBody]string groupId)
+ {
+ var teamGroupDetail = new TeamGroupDetail();
+
+ var authService = new AuthService(ServiceHelper.Authority);
+ var authResult = await authService.AuthenticateSilently(ServiceHelper.GraphResource);
+ if (authResult != null)
+ {
+ var graphService = new GraphService();
+ var teamGroup = await graphService.GetTeamGroupSPUrl(authResult.AccessToken, groupId);
+
+ var imageBytes = await graphService.GetGroupPhoto(authResult.AccessToken, groupId);
+ var picUrl = Convert.ToBase64String(imageBytes);
+
+ teamGroupDetail.Id = groupId;
+ teamGroupDetail.Name = teamGroup.Name;
+ teamGroupDetail.DisplayName = teamGroup.DisplayName;
+ teamGroupDetail.Description = teamGroup.Description;
+ teamGroupDetail.WebUrl = teamGroup.WebUrl;
+ teamGroupDetail.PhotoByteUrl = picUrl;
+
+ return teamGroupDetail;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Gets the list of Channels for the given Team
+ ///
+ /// Office 365 Group ID
+ /// A list of channels within the Team
+ [HttpPost]
+ [Route("GetTeamChannels")]
+ public async Task> GetTeamChannels([FromBody]string groupId)
+ {
+ var teamGroupDetail = new TeamGroupDetail();
+
+ var authService = new AuthService(ServiceHelper.Authority);
+ var authResult = await authService.AuthenticateSilently(ServiceHelper.GraphResource);
+ if (authResult != null)
+ {
+ var graphService = new GraphService();
+ var teamChannels = await graphService.GetChannels(authResult.AccessToken, groupId);
+ return teamChannels;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Gets the Team photo
+ ///
+ /// Office 365 Group ID
+ /// Base64 encoded representation of the Team photo
+ [HttpPost]
+ [Route("GetTeamGroupPhoto")]
+ public async Task GetTeamGroupPhoto([FromBody]string groupId)
+ {
+ var authService = new AuthService(ServiceHelper.Authority);
+ var authResult = await authService.AuthenticateSilently(ServiceHelper.GraphResource);
+ if (authResult != null)
+ {
+ var graphService = new GraphService();
+ var imageBytes = await graphService.GetGroupPhoto(authResult.AccessToken, groupId);
+
+ var picUrl = @"data:image/png;base64," + Convert.ToBase64String(imageBytes);
+
+ return picUrl;
+ }
+
+ return null;
+ }
+
+ ///
+ /// Gets all Courses
+ ///
+ /// List of all Courses
+ [HttpGet]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("GetCourses")]
+ public List GetCourses()
+ {
+ try
+ {
+ var courses = SQLService.GetCourses();
+ return ModelMapper.MapToCourseModels(courses);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// Adds or updates a Course record
+ ///
+ /// Course model to be saved
+ /// The full list of courses after the opearation completes
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("SaveCourse")]
+ public async Task> SaveCourse(Course course)
+ {
+ try
+ {
+ var courses = SQLService.SaveCourse(course);
+ if (courses != null)
+ {
+ var authService = new AuthService(ServiceHelper.Authority);
+ var authResult = await authService.AuthenticateSilently(ServiceHelper.GraphResource);
+ if (authResult != null)
+ {
+ var graphService = new GraphService();
+ var graphUsers = await graphService.GetMembers(authResult.AccessToken, course.GroupId.ToString());
+ if (graphUsers != null)
+ {
+ var courseId = SQLService.GetCourseIDByName(course.Name);
+ List users = new List();
+ foreach (GraphUser graphUser in graphUsers.Items)
+ {
+ users.Add(new User()
+ {
+ Id = 0,
+ StudentId = graphUser.id,
+ FirstName = graphUser.givenName,
+ LastName = graphUser.surname,
+ UserPrincipalName = graphUser.userPrincipalName,
+ Email = graphUser.mail,
+ });
+ }
+
+ var result = SQLService.AddStudents(users, course.Name);
+ }
+ }
+ }
+
+ return ModelMapper.MapToCourseModels(courses);
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Synchronises Users based on Teams membership for a course
+ ///
+ /// The course record
+ /// List of Users after the operation completes
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("RefreshUsers")]
+ public async Task> RefreshUsers(Course course)
+ {
+ try
+ {
+ var result = new List();
+ var authService = new AuthService(ServiceHelper.Authority);
+ var authResult = await authService.AuthenticateSilently(ServiceHelper.GraphResource);
+ if (authResult != null)
+ {
+ var graphService = new GraphService();
+ var graphUsers = await graphService.GetMembers(authResult.AccessToken, course.GroupId.ToString());
+ if (graphUsers != null)
+ {
+ var courseId = course.Id;
+ List users = new List();
+ foreach (GraphUser graphUser in graphUsers.Items)
+ {
+ users.Add(new User()
+ {
+ Id = 0,
+ StudentId = graphUser.id,
+ FirstName = graphUser.givenName,
+ LastName = graphUser.surname,
+ UserPrincipalName = graphUser.userPrincipalName,
+ Email = graphUser.mail,
+ });
+ }
+
+ result = ModelMapper.MapToUsersModel(SQLService.AddStudents(users, course.Name));
+ }
+
+ }
+
+ return result;
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Deletes a Course
+ ///
+ /// Course ID
+ /// List of Courses after the operation completes
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("DeleteCourse")]
+ public List DeleteCourse([FromBody]int id)
+ {
+ return ModelMapper.MapToCourseModels(SQLService.DeleteCourse(id));
+ }
+
+ ///
+ /// Adds a list of Student to a Course. User records will be updated if they exist, otherwise they are added for the given Course
+ ///
+ /// List of students to update
+ /// The course that the students belong to
+ /// List of Students after the operation completes
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("AddStudents")]
+ public List AddStudents(List students, string coursename)
+ {
+ try
+ {
+ List mappedStudents = ModelMapper.MapFromUserModels(students);
+ var user = SQLService.AddStudents(mappedStudents, coursename);
+ List studentsToReturn = ModelMapper.MapToUsersModel(user);
+ return studentsToReturn;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// Gets all Teams that a given user currently owns
+ ///
+ /// Parameter contains the Tenant ID and the UPN
+ /// List of Teams that the user owns
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("GetOwnedTeams")]
+ public async Task GetOwnedTeams([FromBody]dynamic obj)
+ {
+ try
+ {
+ var tenantId = obj["tenantId"].ToObject();
+ var upn = obj["upn"].ToObject();
+ var authService = new AuthService(ServiceHelper.Authority);
+ var authResult = await authService.AuthenticateSilently(ServiceHelper.GraphResource);
+ if (authResult != null)
+ {
+ var graphService = new GraphService();
+ var ownerOf = await graphService.GetOwnedObjects(authResult.AccessToken, upn);
+ return ownerOf;
+ }
+ return null;
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Get Users for a Course
+ ///
+ /// Course ID
+ /// List of Users
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("GetUserCourseRoleMappingsByCourse")]
+ public async Task> GetUserCourseRoleMappingsByCourse([FromBody]int courseid)
+ {
+ try
+ {
+ return SQLService.GetUserCourseRoleMappingsByCourse(courseid);
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Deletes a User for a Course
+ ///
+ /// User Role mapping that contains the User record & course they belong to
+ /// A list of Users for the course, after this operation completes
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("DeleteUserCourseRoleMapping")]
+ public async Task> DeleteUserCourseRoleMapping([FromBody]UserCourseRoleMapping ucrm)
+ {
+ try
+ {
+ return SQLService.DeleteUserCourseRoleMapping(ucrm);
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Saves a User for a Course
+ ///
+ /// User Role mapping that contains the User record & course they belong to
+ /// A list of Users for the course, after this operation completes
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("SaveUserCourseRoleMapping")]
+ public async Task> SaveUserCourseRoleMapping([FromBody]UserCourseRoleMappingModel ucrm)
+ {
+ try
+ {
+ return SQLService.SaveUserCourseRoleMapping(ucrm);
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Gets all Roles within the system
+ ///
+ /// List of Roles
+ [HttpGet]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("GetRoles")]
+ public async Task> GetRoles()
+ {
+ try
+ {
+ return SQLService.GetRoles();
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Gets a list of Tutorial Groups within a Course
+ ///
+ /// The Course ID
+ /// The list of Tutorial Groups
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("GetTutorialsByCourse")]
+ public async Task> GetTutorialsByCourse([FromBody]int courseid)
+ {
+ try
+ {
+ return SQLService.GetTutorialsByCourse(courseid);
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Saves a Tutorial Group record
+ ///
+ /// The Tutorial Group to save
+ /// The list of Tutorial Groups after the operation
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("SaveTutorialGroup")]
+ public async Task> SaveTutorialGroup([FromBody]TutorialGroup tutorial)
+ {
+ try
+ {
+ return SQLService.SaveTutorialGroup(tutorial);
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ return null;
+ }
+ }
+
+ ///
+ /// Deletes a Tutorial Group
+ ///
+ /// The Tutorial Group to delete
+ /// The list of Tutorial Groups after the operation
+ [HttpPost]
+ [EnableCors(origins: "*", headers: "*", methods: "*")]
+ [Route("DeleteTutorialGroup")]
+ public async Task> DeleteTutorialGroup([FromBody]TutorialGroup tutorial)
+ {
+ try
+ {
+ return SQLService.DeleteTutorialGroup(tutorial);
+ }
+ catch (Exception e)
+ {
+ Trace.TraceError(e.ToString());
+ return null;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Dialogs/RootDialog.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Dialogs/RootDialog.cs
new file mode 100644
index 0000000..b22ce24
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Dialogs/RootDialog.cs
@@ -0,0 +1,468 @@
+using AdaptiveCards;
+using Antares.Bot.Channels;
+using Microsoft.Bot.Builder.Dialogs;
+using Microsoft.Bot.Connector;
+using Microsoft.Bot.Connector.Teams;
+using Microsoft.Bot.Connector.Teams.Models;
+using Microsoft.Teams.Apps.QBot.Bot.Services;
+using Microsoft.Teams.Apps.QBot.Bot.utility;
+using Microsoft.Teams.Apps.QBot.Model;
+using Microsoft.Teams.Apps.QBot.Model.Teams;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web;
+using Task = System.Threading.Tasks.Task;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Dialogs
+{
+ [Serializable]
+ public class RootDialog : IDialog
+ {
+ private ResourceService resourceService;
+
+ public RootDialog()
+ {
+ resourceService = new ResourceService();
+ }
+
+ public Task StartAsync(IDialogContext context)
+ {
+ context.Wait(MessageReceivedAsync);
+
+ return Task.CompletedTask;
+ }
+
+ private async Task MessageReceivedAsync(IDialogContext context, IAwaitable result)
+ {
+ // Init
+ var activity = await result as Microsoft.Bot.Connector.Activity;
+
+ // Handle tagged in a question
+ // Check if we already have this particular conversation saved. This is to counter the auto-tagging when replying to a bot in Teams
+ if (SQLService.DoesConversationIdExist(activity.Conversation.Id))
+ {
+ // Do nothing if we find it.
+ }
+ else
+ {
+ // Check if this is a group (channel) or a 1-on-1 conversation
+ if (activity.Conversation.IsGroup == true)
+ {
+ await HandleChannelConversation(context, activity);
+ }
+ else
+ {
+ await HandleOneOnOneConversation(activity);
+ }
+ }
+
+ }
+
+ private async Task HandleOneOnOneConversation(Microsoft.Bot.Connector.Activity activity)
+ {
+ var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
+
+ // One-on-one chat isn't support yet, encourage to post question in the channel instead
+ var defaultReply = activity.CreateReply("Please post your question in the channel instead -- and don't forget to tag me, so I know about it!");
+ await connector.Conversations.ReplyToActivityAsync(defaultReply);
+ }
+
+ private async Task HandleChannelConversation(IDialogContext context, Microsoft.Bot.Connector.Activity activity)
+ {
+ var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
+
+ // Channel conversation
+
+ // Get the question text, and team and channel details
+ var question = activity.Text;
+ var messageId = activity.Id;
+ var conversationId = activity.Conversation.Id;
+ var channelData = activity.GetChannelData();
+ string tenantId = channelData.Tenant.Id;
+ string teamId = channelData.Team.Id;
+ string channelId = channelData.Channel.Id;
+
+ TeamDetails teamDetails = connector.GetTeamsConnectorClient().Teams.FetchTeamDetails(teamId);
+ var teamName = teamDetails.Name;
+ var groupId = teamDetails.AadGroupId;
+
+ ConversationList channelList = connector.GetTeamsConnectorClient().Teams.FetchChannelList(teamId);
+ var channel = channelList.Conversations.Where(x => x.Id == channelId).FirstOrDefault();
+ var channelName = channel?.Name;
+ var topic = channelName ?? "General";
+
+ IList members = await connector.Conversations.GetConversationMembersAsync(teamId);
+ var teamsMembers = members.AsTeamsChannelAccounts();
+
+ // Get original poster
+ var originalPosterAsTeamsChannelAccount = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault();
+ var userUpn = originalPosterAsTeamsChannelAccount.UserPrincipalName;
+ var user = SQLService.GetUser(userUpn);
+
+ // strip @bot mention for teams
+ if (activity.ChannelId == "msteams")
+ {
+ activity = MicrosoftTeamsChannelHelper.StripAtMentionText(activity);
+ }
+ else
+ {
+ activity.Text = activity.Text.Trim();
+ }
+
+ // strip the html tags
+ question = MicrosoftTeamsChannelHelper.StripHtmlTags(activity.Text);
+
+ var questionModel = new QuestionModel()
+ {
+ ID = 0,
+ TenantId = tenantId,
+ GroupId = groupId,
+ TeamId = teamId,
+ TeamName = teamName,
+ ConversationId = conversationId,
+ MessageId = messageId,
+ Topic = topic,
+ QuestionText = question,
+ QuestionSubmitted = DateTime.Now,
+ OriginalPoster = user,
+ Link = CreateLink(conversationId, tenantId, groupId, messageId, teamName, topic),
+ };
+
+ if (string.IsNullOrEmpty(question))
+ {
+ await HandleNoQuestion(context, activity, questionModel, channelId);
+ }
+ else
+ {
+ // get courseID
+ var courseID = SQLService.GetCourseIDByName(teamName.Trim());
+ var course = SQLService.GetCourse(courseID);
+ questionModel.CourseID = courseID;
+ await HandleQuestionWorkflow(context, activity, course, questionModel);
+ }
+ }
+
+ private async Task HandleQuestionWorkflow(IDialogContext context, Microsoft.Bot.Connector.Activity activity, Data.Course course, QuestionModel questionModel)
+ {
+ var predictiveQnAService = new PredictiveQnAService(course.Id);
+ QnAAnswer response = await predictiveQnAService.GetAnswer(questionModel.QuestionText);
+
+ // if result, check confidence level
+ if (response != null && response.Score > Convert.ToDouble(course.PredictiveQnAConfidenceThreshold))
+ {
+ await HandleBotAnswerWorkflow(context, activity, questionModel, response, questionModel.TeamId);
+ }
+ else
+ {
+ // a score of 0 or a score below threshold both result in regular workflow
+ await HandleTagAdminWorkflow(activity, questionModel, questionModel.TeamId, course.Id);
+ }
+ }
+
+ private async Task HandleBotAnswerWorkflow(IDialogContext context, Microsoft.Bot.Connector.Activity activity, QuestionModel questionModel, QnAAnswer response, string teamId)
+ {
+ var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
+ // above threshold
+ // post answer card with helpful/not-helpful
+
+ // Set question state
+ questionModel.QuestionStatus = Constants.QUESTION_STATUS_UNANSWERED;
+
+ // Save question
+ var questionId = SQLService.CreateOrUpdateQuestion(questionModel);
+
+ var attachment = CreateBotAnswerCard(response.Id, response.Answer, response.Score, questionId, questionModel.OriginalPoster.Email);
+
+ var reply = activity.CreateReply();
+ reply.Attachments.Add(attachment);
+ await context.PostAsync(reply);
+ }
+
+ private async Task HandleTagAdminWorkflow(Microsoft.Bot.Connector.Activity activity, QuestionModel questionModel, string teamId, int courseId)
+ {
+ var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
+
+ // Tag admin workflow
+ IList members = await connector.Conversations.GetConversationMembersAsync(teamId);
+ var teamsMembers = members.AsTeamsChannelAccounts().ToList();
+
+ // Get original poster
+ var originalPosterAsTeamsChannelAccount = teamsMembers.Where(x => x.ObjectId == activity.From.Properties["aadObjectId"].ToString()).FirstOrDefault();
+ var studentUPN = originalPosterAsTeamsChannelAccount.UserPrincipalName;
+ var mappedStudentCourseRole = SQLService.GetUser(studentUPN);
+
+ // Set question state
+ var questionStatus = Constants.QUESTION_STATUS_UNANSWERED;
+
+ // Save question
+ questionModel.QuestionStatus = questionStatus;
+ questionModel.OriginalPoster = mappedStudentCourseRole;
+ var questionId = SQLService.CreateOrUpdateQuestion(questionModel);
+ questionModel.ID = questionId;
+
+ // TagAdmins
+ var mentionOnlyReply = activity.CreateReply();
+ var adminsOnTeams = GetAdminChannelAccountsToTag(activity, teamId, courseId, teamsMembers, mappedStudentCourseRole);
+ foreach (var admin in adminsOnTeams)
+ {
+ mentionOnlyReply.AddMentionToText(admin, MentionTextLocation.AppendText);
+ }
+ var r1 = await connector.Conversations.ReplyToActivityAsync(mentionOnlyReply);
+
+ var reply = activity.CreateReply();
+ var attachment = CreateUserAnswerCard(questionId);
+ reply.Attachments.Add(attachment);
+ var r2 = await connector.Conversations.ReplyToActivityAsync(reply);
+
+ questionModel.AnswerCardActivityId = r2?.Id;
+ SQLService.CreateOrUpdateQuestion(questionModel);
+ }
+
+ private async Task HandleNoQuestion(IDialogContext context, Microsoft.Bot.Connector.Activity activity, QuestionModel questionModel, string channelId)
+ {
+ var messageId = questionModel.MessageId;
+ // We stripped the @mention and html tags. If nothing remains then this means the user forgot to tag the bot in the original question and tagged it in a reply, so we need to handle it
+ // Get the ID of the parent message (which should be the root)
+ var thisTeamsMessage = await GetMessage(questionModel.GroupId, channelId, messageId);
+
+ // check for null below
+ if (thisTeamsMessage == null)
+ {
+ // Get root message
+ var rootTeamsMessage = await GetRootMessage(questionModel.GroupId, channelId, messageId, questionModel.ConversationId);
+ var question = MicrosoftTeamsChannelHelper.StripHtmlTags(rootTeamsMessage.Body.Content);
+ messageId = rootTeamsMessage.Id;
+ var conversationId = channelId + @";messageid=" + messageId;
+
+ questionModel.QuestionText = question;
+ questionModel.MessageId = messageId;
+ questionModel.ConversationId = conversationId;
+
+ // Get original poster
+ var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
+ IList members = await connector.Conversations.GetConversationMembersAsync(questionModel.TeamId);
+ var teamsMembers = members.AsTeamsChannelAccounts();
+ var originalPosterAsTeamsChannelAccount = teamsMembers.Where(x => x.ObjectId == rootTeamsMessage.From.User.Id).FirstOrDefault();
+ var userUpn = originalPosterAsTeamsChannelAccount.UserPrincipalName;
+ var user = SQLService.GetUser(userUpn);
+
+ // Handle if the bot gets tagged again in the same set of replies
+ if (SQLService.DoesConversationIdExist(conversationId))
+ {
+ // WE DO NOTHING!
+ }
+ else
+ {
+ // get courseID
+ var courseID = SQLService.GetCourseIDByName(questionModel.TeamName.Trim());
+ var course = SQLService.GetCourse(courseID);
+ questionModel.CourseID = courseID;
+ await HandleQuestionWorkflow(context, activity, course, questionModel);
+ }
+ }
+ else
+ {
+ // Empty was the root, which means the user simply forgot to ask a question.
+ await context.PostAsync($"If you have a question, please include it as part of your message.");
+ }
+ }
+
+ private List GetAdminChannelAccountsToTag(Microsoft.Bot.Connector.Activity activity, string teamId, int courseID, List teamsMembers, UserCourseRoleMappingModel mappedStudentCourseRole)
+ {
+ var adminsOnTeams = new List();
+
+ if (mappedStudentCourseRole != null)
+ {
+ if (mappedStudentCourseRole.Role != null && mappedStudentCourseRole.Role.Name != Constants.STUDENT_ROLE)
+ {
+ // Not a student - notify lecturer
+ var lecturers = SQLService.GetUsersByRole(Constants.LECTURER_ROLE, courseID);
+
+ foreach (var admin in lecturers)
+ {
+ var adminOnTeams = teamsMembers.Where(x =>
+ (x.Email.ToLower() == admin.Email.ToLower() || x.Email.ToLower() == admin.UserName.ToLower() || x.UserPrincipalName.ToLower() == admin.UserName.ToLower() || x.UserPrincipalName.ToLower() == admin.Email.ToLower()) &&
+ (x.Email != mappedStudentCourseRole.Email && x.Email != mappedStudentCourseRole.UserName && x.UserPrincipalName != mappedStudentCourseRole.UserName && x.UserPrincipalName != mappedStudentCourseRole.Email)
+ ).FirstOrDefault();
+ if (adminOnTeams != null)
+ {
+ adminsOnTeams.Add(adminOnTeams);
+ }
+ }
+ }
+ else
+ {
+ // Is a student
+ if (mappedStudentCourseRole.TutorialGroups != null && mappedStudentCourseRole.TutorialGroups.Count > 0)
+ {
+ // Notify demonstrator
+ var tutorialAdmins = new List();
+ foreach (var tutorialGroup in mappedStudentCourseRole.TutorialGroups)
+ {
+ tutorialAdmins.AddRange(SQLService.GetDemonstrators(courseID));
+ }
+
+
+ if (tutorialAdmins != null)
+ {
+ foreach (var admin in tutorialAdmins)
+ {
+ var adminOnTeams = teamsMembers.Where(x =>
+ (x.Email == admin.Email || x.Email == admin.UserName || x.UserPrincipalName == admin.UserName || x.UserPrincipalName == admin.Email) &&
+ (x.Email != mappedStudentCourseRole.Email && x.Email != mappedStudentCourseRole.UserName && x.UserPrincipalName != mappedStudentCourseRole.UserName && x.UserPrincipalName != mappedStudentCourseRole.Email)
+ ).FirstOrDefault();
+ if (adminOnTeams != null)
+ {
+ adminsOnTeams.Add(adminOnTeams);
+ }
+ }
+ }
+ }
+ else
+ {
+ // student without tutorial class
+ var allAdmins = SQLService.GetAllAdmins(courseID).Distinct();
+
+ if (allAdmins != null)
+ {
+ foreach (var admin in allAdmins)
+ {
+ var adminOnTeams = teamsMembers.Where(x =>
+ (x.Email == admin.Email || x.Email == admin.UserName || x.UserPrincipalName == admin.UserName || x.UserPrincipalName == admin.Email) &&
+ (x.Email != mappedStudentCourseRole.Email && x.Email != mappedStudentCourseRole.UserName && x.UserPrincipalName != mappedStudentCourseRole.UserName && x.UserPrincipalName != mappedStudentCourseRole.Email)
+ ).FirstOrDefault();
+ if (adminOnTeams != null)
+ {
+ adminsOnTeams.Add(adminOnTeams);
+ }
+ }
+ }
+ }
+
+ }
+ }
+ else
+ {
+ // User not in database
+ // Notify lecturer
+ var lecturers = SQLService.GetUsersByRole(Constants.LECTURER_ROLE, courseID);
+
+ foreach (var admin in lecturers)
+ {
+ var adminOnTeams = teamsMembers.Where(x =>
+ (x.Email == admin.Email || x.Email == admin.UserName || x.UserPrincipalName == admin.UserName || x.UserPrincipalName == admin.Email)
+ ).FirstOrDefault();
+ if (adminOnTeams != null)
+ {
+ adminsOnTeams.Add(adminOnTeams);
+ }
+ }
+ }
+
+ return adminsOnTeams;
+ }
+
+ private Attachment CreateBotAnswerCard(int qnaId, string answerText, double confidenceScore, int questionId, string userUpn)
+ {
+ var card = new AdaptiveCard();
+
+ var title = new AdaptiveTextBlock("'" + answerText.ReplaceLinksWithMarkdown() + "'");
+ title.Weight = AdaptiveTextWeight.Bolder;
+ title.Size = AdaptiveTextSize.Medium;
+ title.Wrap = true;
+
+ var confidence = new AdaptiveTextBlock("I think that is the answer (confidence score of " + confidenceScore.ToString("0.##") + "%)");
+ confidence.Wrap = true;
+
+ card.Body.Add(title);
+ card.Body.Add(confidence);
+
+ var actionHelpfulJson = "{\"type\":\"" + Constants.ACTIVITY_BOT_HELPFUL + "\",\"questionId\": \"" + questionId + "\", \"answer\": \"" + answerText + "\", \"qnaId\": \"" + qnaId + "\"}";
+ var actionUnhelpfulJson = "{\"type\":\"" + Constants.ACTIVITY_BOT_NOT_HELPFUL + "\",\"questionId\": \"" + questionId + "\" ,\"userUpn\": \"" + userUpn + "\"}";
+
+
+ card.Actions.AddRange(new List()
+ {
+ new AdaptiveSubmitAction() { Type = AdaptiveSubmitAction.TypeName, Title = "This is helpful", DataJson = actionHelpfulJson },
+ new AdaptiveSubmitAction() { Type = AdaptiveSubmitAction.TypeName, Title = this.resourceService.GetValueFor("TagAdmins"), DataJson = actionUnhelpfulJson },
+ });
+
+ Attachment attachment = new Attachment()
+ {
+ ContentType = AdaptiveCard.ContentType,
+ Content = card,
+ };
+
+ return attachment;
+ }
+
+ private Attachment CreateUserAnswerCard(int questionId)
+ {
+ var actionJson = "{\"type\":\"" + Constants.ACTIVITY_SELECT_ANSWER + "\",\"questionId\": \"" + questionId + "\"}";
+
+ var card = new HeroCard()
+ {
+ Buttons = new List()
+ {
+ new CardAction(ActivityTypes.Invoke, "Select the answer", value: actionJson),
+ },
+ };
+
+ return card.ToAttachment();
+ }
+
+ private string CreateLink(string conversationIdString, string tenantId, string groupId, string messageId, string teamName, string channelName)
+ {
+ var conversationId = conversationIdString.Split(';')[0];
+ var linkBuilder = new StringBuilder(string.Empty);
+
+ linkBuilder.Append(@"https://teams.microsoft.com/l/message/" + conversationId);
+ linkBuilder.Append(@"/" + messageId);
+ linkBuilder.Append(@"?tenantId=" + tenantId);
+ linkBuilder.Append(@"&groupId=" + groupId);
+ linkBuilder.Append(@"&parentMessageId=" + messageId);
+ linkBuilder.Append(@"&teamName=" + HttpUtility.UrlEncode(teamName));
+ linkBuilder.Append(@"&channelName=" + HttpUtility.UrlEncode(channelName));
+ linkBuilder.Append(@"&createdTime=" + messageId);
+
+ return linkBuilder.ToString();
+ }
+
+ private async Task GetRootMessage(string teamsId, string channelId, string messageId, string conversationId)
+ {
+ // Get root message id from conversationid
+ var rootMessageId = conversationId.Split(';')[1].Split('=')[1];
+
+ var authority = ServiceHelper.Authority;
+ var resource = ServiceHelper.GraphResource;
+
+ var authService = new AuthService(authority);
+ var authResult = await authService.AuthenticateSilently(resource);
+
+ var graphService = new GraphService();
+ var teamsMessage = await graphService.GetMessage(authResult.AccessToken, teamsId, channelId, rootMessageId);
+
+ return teamsMessage;
+ }
+
+ private async Task GetMessage(string teamsId, string channelId, string messageId)
+ {
+ var authority = ServiceHelper.Authority;
+ var resource = ServiceHelper.GraphResource;
+
+ var authService = new AuthService(authority);
+ var authResult = await authService.AuthenticateSilently(resource);
+
+ var graphService = new GraphService();
+ var teamsMessage = await graphService.GetMessage(authResult.AccessToken, teamsId, channelId, messageId);
+
+ return teamsMessage;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Global.asax b/Source/Microsoft.Teams.Apps.QBot.Bot/Global.asax
new file mode 100644
index 0000000..755389c
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Global.asax
@@ -0,0 +1 @@
+<%@ Application Codebehind="Global.asax.cs" Inherits="Microsoft.Teams.Apps.QBot.Bot.WebApiApplication" Language="C#" %>
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Global.asax.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Global.asax.cs
new file mode 100644
index 0000000..17dff28
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Global.asax.cs
@@ -0,0 +1,214 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Globalization;
+using System.IdentityModel.Tokens.Jwt;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Reflection;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Web;
+using System.Web.Http;
+using System.Web.Mvc;
+using System.Web.Routing;
+using Autofac;
+using Microsoft.Bot.Builder.Azure;
+using Microsoft.Bot.Builder.Dialogs;
+using Microsoft.Bot.Builder.Dialogs.Internals;
+using Microsoft.Bot.Connector;
+using Microsoft.IdentityModel.Protocols;
+using Microsoft.IdentityModel.Protocols.OpenIdConnect;
+using Microsoft.IdentityModel.Tokens;
+using Microsoft.Teams.Apps.QBot.Bot.Services;
+
+namespace Microsoft.Teams.Apps.QBot.Bot
+{
+ public class WebApiApplication : System.Web.HttpApplication
+ {
+ BotJwtRefreshWorker _BotJwtRefreshWorker;
+
+ protected void Application_Start()
+ {
+ AreaRegistration.RegisterAllAreas();
+ RouteConfig.RegisterRoutes(RouteTable.Routes);
+
+ _BotJwtRefreshWorker = new BotJwtRefreshWorker();
+
+ Conversation.UpdateContainer(
+ builder =>
+ {
+ var store = new InMemoryDataStore();
+
+ builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));
+ // Other storage options
+ // var store = new TableBotDataStore("...DataStorageConnectionString..."); // requires Microsoft.BotBuilder.Azure Nuget package
+ // var store = new DocumentDbBotDataStore("cosmos db uri", "cosmos db key"); // requires Microsoft.BotBuilder.Azure Nuget package
+
+ builder.Register(c => store)
+ .Keyed>(AzureModule.Key_DataStore)
+ .AsSelf()
+ .SingleInstance();
+ });
+
+ GlobalConfiguration.Configure(WebApiConfig.Register);
+ GlobalConfiguration.Configuration.MessageHandlers.Add(new TokenValidationHandler());
+ }
+
+ protected void Application_End()
+ {
+ _BotJwtRefreshWorker.Dispose();
+ _BotJwtRefreshWorker = null;
+ }
+ }
+ internal class TokenValidationHandler : DelegatingHandler
+ {
+ //
+ // The AAD Instance is the instance of Azure, for example public Azure or Azure China.
+ // The Tenant is the name of the tenant in which this application is registered.
+ // The Authority is the sign-in URL of the tenant.
+ // The Audience is the value of one of the 'aud' claims the service expects to find in token to assure the token is addressed to it.
+
+ private string _audience;
+ private string _authority;
+ private string _clientId;
+ private ConfigurationManager _configManager;
+ private string _tenant;
+ private ISecurityTokenValidator _tokenValidator;
+
+ public TokenValidationHandler()
+ {
+ _audience = ConfigurationManager.AppSettings["ida:Audience"];
+ _clientId = ConfigurationManager.AppSettings["ida:ClientId"];
+ var aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
+ _tenant = ConfigurationManager.AppSettings["ida:TenantId"];
+ _authority = string.Format(CultureInfo.InvariantCulture, aadInstance, _tenant);
+ _configManager = new ConfigurationManager($"{_authority}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
+ _tokenValidator = new JwtSecurityTokenHandler();
+ }
+
+ ///
+ /// Checks that incoming requests have a valid access token, and sets the current user identity using that access token.
+ ///
+ /// the current .
+ /// a set by application.
+ /// A .
+ protected async override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+ {
+ // Let Bot Message requests go through
+ if (request.RequestUri.AbsolutePath.Contains("/api/messages"))
+ {
+ return await base.SendAsync(request, cancellationToken);
+ }
+
+ // For debugging/development purposes, one can enable additional detail in exceptions by setting IdentityModelEventSource.ShowPII to true.
+ Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
+
+ // check if there is a jwt in the authorization header, return 'Unauthorized' error if the token is null.
+ if (request.Headers.Authorization == null || request.Headers.Authorization.Parameter == null)
+ {
+ return BuildResponseErrorMessage(HttpStatusCode.Unauthorized);
+ }
+
+ // Pull OIDC discovery document from Azure AD. For example, the tenant-independent version of the document is located
+ // at https://login.microsoftonline.com/common/.well-known/openid-configuration.
+ OpenIdConnectConfiguration config = null;
+ try
+ {
+ config = await _configManager.GetConfigurationAsync(cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ return BuildResponseErrorMessage(HttpStatusCode.InternalServerError, ex.Message);
+#else
+ return new HttpResponseMessage(HttpStatusCode.InternalServerError);
+#endif
+ }
+
+ // You can get a list of issuers for the various Azure AD deployments (global & sovereign) from the following endpoint
+ //https://login.microsoftonline.com/common/discovery/instance?authorization_endpoint=https://login.microsoftonline.com/common/oauth2/v2.0/authorize&api-version=1.1;
+
+ IList validissuers = new List()
+ {
+ $"https://login.microsoftonline.com/{_tenant}/",
+ $"https://login.microsoftonline.com/{_tenant}/v2.0",
+ $"https://login.windows.net/{_tenant}/",
+ $"https://login.microsoft.com/{_tenant}/",
+ $"https://sts.windows.net/{_tenant}/"
+ };
+
+ // Initialize the token validation parameters
+ TokenValidationParameters validationParameters = new TokenValidationParameters
+ {
+ // App Id URI and AppId of this service application are both valid audiences.
+ ValidAudiences = new[] { _audience, _clientId },
+
+ // Support Azure AD V1 and V2 endpoints.
+ ValidIssuers = validissuers,
+ IssuerSigningKeys = config.SigningKeys
+ };
+
+ try
+ {
+ // Validate token.
+ SecurityToken securityToken;
+ var claimsPrincipal = _tokenValidator.ValidateToken(request.Headers.Authorization.Parameter, validationParameters, out securityToken);
+
+#pragma warning disable 1998
+ // This check is required to ensure that the Web API only accepts tokens from tenants where it has been consented to and provisioned.
+// if (!claimsPrincipal.Claims.Any(x => x.Type == ClaimConstants.ScopeClaimType)
+// && !claimsPrincipal.Claims.Any(y => y.Type == ClaimConstants.RolesClaimType))
+// {
+//#if DEBUG
+// return BuildResponseErrorMessage(HttpStatusCode.Forbidden, "Neither 'scope' or 'roles' claim was found in the bearer token.");
+//#else
+// return BuildResponseErrorMessage(HttpStatusCode.Forbidden);
+//#endif
+// }
+#pragma warning restore 1998
+
+ // Set the ClaimsPrincipal on the current thread.
+ Thread.CurrentPrincipal = claimsPrincipal;
+
+ // Set the ClaimsPrincipal on HttpContext.Current if the app is running in web hosted environment.
+ if (HttpContext.Current != null)
+ HttpContext.Current.User = claimsPrincipal;
+
+ // If the token is scoped, verify that required permission is set in the scope claim. This could be done later at the controller level as well
+ //if (ClaimsPrincipal.Current.FindFirst(ClaimConstants.ScopeClaimType).Value != ClaimConstants.ScopeClaimValue)
+ // return BuildResponseErrorMessage(HttpStatusCode.Forbidden);
+
+ return await base.SendAsync(request, cancellationToken);
+ }
+ catch (SecurityTokenValidationException stex)
+ {
+#if DEBUG
+ return BuildResponseErrorMessage(HttpStatusCode.Unauthorized, stex.Message);
+#else
+ return BuildResponseErrorMessage(HttpStatusCode.Unauthorized);
+#endif
+ }
+ catch (Exception ex)
+ {
+#if DEBUG
+ return BuildResponseErrorMessage(HttpStatusCode.InternalServerError, ex.Message);
+#else
+ return new HttpResponseMessage(HttpStatusCode.InternalServerError);
+#endif
+ }
+ }
+
+ private HttpResponseMessage BuildResponseErrorMessage(HttpStatusCode statusCode, string error_description = "")
+ {
+ var response = new HttpResponseMessage(statusCode);
+
+ // The Scheme should be "Bearer", authorization_uri should point to the tenant url and resource_id should point to the audience.
+ var authenticateHeader = new AuthenticationHeaderValue("Bearer", "authorization_uri=\"" + _authority + "\"" + "," + "resource_id=" + _audience + $",error_description={error_description}");
+ response.Headers.WwwAuthenticate.Add(authenticateHeader);
+ return response;
+ }
+ }
+
+}
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Microsoft.Teams.Apps.QBot.Bot.csproj b/Source/Microsoft.Teams.Apps.QBot.Bot/Microsoft.Teams.Apps.QBot.Bot.csproj
new file mode 100644
index 0000000..e51d682
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Microsoft.Teams.Apps.QBot.Bot.csproj
@@ -0,0 +1,462 @@
+
+
+
+
+ Debug
+ AnyCPU
+
+
+ 2.0
+ {A8BA1066-5695-4D71-ABB4-65E5A5E0C3D4}
+ {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}
+ Library
+ Properties
+ Microsoft.Teams.Apps.QBot.Bot
+ Bot Application
+ v4.7.1
+ true
+
+
+
+
+
+
+
+
+
+ SAK
+ SAK
+ SAK
+ SAK
+ /subscriptions/9c4f81d0-fc86-4c82-b49a-0897f03ac709/resourcegroups/educationDeliveryTeaching-pocForBots-dev/providers/microsoft.insights/components/unswquestionbot-pilot
+ /subscriptions/9c4f81d0-fc86-4c82-b49a-0897f03ac709/resourcegroups/educationDeliveryTeaching-pocForBots-dev/providers/microsoft.insights/components/unswquestionbot-pilot
+ ..\packages\WebGrease.1.5.2\lib
+
+
+ true
+ full
+ false
+ bin\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\AdaptiveCards.1.0.3\lib\net452\AdaptiveCards.dll
+
+
+ ..\packages\Autofac.4.6.2\lib\net45\Autofac.dll
+
+
+ ..\packages\Chronic.Signed.0.3.2\lib\net40\Chronic.dll
+
+
+ ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.dll
+
+
+ ..\packages\EntityFramework.6.2.0\lib\net45\EntityFramework.SqlServer.dll
+
+
+ ..\packages\HtmlAgilityPack.1.8.5\lib\Net45\HtmlAgilityPack.dll
+
+
+ ..\packages\Microsoft.ApplicationInsights.Agent.Intercept.2.4.0\lib\net45\Microsoft.AI.Agent.Intercept.dll
+
+
+ ..\packages\Microsoft.ApplicationInsights.DependencyCollector.2.7.2\lib\net45\Microsoft.AI.DependencyCollector.dll
+
+
+ ..\packages\Microsoft.ApplicationInsights.PerfCounterCollector.2.7.2\lib\net45\Microsoft.AI.PerfCounterCollector.dll
+
+
+ ..\packages\Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel.2.7.2\lib\net45\Microsoft.AI.ServerTelemetryChannel.dll
+
+
+ ..\packages\Microsoft.ApplicationInsights.Web.2.7.2\lib\net45\Microsoft.AI.Web.dll
+
+
+ ..\packages\Microsoft.ApplicationInsights.WindowsServer.2.7.2\lib\net45\Microsoft.AI.WindowsServer.dll
+
+
+ ..\packages\Microsoft.ApplicationInsights.2.7.2\lib\net46\Microsoft.ApplicationInsights.dll
+
+
+ ..\packages\Microsoft.ApplicationInsights.TraceListener.2.7.2\lib\net45\Microsoft.ApplicationInsights.TraceListener.dll
+
+
+ ..\packages\Microsoft.AspNet.TelemetryCorrelation.1.0.3\lib\net45\Microsoft.AspNet.TelemetryCorrelation.dll
+
+
+ ..\..\..\..\..\..\..\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.html.abstractions\2.1.1\lib\netstandard2.0\Microsoft.AspNetCore.Html.Abstractions.dll
+
+
+ ..\packages\Microsoft.Azure.DocumentDB.1.22.0\lib\net45\Microsoft.Azure.Documents.Client.dll
+
+
+ ..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll
+
+
+ ..\packages\Microsoft.Bot.Builder.3.15.3\lib\net46\Microsoft.Bot.Builder.dll
+
+
+ ..\packages\Microsoft.Bot.Builder.3.15.3\lib\net46\Microsoft.Bot.Builder.Autofac.dll
+
+
+ ..\packages\Microsoft.Bot.Builder.Azure.3.2.5\lib\net46\Microsoft.Bot.Builder.Azure.dll
+
+
+ ..\packages\Microsoft.Bot.Builder.History.3.15.3\lib\net46\Microsoft.Bot.Builder.History.dll
+
+
+ ..\packages\Microsoft.Bot.Connector.3.15.3\lib\net46\Microsoft.Bot.Connector.dll
+
+
+ ..\packages\Microsoft.Bot.Connector.Teams.0.9.0\lib\net46\Microsoft.Bot.Connector.Teams.dll
+
+
+
+ ..\packages\Microsoft.Data.Edm.5.7.0\lib\net40\Microsoft.Data.Edm.dll
+
+
+ ..\packages\Microsoft.Data.OData.5.7.0\lib\net40\Microsoft.Data.OData.dll
+
+
+ ..\packages\Microsoft.Data.Services.Client.5.7.0\lib\net40\Microsoft.Data.Services.Client.dll
+
+
+ ..\packages\Microsoft.IdentityModel.7.0.0\lib\net35\microsoft.identitymodel.dll
+
+
+ ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll
+
+
+ ..\packages\Microsoft.IdentityModel.Clients.ActiveDirectory.3.19.8\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll
+
+
+ ..\packages\Microsoft.IdentityModel.JsonWebTokens.5.5.0\lib\net461\Microsoft.IdentityModel.JsonWebTokens.dll
+
+
+ ..\packages\Microsoft.IdentityModel.Logging.5.5.0\lib\net461\Microsoft.IdentityModel.Logging.dll
+
+
+ ..\packages\Microsoft.IdentityModel.Protocols.5.5.0\lib\net461\Microsoft.IdentityModel.Protocols.dll
+
+
+ ..\packages\Microsoft.IdentityModel.Protocols.OpenIdConnect.5.5.0\lib\net461\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll
+
+
+ ..\packages\Microsoft.IdentityModel.Tokens.5.5.0\lib\net461\Microsoft.IdentityModel.Tokens.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.Office.Client.Education.dll
+ True
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.Office.Client.Policy.dll
+ True
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.Office.Client.TranslationServices.dll
+ True
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.Office.SharePoint.Tools.dll
+ True
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.Online.SharePoint.Client.Tenant.dll
+
+
+ ..\packages\Microsoft.Rest.ClientRuntime.2.3.10\lib\net452\Microsoft.Rest.ClientRuntime.dll
+
+
+ ..\packages\SharePoint.Client.15.0.0\lib\Microsoft.SharePoint.Client\Microsoft.SharePoint.Client.dll
+ True
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.SharePoint.Client.DocumentManagement.dll
+ True
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.SharePoint.Client.Publishing.dll
+ True
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.SharePoint.Client.Runtime.dll
+ True
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.SharePoint.Client.Search.dll
+ True
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.SharePoint.Client.Search.Applications.dll
+ True
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.SharePoint.Client.Taxonomy.dll
+ True
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.SharePoint.Client.UserProfiles.dll
+ True
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4859.1003\lib\net40-full\Microsoft.SharePoint.Client.WorkflowServices.dll
+ True
+
+
+ ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll
+
+
+ ..\packages\Microsoft.WindowsAzure.ConfigurationManager.3.2.3\lib\net40\Microsoft.WindowsAzure.Configuration.dll
+
+
+ ..\packages\WindowsAzure.Storage.7.2.1\lib\net40\Microsoft.WindowsAzure.Storage.dll
+
+
+ ..\packages\Newtonsoft.Json.11.0.1\lib\net45\Newtonsoft.Json.dll
+
+
+ ..\packages\Polly-Signed.5.8.0\lib\net45\Polly.dll
+
+
+
+ ..\packages\System.Diagnostics.DiagnosticSource.4.5.0\lib\net46\System.Diagnostics.DiagnosticSource.dll
+
+
+ ..\packages\System.IdentityModel.Tokens.Jwt.5.5.0\lib\net461\System.IdentityModel.Tokens.Jwt.dll
+
+
+
+
+
+ ..\packages\Microsoft.AspNet.WebApi.Client.5.2.7\lib\net45\System.Net.Http.Formatting.dll
+
+
+
+
+
+ ..\packages\System.Spatial.5.7.0\lib\net40\System.Spatial.dll
+
+
+ ..\packages\Microsoft.AspNet.Cors.5.2.7\lib\net45\System.Web.Cors.dll
+
+
+
+
+
+
+
+
+
+
+
+ ..\packages\Microsoft.AspNet.WebPages.3.2.4\lib\net45\System.Web.Helpers.dll
+
+
+ ..\packages\Microsoft.AspNet.WebApi.Core.5.2.7\lib\net45\System.Web.Http.dll
+
+
+ ..\packages\Microsoft.AspNet.WebApi.Cors.5.2.7\lib\net45\System.Web.Http.Cors.dll
+
+
+ ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.4\lib\net45\System.Web.Http.WebHost.dll
+
+
+ ..\packages\Microsoft.AspNet.Mvc.5.2.4\lib\net45\System.Web.Mvc.dll
+
+
+ ..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll
+
+
+ ..\packages\Microsoft.AspNet.Razor.3.2.4\lib\net45\System.Web.Razor.dll
+
+
+ ..\packages\Microsoft.AspNet.WebPages.3.2.4\lib\net45\System.Web.WebPages.dll
+
+
+ ..\packages\Microsoft.AspNet.WebPages.3.2.4\lib\net45\System.Web.WebPages.Deployment.dll
+
+
+ ..\packages\Microsoft.AspNet.WebPages.3.2.4\lib\net45\System.Web.WebPages.Razor.dll
+
+
+
+
+
+
+
+ ..\packages\ZXing.Net.0.16.4\lib\net47\zxing.dll
+
+
+ ..\packages\ZXing.Net.0.16.4\lib\net47\zxing.presentation.dll
+
+
+
+
+
+
+ stylecop.json
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+ GlobalSuppressions.cs
+
+
+
+
+
+
+
+
+
+ Global.asax
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ strings.resx
+
+
+
+
+
+
+
+
+
+ Designer
+
+
+ PreserveNewest
+
+
+
+ Web.config
+
+
+ Web.config
+
+
+
+
+ {8392407D-7934-4D2A-B0F0-BD6E866A2E38}
+ EncryptionHelper
+
+
+ {4e7a14ca-80cd-447c-8c3d-615b45c56939}
+ Microsoft.Teams.Apps.QBot.Data
+
+
+ {5C7943E8-9C2A-4C81-90B3-A672876DCBDD}
+ Microsoft.Teams.Apps.QBot.Model
+
+
+
+
+
+ ResXFileCodeGenerator
+ strings.Designer.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10.0
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
+
+
+ true
+
+
+ bin\
+ TRACE
+ true
+ pdbonly
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+
+
+
+
+
+
+ True
+ True
+ 3979
+ /
+ http://localhost:3979/
+ False
+ False
+
+
+ False
+
+
+
+
+
+
+
+ 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}.
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Models/Models.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Models/Models.cs
new file mode 100644
index 0000000..7fe5bcf
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Models/Models.cs
@@ -0,0 +1,102 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Web;
+using Microsoft.Bot.Connector;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Models
+{
+ public class BotFrameworkCardValue
+ {
+ [JsonProperty("type")]
+ public object Type { get; set; } = "task/fetch";
+
+ [JsonProperty("data")]
+ public T Data { get; set; }
+ }
+
+ public class AdaptiveCardValue
+ {
+ [JsonProperty("msteams")]
+ public object Type { get; set; } = JsonConvert.DeserializeObject("{\"type\": \"task/fetch\" }");
+
+ [JsonProperty("data")]
+ public T Data { get; set; }
+ }
+
+ public class TaskModuleActionData
+ {
+ [JsonProperty("data")]
+ public BotFrameworkCardValue Data { get; set; }
+ }
+
+ public class TaskInfo
+ {
+ [JsonProperty("url")]
+ public string Url { get; set; }
+
+ [JsonProperty("card")]
+ public Attachment Card { get; set; }
+
+ [JsonProperty("title")]
+ public string Title { get; set; }
+
+ [JsonProperty("height")]
+ public object Height { get; set; }
+
+ [JsonProperty("width")]
+ public object Width { get; set; }
+
+ [JsonProperty("fallbackUrl")]
+ public string FallbackUrl { get; set; }
+
+ [JsonProperty("completionBotId")]
+ public string CompletionBotId { get; set; }
+
+ public string ToJson()
+ {
+ return JsonConvert.SerializeObject(this);
+ }
+ }
+
+ public class TaskEnvelope
+ {
+ [JsonProperty("task")]
+ public Task Task { get; set; }
+ }
+
+ public class Task
+ {
+ [JsonProperty("value")]
+ public TaskInfo TaskInfo { get; set; }
+
+ [JsonProperty("type")]
+ public TaskType Type { get; set; }
+ }
+
+ public enum TaskType
+ {
+ ///
+ /// Teams will display the value of value in a popup message box.
+ ///
+ [EnumMember(Value = "message")]
+ Message,
+
+ ///
+ /// Allows you to "chain" sequences of Adaptive cards together in a wizard/multi-step experience.
+ ///
+ [EnumMember(Value = "continue")]
+ Continue
+ }
+
+
+ public class StreamVideoProperties
+ {
+ public string VideoTitle { get; set; }
+ public string VideoID { get; set; }
+ public int VideoStartTime { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Models/UIConstants.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Models/UIConstants.cs
new file mode 100644
index 0000000..11cd7e7
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Models/UIConstants.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Models
+{
+ public static class TaskModuleUIConstants
+ {
+ public static UIConstants MSStream { get; set; } =
+ new UIConstants(1280, 720, "Problem052 - Frames and Machines", TaskModuleIds.MSStream, "MS Stream");
+ public static UIConstants YouTube { get; set; } =
+ new UIConstants(1000, 700, "Microsoft Ignite 2018 Vision Keynote", TaskModuleIds.YouTube, "YouTube");
+ public static UIConstants PowerApp { get; set; } =
+ new UIConstants(720, 520, "PowerApp: Asset Checkout", TaskModuleIds.PowerApp, "Power App");
+ public static UIConstants CustomForm { get; set; } =
+ new UIConstants(510, 450, "Custom Form", TaskModuleIds.CustomForm, "Custom Form");
+ public static UIConstants AdaptiveCard { get; set; } =
+ new UIConstants(700, 500, "Adaptive Card: Inputs", TaskModuleIds.AdaptiveCard, "Adaptive Card");
+ }
+
+ public class UIConstants
+ {
+ public UIConstants(int width, int height, string title, string id, string buttonTitle)
+ {
+ Width = width;
+ Height = height;
+ Title = title;
+ Id = id;
+ ButtonTitle = buttonTitle;
+ }
+
+ public int Height { get; set; }
+ public int Width { get; set; }
+ public string Title { get; set; }
+ public string ButtonTitle { get; set; }
+ public string Id { get; set; }
+ }
+
+ public class TaskModuleIds
+ {
+ public const string MSStream = "msstream";
+ public const string YouTube = "youtube";
+ public const string PowerApp = "powerapp";
+ public const string CustomForm = "customform";
+ public const string AdaptiveCard = "adaptivecard";
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Properties/AssemblyInfo.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..30990c4
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+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("Microsoft.Teams.Apps.QBot.Bot")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Microsoft.Teams.Apps.QBot.Bot")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[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("a8cb9a21-19b5-4ef9-ad7e-ffb55793d50c")]
+
+// 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 Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Properties/Strings.Designer.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Properties/Strings.Designer.cs
new file mode 100644
index 0000000..d9bb2aa
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Properties/Strings.Designer.cs
@@ -0,0 +1,2097 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft.Teams.TemplateBotCSharp.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Strings {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Strings() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Teams.TemplateBotCSharp.Properties.Strings", typeof(Strings).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Cannot resume!.
+ ///
+ internal static string AuthCallbackResumeError {
+ get {
+ return ResourceManager.GetString("AuthCallbackResumeError", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Entered numbered is not valid!, please login again..
+ ///
+ internal static string AuthMagicNumberNotMacthed {
+ get {
+ return ResourceManager.GetString("AuthMagicNumberNotMacthed", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Please Clicked below any OAuth 2.0 Samples (Bot Command - "auth").
+ ///
+ internal static string AuthSampleCardTitle {
+ get {
+ return ResourceManager.GetString("AuthSampleCardTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Chat.
+ ///
+ internal static string CaptionChatButton {
+ get {
+ return ResourceManager.GetString("CaptionChatButton", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invoke Hello Dialog.
+ ///
+ internal static string CaptionInvokeHelloDailog {
+ get {
+ return ResourceManager.GetString("CaptionInvokeHelloDailog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Invoke Multi Dialog.
+ ///
+ internal static string CaptionInvokeMultiDailog {
+ get {
+ return ResourceManager.GetString("CaptionInvokeMultiDailog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to auth.
+ ///
+ internal static string cmdAuthSampleDialog {
+ get {
+ return ResourceManager.GetString("cmdAuthSampleDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to deep link.
+ ///
+ internal static string cmdDeepLink {
+ get {
+ return ResourceManager.GetString("cmdDeepLink", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to dialog flow.
+ ///
+ internal static string cmdDialogFlow {
+ get {
+ return ResourceManager.GetString("cmdDialogFlow", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to display cards.
+ ///
+ internal static string cmdDisplayCards {
+ get {
+ return ResourceManager.GetString("cmdDisplayCards", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to last dialog.
+ ///
+ internal static string cmdFetchLastDialog {
+ get {
+ return ResourceManager.GetString("cmdFetchLastDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to names.
+ ///
+ internal static string cmdFetchRoster {
+ get {
+ return ResourceManager.GetString("cmdFetchRoster", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to hi.
+ ///
+ internal static string cmdHelloDialog {
+ get {
+ return ResourceManager.GetString("cmdHelloDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to localtime.
+ ///
+ internal static string cmdLocalTime {
+ get {
+ return ResourceManager.GetString("cmdLocalTime", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to msgback.
+ ///
+ internal static string cmdMessageBack {
+ get {
+ return ResourceManager.GetString("cmdMessageBack", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to multi dialog 1.
+ ///
+ internal static string cmdMultiDialog1 {
+ get {
+ return ResourceManager.GetString("cmdMultiDialog1", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to multi dialog 2.
+ ///
+ internal static string cmdMultiDialog2 {
+ get {
+ return ResourceManager.GetString("cmdMultiDialog2", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to no.
+ ///
+ internal static string cmdNoDisplayCards {
+ get {
+ return ResourceManager.GetString("cmdNoDisplayCards", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Actionable Card.
+ ///
+ internal static string cmdO365ConnectorCardActionableMessages {
+ get {
+ return ResourceManager.GetString("cmdO365ConnectorCardActionableMessages", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to signin.
+ ///
+ internal static string cmdPopUpSignIn {
+ get {
+ return ResourceManager.GetString("cmdPopUpSignIn", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to prompt.
+ ///
+ internal static string cmdPrompt {
+ get {
+ return ResourceManager.GetString("cmdPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to roster.
+ ///
+ internal static string cmdRosterPayload {
+ get {
+ return ResourceManager.GetString("cmdRosterPayload", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to at mention.
+ ///
+ internal static string cmdRunAtMentionDialog {
+ get {
+ return ResourceManager.GetString("cmdRunAtMentionDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to quiz.
+ ///
+ internal static string cmdRunQuiz {
+ get {
+ return ResourceManager.GetString("cmdRunQuiz", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to send message to 1:1.
+ ///
+ internal static string cmdSend1on1ConversationDialog {
+ get {
+ return ResourceManager.GetString("cmdSend1on1ConversationDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to setup text message.
+ ///
+ internal static string cmdSetupMessage {
+ get {
+ return ResourceManager.GetString("cmdSetupMessage", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to update card message.
+ ///
+ internal static string cmdUpdateCard {
+ get {
+ return ResourceManager.GetString("cmdUpdateCard", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to update text message.
+ ///
+ internal static string cmdUpdateMessage {
+ get {
+ return ResourceManager.GetString("cmdUpdateMessage", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to msgback.
+ ///
+ internal static string cmdValueMessageBack {
+ get {
+ return ResourceManager.GetString("cmdValueMessageBack", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to composeExtensionCardType.
+ ///
+ internal static string ComposeExtensionCardTypeKeyword {
+ get {
+ return ResourceManager.GetString("ComposeExtensionCardTypeKeyword", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This Compose Extension is used as Compose Extension Sample. To change your settings either enter the work 'settings' or change your settings on the settings menu option.To reset your configuration, simply enter the word 'reset'..
+ ///
+ internal static string ComposeExtensionInitialRunText {
+ get {
+ return ResourceManager.GetString("ComposeExtensionInitialRunText", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to ERROR: No user data.
+ ///
+ internal static string ComposeExtensionNoUserData {
+ get {
+ return ResourceManager.GetString("ComposeExtensionNoUserData", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to composeextension/querysettingurl.
+ ///
+ internal static string ComposeExtensionQuerySettingUrl {
+ get {
+ return ResourceManager.GetString("ComposeExtensionQuerySettingUrl", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to reset.
+ ///
+ internal static string ComposeExtensionResetKeyword {
+ get {
+ return ResourceManager.GetString("ComposeExtensionResetKeyword", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Your compose extension state has been reset..
+ ///
+ internal static string ComposeExtensionResetText {
+ get {
+ return ResourceManager.GetString("ComposeExtensionResetText", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to setting.
+ ///
+ internal static string ComposeExtensionSettingKeyword {
+ get {
+ return ResourceManager.GetString("ComposeExtensionSettingKeyword", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to settings.
+ ///
+ internal static string ComposeExtensionSettingsKeyword {
+ get {
+ return ResourceManager.GetString("ComposeExtensionSettingsKeyword", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Static Tab Deep Link.
+ ///
+ internal static string DeepLinkCard1To1ButtonCaption {
+ get {
+ return ResourceManager.GetString("DeepLinkCard1To1ButtonCaption", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Please click below to navigate static tab.
+ ///
+ internal static string DeepLinkCard1To1Title {
+ get {
+ return ResourceManager.GetString("DeepLinkCard1To1Title", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Config Tab Deep Link.
+ ///
+ internal static string DeepLinkCardConfigButtonCaption {
+ get {
+ return ResourceManager.GetString("DeepLinkCardConfigButtonCaption", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Please click below to navigate config tab.
+ ///
+ internal static string DeepLinkCardConfigTitle {
+ get {
+ return ResourceManager.GetString("DeepLinkCardConfigTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This is step1 in Root Dialog.
+ ///
+ internal static string DialogFlowStep1 {
+ get {
+ return ResourceManager.GetString("DialogFlowStep1", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This is step2 in Root Dialog.
+ ///
+ internal static string DialogFlowStep2 {
+ get {
+ return ResourceManager.GetString("DialogFlowStep2", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This is step3 in Root Dialog After triggering the Hello Dialog.
+ ///
+ internal static string DialogFlowStep3 {
+ get {
+ return ResourceManager.GetString("DialogFlowStep3", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Failed with message:.
+ ///
+ internal static string DisplayCardErrorMsg {
+ get {
+ return ResourceManager.GetString("DisplayCardErrorMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Hero Card.
+ ///
+ internal static string DisplayCardHeroCard {
+ get {
+ return ResourceManager.GetString("DisplayCardHeroCard", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Connector Card Actions.
+ ///
+ internal static string DisplayCardO365ConnectorActionableCard {
+ get {
+ return ResourceManager.GetString("DisplayCardO365ConnectorActionableCard", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Connector Card Actions V2.
+ ///
+ internal static string DisplayCardO365ConnectorActionableCardV2 {
+ get {
+ return ResourceManager.GetString("DisplayCardO365ConnectorActionableCardV2", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to ConnectorCardV1.
+ ///
+ internal static string DisplayCardO365ConnectorCardV1 {
+ get {
+ return ResourceManager.GetString("DisplayCardO365ConnectorCardV1", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to ConnectorCardV2.
+ ///
+ internal static string DisplayCardO365ConnectorCardV2 {
+ get {
+ return ResourceManager.GetString("DisplayCardO365ConnectorCardV2", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to ConnectorCardV3.
+ ///
+ internal static string DisplayCardO365ConnectorCardV3 {
+ get {
+ return ResourceManager.GetString("DisplayCardO365ConnectorCardV3", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to What card you would like to test?.
+ ///
+ internal static string DisplayCardPromptText {
+ get {
+ return ResourceManager.GetString("DisplayCardPromptText", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Do you want to test another card?.
+ ///
+ internal static string DisplayCardsPromptChoiceTitle {
+ get {
+ return ResourceManager.GetString("DisplayCardsPromptChoiceTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Hope you liked the Cards!!.
+ ///
+ internal static string DisplayCardsThanksMsg {
+ get {
+ return ResourceManager.GetString("DisplayCardsThanksMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Thumbnail Card.
+ ///
+ internal static string DisplayCardThumbnailCard {
+ get {
+ return ResourceManager.GetString("DisplayCardThumbnailCard", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to There is some error updating last message.
+ ///
+ internal static string ErrorTextMessageUpdate {
+ get {
+ return ResourceManager.GetString("ErrorTextMessageUpdate", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Facebook Auth.
+ ///
+ internal static string FBAuthCardCaption {
+ get {
+ return ResourceManager.GetString("FBAuthCardCaption", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to fblogin.
+ ///
+ internal static string FBAuthCardValue {
+ get {
+ return ResourceManager.GetString("FBAuthCardValue", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Unable to deserialize the Facebook response..
+ ///
+ internal static string FBAuthDeserializeError {
+ get {
+ return ResourceManager.GetString("FBAuthDeserializeError", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Go to User Profile.
+ ///
+ internal static string FBCardButtonCaption {
+ get {
+ return ResourceManager.GetString("FBCardButtonCaption", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to To logged out from Facebook, use command 'fblogout'.
+ ///
+ internal static string FBLginSuccessPromptLogoutInfo {
+ get {
+ return ResourceManager.GetString("FBLginSuccessPromptLogoutInfo", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Login to Facebook!.
+ ///
+ internal static string FBLoginCardButtonCaption {
+ get {
+ return ResourceManager.GetString("FBLoginCardButtonCaption", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to You need to authorize me.
+ ///
+ internal static string FBLoginCardPrompt {
+ get {
+ return ResourceManager.GetString("FBLoginCardPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to You are already logged in, Enjoy your login session!!.
+ ///
+ internal static string FBLoginSessionExistsPrompt {
+ get {
+ return ResourceManager.GetString("FBLoginSessionExistsPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to You are logged in as:.
+ ///
+ internal static string FBLoginSuccessPrompt {
+ get {
+ return ResourceManager.GetString("FBLoginSuccessPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Please login in using this card.
+ ///
+ internal static string FBLoginTitle {
+ get {
+ return ResourceManager.GetString("FBLoginTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to To logged out from Facebook, use command 'fblogout'.
+ ///
+ internal static string FBLogoutPrompt {
+ get {
+ return ResourceManager.GetString("FBLogoutPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to To login again, use command 'fblogin'!.
+ ///
+ internal static string FBSuccessfulLogoutLoginPrompt {
+ get {
+ return ResourceManager.GetString("FBSuccessfulLogoutLoginPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to You are logged out from Facebook acount!.
+ ///
+ internal static string FBSuccessfulLogoutPrompt {
+ get {
+ return ResourceManager.GetString("FBSuccessfulLogoutPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This is Hello Dialog.
+ ///
+ internal static string HelloDialogMsg {
+ get {
+ return ResourceManager.GetString("HelloDialogMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to At Mention.
+ ///
+ internal static string HelpCaptionAtMention {
+ get {
+ return ResourceManager.GetString("HelpCaptionAtMention", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Auth Sample.
+ ///
+ internal static string HelpCaptionAuthSample {
+ get {
+ return ResourceManager.GetString("HelpCaptionAuthSample", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Tab Example.
+ ///
+ internal static string HelpCaptionDeepLink {
+ get {
+ return ResourceManager.GetString("HelpCaptionDeepLink", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Dialog Flow.
+ ///
+ internal static string HelpCaptionDialogFlow {
+ get {
+ return ResourceManager.GetString("HelpCaptionDialogFlow", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Choose Cards.
+ ///
+ internal static string HelpCaptionDisplayCards {
+ get {
+ return ResourceManager.GetString("HelpCaptionDisplayCards", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Fetch Last Dialog.
+ ///
+ internal static string HelpCaptionFetchLastDialog {
+ get {
+ return ResourceManager.GetString("HelpCaptionFetchLastDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Fetch Members.
+ ///
+ internal static string HelpCaptionFetchRoster {
+ get {
+ return ResourceManager.GetString("HelpCaptionFetchRoster", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Hello Dialog.
+ ///
+ internal static string HelpCaptionHelloDialog {
+ get {
+ return ResourceManager.GetString("HelpCaptionHelloDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Message Back.
+ ///
+ internal static string HelpCaptionMessageBack {
+ get {
+ return ResourceManager.GetString("HelpCaptionMessageBack", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Begin Multi Dailog 1.
+ ///
+ internal static string HelpCaptionMultiDialog1 {
+ get {
+ return ResourceManager.GetString("HelpCaptionMultiDialog1", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Begin Multi Dialog 2.
+ ///
+ internal static string HelpCaptionMultiDialog2 {
+ get {
+ return ResourceManager.GetString("HelpCaptionMultiDialog2", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Play Game.
+ ///
+ internal static string HelpCaptionPlayGame {
+ get {
+ return ResourceManager.GetString("HelpCaptionPlayGame", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Popup Sign-In.
+ ///
+ internal static string HelpCaptionPopUpSignIn {
+ get {
+ return ResourceManager.GetString("HelpCaptionPopUpSignIn", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Fetch Roster Payload.
+ ///
+ internal static string HelpCaptionRosterPayload {
+ get {
+ return ResourceManager.GetString("HelpCaptionRosterPayload", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to RunQuiz.
+ ///
+ internal static string HelpCaptionRunQuiz {
+ get {
+ return ResourceManager.GetString("HelpCaptionRunQuiz", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Send 1:1 Message.
+ ///
+ internal static string HelpCaptionSend1on1Conversation {
+ get {
+ return ResourceManager.GetString("HelpCaptionSend1on1Conversation", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Setup Message.
+ ///
+ internal static string HelpCaptionSetupMessage {
+ get {
+ return ResourceManager.GetString("HelpCaptionSetupMessage", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Update Card.
+ ///
+ internal static string HelpCaptionUpdateCard {
+ get {
+ return ResourceManager.GetString("HelpCaptionUpdateCard", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Update Message.
+ ///
+ internal static string HelpCaptionUpdateMessage {
+ get {
+ return ResourceManager.GetString("HelpCaptionUpdateMessage", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Local Time.
+ ///
+ internal static string HelpLocalTimeZone {
+ get {
+ return ResourceManager.GetString("HelpLocalTimeZone", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Template Options.
+ ///
+ internal static string HelpTitle {
+ get {
+ return ResourceManager.GetString("HelpTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Get Started.
+ ///
+ internal static string HeroCardButtonCaption {
+ get {
+ return ResourceManager.GetString("HeroCardButtonCaption", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg.
+ ///
+ internal static string HeroCardImageUrl {
+ get {
+ return ResourceManager.GetString("HeroCardImageUrl", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Your bots — wherever your users are talking.
+ ///
+ internal static string HeroCardSubTitle {
+ get {
+ return ResourceManager.GetString("HeroCardSubTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Build and connect intelligent bots to interact with your users naturally wherever they are, from text/sms to Skype, Slack, Office 365 mail and other popular services..
+ ///
+ internal static string HeroCardTextMsg {
+ get {
+ return ResourceManager.GetString("HeroCardTextMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to BotFramework Hero Card.
+ ///
+ internal static string HeroCardTitle {
+ get {
+ return ResourceManager.GetString("HeroCardTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to invokeKey.
+ ///
+ internal static string InvokeRequestJsonKey {
+ get {
+ return ResourceManager.GetString("InvokeRequestJsonKey", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to ActionableMessageCardDialog.
+ ///
+ internal static string LastDialogActionableMessageDialog {
+ get {
+ return ResourceManager.GetString("LastDialogActionableMessageDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to AtMentionDialog.
+ ///
+ internal static string LastDialogAtMentionDialog {
+ get {
+ return ResourceManager.GetString("LastDialogAtMentionDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to BeginDialog.
+ ///
+ internal static string LastDialogBeginDialog {
+ get {
+ return ResourceManager.GetString("LastDialogBeginDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to O365ConnectorCardDailog.
+ ///
+ internal static string LastDialogConnectorCard {
+ get {
+ return ResourceManager.GetString("LastDialogConnectorCard", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to ConnectorCardV1Dialog.
+ ///
+ internal static string LastDialogConnectorCardV1Dialog {
+ get {
+ return ResourceManager.GetString("LastDialogConnectorCardV1Dialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to ConnectorCardV2Dialog.
+ ///
+ internal static string LastDialogConnectorCardV2Dialog {
+ get {
+ return ResourceManager.GetString("LastDialogConnectorCardV2Dialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to ConnectorCardV3Dialog.
+ ///
+ internal static string LastDialogConnectorCardV3Dialog {
+ get {
+ return ResourceManager.GetString("LastDialogConnectorCardV3Dialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to DeepLinkStaticTabDialog.
+ ///
+ internal static string LastDialogDeepLinkStaticTabDialog {
+ get {
+ return ResourceManager.GetString("LastDialogDeepLinkStaticTabDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to DisplayCardsDialog.
+ ///
+ internal static string LastDialogDisplayCardsDialog {
+ get {
+ return ResourceManager.GetString("LastDialogDisplayCardsDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Error finding last executed dialog.
+ ///
+ internal static string LastDialogErrorMsg {
+ get {
+ return ResourceManager.GetString("LastDialogErrorMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to SimpleFacebookAuthDialog.
+ ///
+ internal static string LastDialogFacebookDialog {
+ get {
+ return ResourceManager.GetString("LastDialogFacebookDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to FetchLastDialogName.
+ ///
+ internal static string LastDialogFetchDiaog {
+ get {
+ return ResourceManager.GetString("LastDialogFetchDiaog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to FetchPayloadRosterDialog.
+ ///
+ internal static string LastDialogFetchPayloadRosterDialog {
+ get {
+ return ResourceManager.GetString("LastDialogFetchPayloadRosterDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to FetchRosterDialog.
+ ///
+ internal static string LastDialogFetchRosterDialog {
+ get {
+ return ResourceManager.GetString("LastDialogFetchRosterDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to GameDialog.
+ ///
+ internal static string LastDialogGameDialog {
+ get {
+ return ResourceManager.GetString("LastDialogGameDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to HelloDialog.
+ ///
+ internal static string LastDialogHelloDialog {
+ get {
+ return ResourceManager.GetString("LastDialogHelloDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to HelpDialog.
+ ///
+ internal static string LastDialogHelpDialog {
+ get {
+ return ResourceManager.GetString("LastDialogHelpDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to HeroCardDialog.
+ ///
+ internal static string LastDialogHeroCard {
+ get {
+ return ResourceManager.GetString("LastDialogHeroCard", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to DialogId.
+ ///
+ internal static string LastDialogKey {
+ get {
+ return ResourceManager.GetString("LastDialogKey", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Message Back Dailog.
+ ///
+ internal static string LastDialogMessageBackDialog {
+ get {
+ return ResourceManager.GetString("LastDialogMessageBackDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to MultiDialog1.
+ ///
+ internal static string LastDialogMultiDialog1 {
+ get {
+ return ResourceManager.GetString("LastDialogMultiDialog1", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to MultiDialog2.
+ ///
+ internal static string LastDialogMultiDialog2 {
+ get {
+ return ResourceManager.GetString("LastDialogMultiDialog2", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to PopUpSignInDialog.
+ ///
+ internal static string LastDialogPopUpSignIn {
+ get {
+ return ResourceManager.GetString("LastDialogPopUpSignIn", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Last response was from dialog: .
+ ///
+ internal static string LastDialogPromptMsg {
+ get {
+ return ResourceManager.GetString("LastDialogPromptMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Quiz1 Dialog.
+ ///
+ internal static string LastDialogQuiz1Dialog {
+ get {
+ return ResourceManager.GetString("LastDialogQuiz1Dialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Quiz2 Dialog.
+ ///
+ internal static string LastDialogQuiz2Dialog {
+ get {
+ return ResourceManager.GetString("LastDialogQuiz2Dialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Quiz Dialog.
+ ///
+ internal static string LastDialogQuizDialog {
+ get {
+ return ResourceManager.GetString("LastDialogQuizDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Send 1:1 Dialog.
+ ///
+ internal static string LastDialogSend1on1Dialog {
+ get {
+ return ResourceManager.GetString("LastDialogSend1on1Dialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to SetupTextMessageDialog.
+ ///
+ internal static string LastDialogSetupMessasge {
+ get {
+ return ResourceManager.GetString("LastDialogSetupMessasge", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to SetupUpdateCardMsgDialog.
+ ///
+ internal static string LastDialogSetupUpdateCard {
+ get {
+ return ResourceManager.GetString("LastDialogSetupUpdateCard", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to ThumbnailcardDailog.
+ ///
+ internal static string LastDialogThumbnailCard {
+ get {
+ return ResourceManager.GetString("LastDialogThumbnailCard", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to UpdateLastTextMessageDialog.
+ ///
+ internal static string LastDialogUpdateMessasge {
+ get {
+ return ResourceManager.GetString("LastDialogUpdateMessasge", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to VSTSAuthDialog.
+ ///
+ internal static string LastDialogVSTSDialog {
+ get {
+ return ResourceManager.GetString("LastDialogVSTSDialog", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Here is Local Time - .
+ ///
+ internal static string LocalTimeZonePrompt {
+ get {
+ return ResourceManager.GetString("LocalTimeZonePrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to initialRun.
+ ///
+ internal static string manifestInitialRun {
+ get {
+ return ResourceManager.GetString("manifestInitialRun", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to query.
+ ///
+ internal static string manifestParameterName {
+ get {
+ return ResourceManager.GetString("manifestParameterName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to message.
+ ///
+ internal static string MessageActivity {
+ get {
+ return ResourceManager.GetString("MessageActivity", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Message Back.
+ ///
+ internal static string MessageBackCardButtonCaption {
+ get {
+ return ResourceManager.GetString("MessageBackCardButtonCaption", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This is Displayed Text for Message Back.
+ ///
+ internal static string MessageBackDisplayedText {
+ get {
+ return ResourceManager.GetString("MessageBackDisplayedText", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This is Message Back PayLoad Text..
+ ///
+ internal static string MessageBackPayloadText {
+ get {
+ return ResourceManager.GetString("MessageBackPayloadText", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This is Message Back example.
+ ///
+ internal static string MessageBackTitleMsg {
+ get {
+ return ResourceManager.GetString("MessageBackTitleMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Multi Dialog Card Sub Title..
+ ///
+ internal static string MultiDialogCardSubTitle {
+ get {
+ return ResourceManager.GetString("MultiDialogCardSubTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Multi Dialog Card Text.
+ ///
+ internal static string MultiDialogCardText {
+ get {
+ return ResourceManager.GetString("MultiDialogCardText", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Multi Dialog Card Title..
+ ///
+ internal static string MultiDialogCardTitle {
+ get {
+ return ResourceManager.GetString("MultiDialogCardTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to is Null.
+ ///
+ internal static string NullException {
+ get {
+ return ResourceManager.GetString("NullException", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This is the text1.
+ ///
+ internal static string O365V1Section1 {
+ get {
+ return ResourceManager.GetString("O365V1Section1", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This is the text2.
+ ///
+ internal static string O365V1Section2 {
+ get {
+ return ResourceManager.GetString("O365V1Section2", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Title.
+ ///
+ internal static string O365V1Title {
+ get {
+ return ResourceManager.GetString("O365V1Title", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Batch upload for TAX data on db-srv-hr1 aborted due to timeout. (ref324).
+ ///
+ internal static string O365V2ActivityTitle {
+ get {
+ return ResourceManager.GetString("O365V2ActivityTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Receive Time.
+ ///
+ internal static string O365V2Fact1Key {
+ get {
+ return ResourceManager.GetString("O365V2Fact1Key", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 2016-05-30T16:50:02.503Z.
+ ///
+ internal static string O365V2Fact1Value {
+ get {
+ return ResourceManager.GetString("O365V2Fact1Value", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Node.
+ ///
+ internal static string O365V2Fact2Key {
+ get {
+ return ResourceManager.GetString("O365V2Fact2Key", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to omi10svr.
+ ///
+ internal static string O365V2Fact2Value {
+ get {
+ return ResourceManager.GetString("O365V2Fact2Value", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Category.
+ ///
+ internal static string O365V2Fact3Key {
+ get {
+ return ResourceManager.GetString("O365V2Fact3Key", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to job.
+ ///
+ internal static string O365V2Fact3Value {
+ get {
+ return ResourceManager.GetString("O365V2Fact3Value", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Priority.
+ ///
+ internal static string O365V2Fact4Key {
+ get {
+ return ResourceManager.GetString("O365V2Fact4Key", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to medium.
+ ///
+ internal static string O365V2Fact4Value {
+ get {
+ return ResourceManager.GetString("O365V2Fact4Value", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to fe9a13.
+ ///
+ internal static string O365V2themecolor {
+ get {
+ return ResourceManager.GetString("O365V2themecolor", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to **New major event on omi10svr**.
+ ///
+ internal static string O365V2Title {
+ get {
+ return ResourceManager.GetString("O365V2Title", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 9/13/2016, 11:46am.
+ ///
+ internal static string O365V3ActivitySubtitle {
+ get {
+ return ResourceManager.GetString("O365V3ActivitySubtitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Miguel Garcia.
+ ///
+ internal static string O365V3ActivityTitle {
+ get {
+ return ResourceManager.GetString("O365V3ActivityTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Repository.
+ ///
+ internal static string O365V3Fact1Key {
+ get {
+ return ResourceManager.GetString("O365V3Fact1Key", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to mgarcia\\test.
+ ///
+ internal static string O365V3Fact1Value {
+ get {
+ return ResourceManager.GetString("O365V3Fact1Value", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Issue #:.
+ ///
+ internal static string O365V3Fact2Key {
+ get {
+ return ResourceManager.GetString("O365V3Fact2Key", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 176715375.
+ ///
+ internal static string O365V3Fact2Value {
+ get {
+ return ResourceManager.GetString("O365V3Fact2Value", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to http://connectorsdemo.azurewebsites.net/images/MSC12_Oscar_002.jpg.
+ ///
+ internal static string O365V3ImageUrl {
+ get {
+ return ResourceManager.GetString("O365V3ImageUrl", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Issue 176715375.
+ ///
+ internal static string O365V3Summary {
+ get {
+ return ResourceManager.GetString("O365V3Summary", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to There is a problem with Push notifications, they don't seem to be picked up by the connector..
+ ///
+ internal static string O365V3Text {
+ get {
+ return ResourceManager.GetString("O365V3Text", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 0078D7.
+ ///
+ internal static string O365V3ThemeColor {
+ get {
+ return ResourceManager.GetString("O365V3ThemeColor", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Issue opened: Push notifications not working.
+ ///
+ internal static string O365V3Title {
+ get {
+ return ResourceManager.GetString("O365V3Title", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Please paste 12345 magic number in Bot to validate.
+ ///
+ internal static string OAuthCallbackMessage {
+ get {
+ return ResourceManager.GetString("OAuthCallbackMessage", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Please copy and paste the number returned after logging in..
+ ///
+ internal static string OAuthCallbackUserPrompt {
+ get {
+ return ResourceManager.GetString("OAuthCallbackUserPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to no.
+ ///
+ internal static string OptionNo {
+ get {
+ return ResourceManager.GetString("OptionNo", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to yes.
+ ///
+ internal static string OptionYes {
+ get {
+ return ResourceManager.GetString("OptionYes", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to payload roster.
+ ///
+ internal static string payloadrosterOptionValue {
+ get {
+ return ResourceManager.GetString("payloadrosterOptionValue", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Hi! Nice to meet you .
+ ///
+ internal static string PlayGameAnswerForName {
+ get {
+ return ResourceManager.GetString("PlayGameAnswerForName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to choice1.
+ ///
+ internal static string PlayGameChoice1 {
+ get {
+ return ResourceManager.GetString("PlayGameChoice1", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to choice2.
+ ///
+ internal static string PlayGameChoice2 {
+ get {
+ return ResourceManager.GetString("PlayGameChoice2", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Awwww man! I'm still in the prototype phase..
+ ///
+ internal static string PlayGameFailMsg {
+ get {
+ return ResourceManager.GetString("PlayGameFailMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Hi! I'm a bot. What is your name?.
+ ///
+ internal static string PlayGamePromptForName {
+ get {
+ return ResourceManager.GetString("PlayGamePromptForName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Did you pick,.
+ ///
+ internal static string PlayGameReplyMsg {
+ get {
+ return ResourceManager.GetString("PlayGameReplyMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Let's play a game! You pick a button, and I will repeat it..
+ ///
+ internal static string PlayGameStartMsg {
+ get {
+ return ResourceManager.GetString("PlayGameStartMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Yay!!!! What a fun game!.
+ ///
+ internal static string PlayGameThanksMsg {
+ get {
+ return ResourceManager.GetString("PlayGameThanksMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Wrong Choice.
+ ///
+ internal static string PlayGameWrongChoice {
+ get {
+ return ResourceManager.GetString("PlayGameWrongChoice", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Sign In.
+ ///
+ internal static string PopUpSignInCardButtonTitle {
+ get {
+ return ResourceManager.GetString("PopUpSignInCardButtonTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Please click below for Popup Sign-In experience.
+ ///
+ internal static string PopUpSignInCardTitle {
+ get {
+ return ResourceManager.GetString("PopUpSignInCardTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Ooops, what you choose is not a valid option, please try again!!.
+ ///
+ internal static string PromptInvalidMsg {
+ get {
+ return ResourceManager.GetString("PromptInvalidMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Question 1.
+ ///
+ internal static string Quiz1Question {
+ get {
+ return ResourceManager.GetString("Quiz1Question", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Thanks for Completing Quiz 1.
+ ///
+ internal static string Quiz1ThanksTitleMsg {
+ get {
+ return ResourceManager.GetString("Quiz1ThanksTitleMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Question 2.
+ ///
+ internal static string Quiz2Question {
+ get {
+ return ResourceManager.GetString("Quiz2Question", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Wrong Choice.
+ ///
+ internal static string QuizAnswerNo {
+ get {
+ return ResourceManager.GetString("QuizAnswerNo", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to You are Right.
+ ///
+ internal static string QuizAnswerYes {
+ get {
+ return ResourceManager.GetString("QuizAnswerYes", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Thanks for Playing Fun Quiz!!.
+ ///
+ internal static string QuizThanksTitleMsg {
+ get {
+ return ResourceManager.GetString("QuizThanksTitleMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Hi, Welcome to the Fun Quiz. Let's get started...
+ ///
+ internal static string QuizTitleWelcomeMsg {
+ get {
+ return ResourceManager.GetString("QuizTitleWelcomeMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Here are the User Information.
+ ///
+ internal static string RosterTitle {
+ get {
+ return ResourceManager.GetString("RosterTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Processing the Request for Roster Api User Information!!.
+ ///
+ internal static string RosterWelcomeMsgTitle {
+ get {
+ return ResourceManager.GetString("RosterWelcomeMsgTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 1:1 Message sent.
+ ///
+ internal static string Send1on1ConfirmMsg {
+ get {
+ return ResourceManager.GetString("Send1on1ConfirmMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Hey! I am Bot, How's going!!.
+ ///
+ internal static string Send1on1Prompt {
+ get {
+ return ResourceManager.GetString("Send1on1Prompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Message set to be updated.
+ ///
+ internal static string SetupMessagePrompt {
+ get {
+ return ResourceManager.GetString("SetupMessagePrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to SetUpMsgKey.
+ ///
+ internal static string SetUpMsgKey {
+ get {
+ return ResourceManager.GetString("SetUpMsgKey", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to #PleaseSetTenantInformation.
+ ///
+ internal static string TenantConfigStaticValue {
+ get {
+ return ResourceManager.GetString("TenantConfigStaticValue", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to MS Teams: Attempted access from a different Office 365 tenant: message rejected.
+ ///
+ internal static string TenantLevelDeniedAccess {
+ get {
+ return ResourceManager.GetString("TenantLevelDeniedAccess", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Thanks for searching the Roster Api..
+ ///
+ internal static string ThanksRosterTitleMsg {
+ get {
+ return ResourceManager.GetString("ThanksRosterTitleMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Get Started.
+ ///
+ internal static string ThumbnailCardButtonCaption {
+ get {
+ return ResourceManager.GetString("ThumbnailCardButtonCaption", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg.
+ ///
+ internal static string ThumbnailCardImageUrl {
+ get {
+ return ResourceManager.GetString("ThumbnailCardImageUrl", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Your bots — wherever your users are talking.
+ ///
+ internal static string ThumbnailCardSubTitle {
+ get {
+ return ResourceManager.GetString("ThumbnailCardSubTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Build and connect intelligent bots to interact with your users naturally wherever they are, from text/sms to Skype, Slack, Office 365 mail and other popular services..
+ ///
+ internal static string ThumbnailCardTextMsg {
+ get {
+ return ResourceManager.GetString("ThumbnailCardTextMsg", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to BotFramework Thumbnail Card.
+ ///
+ internal static string ThumbnailCardTitle {
+ get {
+ return ResourceManager.GetString("ThumbnailCardTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Card updated - see above.
+ ///
+ internal static string UpdateCardMessageConfirmation {
+ get {
+ return ResourceManager.GetString("UpdateCardMessageConfirmation", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Message updated - see above.
+ ///
+ internal static string UpdateMessageConfirmation {
+ get {
+ return ResourceManager.GetString("UpdateMessageConfirmation", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This message has been updated.
+ ///
+ internal static string UpdateMessagePrompt {
+ get {
+ return ResourceManager.GetString("UpdateMessagePrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Here is UTC Time -.
+ ///
+ internal static string UTCTimeZonePrompt {
+ get {
+ return ResourceManager.GetString("UTCTimeZonePrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Issue:.
+ ///
+ internal static string VSTSApiIssue {
+ get {
+ return ResourceManager.GetString("VSTSApiIssue", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Request Issue:.
+ ///
+ internal static string VSTSApiRequestError {
+ get {
+ return ResourceManager.GetString("VSTSApiRequestError", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to VSTS Auth.
+ ///
+ internal static string VSTSAuthCardCaption {
+ get {
+ return ResourceManager.GetString("VSTSAuthCardCaption", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to vstslogin.
+ ///
+ internal static string VSTSAuthCardValue {
+ get {
+ return ResourceManager.GetString("VSTSAuthCardValue", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to VSTSAuthToken.
+ ///
+ internal static string VSTSAuthTokenKey {
+ get {
+ return ResourceManager.GetString("VSTSAuthTokenKey", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to There is some internal error!!.
+ ///
+ internal static string VSTSCallbackAuthError {
+ get {
+ return ResourceManager.GetString("VSTSCallbackAuthError", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Go to Work Item.
+ ///
+ internal static string VSTSGetWorkItemCardButtonCaption {
+ get {
+ return ResourceManager.GetString("VSTSGetWorkItemCardButtonCaption", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to I'm sorry. In order to use this functionality you must log in..
+ ///
+ internal static string VSTSGetWorkItemLoginPrompt {
+ get {
+ return ResourceManager.GetString("VSTSGetWorkItemLoginPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to What is the id of the work item you are looking for?.
+ ///
+ internal static string VSTSGetWorkItemPrompt {
+ get {
+ return ResourceManager.GetString("VSTSGetWorkItemPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Login to VSTS!.
+ ///
+ internal static string VSTSLoginCardButtonCaption {
+ get {
+ return ResourceManager.GetString("VSTSLoginCardButtonCaption", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to You need to authorize me.
+ ///
+ internal static string VSTSLoginCardTitle {
+ get {
+ return ResourceManager.GetString("VSTSLoginCardTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to You are already logged in VSTS, Enjoy your login session!!.
+ ///
+ internal static string VSTSLoginSessionExistsPrompt {
+ get {
+ return ResourceManager.GetString("VSTSLoginSessionExistsPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to You are successfully logged-in!!.
+ ///
+ internal static string VSTSLoginSuccessPrompt {
+ get {
+ return ResourceManager.GetString("VSTSLoginSuccessPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Please login in using this card.
+ ///
+ internal static string VSTSLoginTitle {
+ get {
+ return ResourceManager.GetString("VSTSLoginTitle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to To logged out from VSTS, use command 'vstslogout'.
+ ///
+ internal static string VSTSlogoutPrompt {
+ get {
+ return ResourceManager.GetString("VSTSlogoutPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to To login again, use command 'vstslogin'!.
+ ///
+ internal static string VSTSSuccessfulLogoutLoginPrompt {
+ get {
+ return ResourceManager.GetString("VSTSSuccessfulLogoutLoginPrompt", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to You are logged out from VSTS acount!.
+ ///
+ internal static string VSTSSuccessfulLogoutPrompt {
+ get {
+ return ResourceManager.GetString("VSTSSuccessfulLogoutPrompt", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Properties/Strings.resx b/Source/Microsoft.Teams.Apps.QBot.Bot/Properties/Strings.resx
new file mode 100644
index 0000000..d8224ad
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Properties/Strings.resx
@@ -0,0 +1,798 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Wrong Choice
+
+
+ You are Right
+
+
+ At Mention
+
+
+ choice1
+
+
+ choice2
+
+
+ Dialog Flow
+
+
+ This is step1 in Root Dialog
+
+
+ This is step2 in Root Dialog
+
+
+ This is step3 in Root Dialog After triggering the Hello Dialog
+
+
+ Fetch Members
+
+
+ names
+
+
+ Template Options
+
+
+ no
+
+
+ yes
+
+
+ payload roster
+
+
+ Play Game
+
+
+ Awwww man! I'm still in the prototype phase.
+
+
+ Ooops, what you choose is not a valid option, please try again!!
+
+
+ Did you pick,
+
+
+ Let's play a game! You pick a button, and I will repeat it.
+
+
+ Yay!!!! What a fun game!
+
+
+ Hi! I'm a bot. What is your name?
+
+
+ Hi! Nice to meet you
+
+
+ Question 1
+
+
+ Question 2
+
+
+ Thanks for Completing Quiz 1
+
+
+ quiz
+
+
+ Thanks for Playing Fun Quiz!!
+
+
+ Hi, Welcome to the Fun Quiz. Let's get started..
+
+
+ Fetch Roster Payload
+
+
+ roster
+
+
+ Here are the User Information
+
+
+ Processing the Request for Roster Api User Information!!
+
+
+ at mention
+
+
+ dialog flow
+
+
+ prompt
+
+
+ RunQuiz
+
+
+ hi
+
+
+ This is Hello Dialog
+
+
+ Thanks for searching the Roster Api.
+
+
+ Hello Dialog
+
+
+ Wrong Choice
+
+
+ is Null
+
+
+ Chat
+
+
+ Invoke Hello Dialog
+
+
+ Invoke Multi Dialog
+
+
+ last dialog
+
+
+ multi dialog 1
+
+
+ multi dialog 2
+
+
+ send message to 1:1
+
+
+ Fetch Last Dialog
+
+
+ Begin Multi Dailog 1
+
+
+ Begin Multi Dialog 2
+
+
+ Send 1:1 Message
+
+
+ AtMentionDialog
+
+
+ BeginDialog
+
+
+ Error finding last executed dialog
+
+
+ FetchPayloadRosterDialog
+
+
+ FetchRosterDialog
+
+
+ GameDialog
+
+
+ HelpDialog
+
+
+ DialogId
+
+
+ MultiDialog1
+
+
+ MultiDialog2
+
+
+ Last response was from dialog:
+
+
+ Quiz1 Dialog
+
+
+ Quiz2 Dialog
+
+
+ Quiz Dialog
+
+
+ Multi Dialog Card Sub Title.
+
+
+ Multi Dialog Card Text
+
+
+ Multi Dialog Card Title.
+
+
+ setup text message
+
+
+ update text message
+
+
+ There is some error updating last message
+
+
+ Setup Message
+
+
+ Update Message
+
+
+ Send 1:1 Dialog
+
+
+ SetupTextMessageDialog
+
+
+ UpdateLastTextMessageDialog
+
+
+ 1:1 Message sent
+
+
+ Hey! I am Bot, How's going!!
+
+
+ Message set to be updated
+
+
+ SetUpMsgKey
+
+
+ Message updated - see above
+
+
+ This message has been updated
+
+
+ Card updated - see above
+
+
+ SetupUpdateCardMsgDialog
+
+
+ FetchLastDialogName
+
+
+ update card message
+
+
+ Update Card
+
+
+ HelloDialog
+
+
+ display cards
+
+
+ no
+
+
+ Hero Card
+
+
+ ConnectorCardV1
+
+
+ ConnectorCardV2
+
+
+ ConnectorCardV3
+
+
+ What card you would like to test?
+
+
+ Do you want to test another card?
+
+
+ Hope you liked the Cards!!
+
+
+ Thumbnail Card
+
+
+ Choose Cards
+
+
+ deep link
+
+
+ Static Tab Deep Link
+
+
+ Please click below to navigate static tab
+
+
+ Tab Example
+
+
+ Please Clicked below any OAuth 2.0 Samples (Bot Command - "auth")
+
+
+ auth
+
+
+ Config Tab Deep Link
+
+
+ Please click below to navigate config tab
+
+
+ Facebook Auth
+
+
+ fblogin
+
+
+ Auth Sample
+
+
+ Please paste 12345 magic number in Bot to validate
+
+
+ Please copy and paste the number returned after logging in.
+
+
+ VSTS Auth
+
+
+ vstslogin
+
+
+ To logged out from Facebook, use command 'fblogout'
+
+
+ You are logged in as:
+
+
+ Cannot resume!
+
+
+ Unable to deserialize the Facebook response.
+
+
+ Entered numbered is not valid!, please login again.
+
+
+ Go to User Profile
+
+
+ Login to Facebook!
+
+
+ You need to authorize me
+
+
+ You are already logged in, Enjoy your login session!!
+
+
+ Please login in using this card
+
+
+ To logged out from Facebook, use command 'fblogout'
+
+
+ message
+
+
+ VSTSAuthToken
+
+
+ There is some internal error!!
+
+
+ Failed with message:
+
+
+ To login again, use command 'fblogin'!
+
+
+ You are logged out from Facebook acount!
+
+
+ Get Started
+
+
+ https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg
+
+
+ Your bots — wherever your users are talking
+
+
+ Build and connect intelligent bots to interact with your users naturally wherever they are, from text/sms to Skype, Slack, Office 365 mail and other popular services.
+
+
+ BotFramework Hero Card
+
+
+ SimpleFacebookAuthDialog
+
+
+ VSTSAuthDialog
+
+
+ This is the text1
+
+
+ This is the text2
+
+
+ Title
+
+
+ Batch upload for TAX data on db-srv-hr1 aborted due to timeout. (ref324)
+
+
+ Receive Time
+
+
+ 2016-05-30T16:50:02.503Z
+
+
+ Node
+
+
+ omi10svr
+
+
+ Category
+
+
+ job
+
+
+ Priority
+
+
+ medium
+
+
+ fe9a13
+
+
+ **New major event on omi10svr**
+
+
+ 9/13/2016, 11:46am
+
+
+ Miguel Garcia
+
+
+ Repository
+
+
+ mgarcia\\test
+
+
+ Issue #:
+
+
+ 176715375
+
+
+ http://connectorsdemo.azurewebsites.net/images/MSC12_Oscar_002.jpg
+
+
+ Issue 176715375
+
+
+ There is a problem with Push notifications, they don't seem to be picked up by the connector.
+
+
+ 0078D7
+
+
+ Issue opened: Push notifications not working
+
+
+ Get Started
+
+
+ https://sec.ch9.ms/ch9/7ff5/e07cfef0-aa3b-40bb-9baa-7c9ef8ff7ff5/buildreactionbotframework_960.jpg
+
+
+ Your bots — wherever your users are talking
+
+
+ Build and connect intelligent bots to interact with your users naturally wherever they are, from text/sms to Skype, Slack, Office 365 mail and other popular services.
+
+
+ BotFramework Thumbnail Card
+
+
+ Issue:
+
+
+ Request Issue:
+
+
+ Go to Work Item
+
+
+ I'm sorry. In order to use this functionality you must log in.
+
+
+ What is the id of the work item you are looking for?
+
+
+ Login to VSTS!
+
+
+ You need to authorize me
+
+
+ You are already logged in VSTS, Enjoy your login session!!
+
+
+ You are successfully logged-in!!
+
+
+ Please login in using this card
+
+
+ To logged out from VSTS, use command 'vstslogout'
+
+
+ To login again, use command 'vstslogin'!
+
+
+ You are logged out from VSTS acount!
+
+
+ O365ConnectorCardDailog
+
+
+ DeepLinkStaticTabDialog
+
+
+ DisplayCardsDialog
+
+
+ HeroCardDialog
+
+
+ ThumbnailcardDailog
+
+
+ localtime
+
+
+ msgback
+
+
+ Local Time
+
+
+ Message Back Dailog
+
+
+ Here is Local Time -
+
+
+ Message Back
+
+
+ This is Displayed Text for Message Back
+
+
+ This is Message Back PayLoad Text.
+
+
+ Here is UTC Time -
+
+
+ composeExtensionCardType
+
+
+ This Compose Extension is used as Compose Extension Sample. To change your settings either enter the work 'settings' or change your settings on the settings menu option.To reset your configuration, simply enter the word 'reset'.
+
+
+ ERROR: No user data
+
+
+ reset
+
+
+ Your compose extension state has been reset.
+
+
+ setting
+
+
+ settings
+
+
+ initialRun
+
+
+ query
+
+
+ composeextension/querysettingurl
+
+
+ Connector Card Actions
+
+
+ Actionable Card
+
+
+ ActionableMessageCardDialog
+
+
+ ConnectorCardV1Dialog
+
+
+ ConnectorCardV2Dialog
+
+
+ ConnectorCardV3Dialog
+
+
+ MS Teams: Attempted access from a different Office 365 tenant: message rejected
+
+
+ Connector Card Actions V2
+
+
+ PopUpSignInDialog
+
+
+ signin
+
+
+ Popup Sign-In
+
+
+ Sign In
+
+
+ Please click below for Popup Sign-In experience
+
+
+ msgback
+
+
+ Message Back
+
+
+ This is Message Back example
+
+
+ #PleaseSetTenantInformation
+
+
+ invokeKey
+
+
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Resources/strings.Designer.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Resources/strings.Designer.cs
new file mode 100644
index 0000000..aa7244f
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Resources/strings.Designer.cs
@@ -0,0 +1,72 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Resources {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class strings {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal strings() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Teams.Apps.QBot.Bot.Resources.strings", typeof(strings).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Tag Teaching Staff.
+ ///
+ internal static string TagAdmins {
+ get {
+ return ResourceManager.GetString("TagAdmins", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Resources/strings.resx b/Source/Microsoft.Teams.Apps.QBot.Bot/Resources/strings.resx
new file mode 100644
index 0000000..16a185d
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Resources/strings.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Tag Teaching Staff
+
+
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Services/AuthService.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/AuthService.cs
new file mode 100644
index 0000000..51538bd
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/AuthService.cs
@@ -0,0 +1,50 @@
+using Microsoft.IdentityModel.Clients.ActiveDirectory;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Web;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Services
+{
+ public class AuthService
+ {
+ private AuthenticationContext context = null;
+ private AuthenticationResult result = null;
+
+ public AuthService(string authority)
+ {
+ context = new AuthenticationContext(authority);
+ }
+
+ public async Task AuthenticateSilently(string resource)
+ {
+ // Try get token silently
+ try
+ {
+ result = await context.AcquireTokenSilentAsync(resource, ServiceHelper.AppId);
+ }
+ catch (Exception e)
+ {
+ result = null;
+ }
+
+ if (result == null)
+ {
+ // Try with credentials
+ try
+ {
+ var uc = new UserPasswordCredential(ServiceHelper.ServiceAccountName, ServiceHelper.ServiceAccountPassword);
+ //var cc = new ClientCredential(ServiceHelper.AppId, ServiceHelper.AppSecret);
+ result = await context.AcquireTokenAsync(resource, ServiceHelper.ClientId, uc);
+ }
+ catch (Exception e)
+ {
+ result = null;
+ }
+ }
+
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Services/BotJwtRefreshWorker.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/BotJwtRefreshWorker.cs
new file mode 100644
index 0000000..99d8cfd
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/BotJwtRefreshWorker.cs
@@ -0,0 +1,51 @@
+using Microsoft.Bot.Connector;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Web;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Services
+{
+ sealed class BotJwtRefreshWorker : IDisposable
+ {
+ CancellationTokenSource _Cts = new CancellationTokenSource();
+
+ public BotJwtRefreshWorker()
+ {
+ var appID = ServiceHelper.AppId;
+ var appPassword = ServiceHelper.AppSecret;
+ if (!string.IsNullOrEmpty(appID) && !string.IsNullOrEmpty(appPassword))
+ {
+ var credentials = new MicrosoftAppCredentials(appID, appPassword);
+ Task.Factory.StartNew(
+ async () =>
+ {
+ var ct = _Cts.Token;
+ while (!ct.IsCancellationRequested)
+ {
+ try
+ {
+ // GetTokenAsync method internally calls RefreshAndStoreToken, meaning that the token will automatically be cached at this point and you don’t need to do anything else – the bot will always have a valid token.
+ await credentials.GetTokenAsync().ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ Trace.TraceError(ex.ToString());
+ }
+ await Task.Delay(TimeSpan.FromMinutes(30), ct).ConfigureAwait(false);
+ }
+ },
+ TaskCreationOptions.LongRunning);
+ }
+ }
+
+ public void Dispose()
+ {
+ _Cts.Cancel();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Services/Constants.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/Constants.cs
new file mode 100644
index 0000000..2e0fc3b
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/Constants.cs
@@ -0,0 +1,31 @@
+namespace Microsoft.Teams.Apps.QBot.Bot.Services
+{
+ public static class Constants
+ {
+ public const string STUDENT_ROLE = "Student";
+ public const string LECTURER_ROLE = "Lecturer";
+ public const string DEMONSTRATOR_ROLE = "Demonstrator";
+
+ public const string QUESTION_STATUS_ANSWERED = "answered";
+ public const string QUESTION_STATUS_UNANSWERED = "unanswered";
+
+ public const string ACTIVITY_SELECT_ANSWER = "SelectAnswer";
+ public const string ACTIVITY_MARKED_ANSWERED = "MarkedAnswered";
+ public const string ACTIVITY_BOT_HELPFUL = "BotHelpful";
+ public const string ACTIVITY_BOT_NOT_HELPFUL = "BotUnhelpful";
+
+ public const string QNA_HOST_KEY = "QnAServiceHostName";
+ public const string QNA_ID_KEY = "QnAknowledgeBaseId";
+ public const string QNA_ENDPOINT_KEY = "QnAEndpointKey";
+ public const string BOT_ID_KEY = "BotId";
+ public const string BASE_URL_KEY = "BaseUrl";
+ public const string BOT_APPID_KEY = "MicrosoftAppId";
+ public const string BOT_APPPASSWORD_KEY = "MicrosoftAppPassword";
+ public const string AAD_AUTHORITY_KEY = "AADAuthority";
+ public const string AAD_GRAPHRESOURCE_KEY = "AADGraphResource";
+ public const string SERVICE_ACCOUNT_KEY = "AADServiceName";
+ public const string SERVICE_ACCOUNT_PASSWORD_KEY = "AADServicePassword";
+ public const string AAD_GRAPHROOT_KEY = "AADGraphRoot";
+ public const string AAD_CLIENTID_KEY = "AADClientId";
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Services/GraphService.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/GraphService.cs
new file mode 100644
index 0000000..631b494
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/GraphService.cs
@@ -0,0 +1,358 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Threading.Tasks;
+using System.Web;
+using Newtonsoft;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Microsoft.Teams.Apps.QBot.Model;
+using Microsoft.Teams.Apps.QBot.Model.Graph;
+using Microsoft.Teams.Apps.QBot.Model.Teams;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Services
+{
+ public class GraphService
+ {
+
+ public async Task GetProfilePhoto(string accessToken, string userPrincipalName)
+ {
+ string endpoint = ServiceHelper.GraphRootUri + @"/v1.0";
+ string queryParameter = @"users/" + userPrincipalName + @"/photo/$value";
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint + queryParameter, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ var stream = await response.Content.ReadAsStreamAsync();
+ byte[] bytes = new byte[stream.Length];
+ stream.Read(bytes, 0, (int)stream.Length);
+ return bytes;
+ }
+ return null;
+ }
+
+
+ public async Task GetGroupPhoto(string accessToken, string groupId)
+ {
+ string endpoint = ServiceHelper.GraphRootUri + @"/v1.0";
+ string queryParameter = @"/groups/" + groupId + @"/photo/$value";
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint + queryParameter, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ var stream = await response.Content.ReadAsStreamAsync();
+ byte[] bytes = new byte[stream.Length];
+ stream.Read(bytes, 0, (int)stream.Length);
+ return bytes;
+ }
+ return null;
+ }
+
+
+ public async Task GetMessage(string accessToken, string teamId, string channelId, string messageId)
+ {
+ try
+ {
+ string endpoint = ServiceHelper.GraphRootUri + @"/beta";
+ string queryParameter = "/teams/" + teamId + "/channels/" + channelId + "/messages/" + messageId;
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint + queryParameter, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ var jsonString = await response.Content.ReadAsStringAsync();
+ var teamsMessage = JsonConvert.DeserializeObject(jsonString);
+ return teamsMessage;
+ }
+ return null;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public async Task> GetRepliesToMessage(string accessToken, string teamId, string channelId, string messageId)
+ {
+ try
+ {
+ string endpoint = ServiceHelper.GraphRootUri + @"/beta";
+ string queryParameter = "/teams/" + teamId + "/channels/" + channelId + "/messages/" + messageId + "/replies";
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint + queryParameter, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ var jsonString = await response.Content.ReadAsStringAsync();
+ var teamsMessageGraphResult = JsonConvert.DeserializeObject(jsonString);
+ var teamsMessages = teamsMessageGraphResult.TeamsMesages;
+ return teamsMessages;
+ }
+ return null;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public async Task> GetChannels(string accessToken, string groupId)
+ {
+ try
+ {
+ string endpoint = ServiceHelper.GraphRootUri + @"/beta";
+ string queryParameter = "/groups/" + groupId + "/channels";
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint + queryParameter, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ var jsonString = await response.Content.ReadAsStringAsync();
+ var teamsChannelResult = JsonConvert.DeserializeObject(jsonString);
+ return teamsChannelResult.TeamChannels;
+ }
+ return null;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public async Task GetTeamGroupSPUrl(string accessToken, string groupId)
+ {
+ try
+ {
+ string endpoint = ServiceHelper.GraphRootUri + @"/v1.0";
+ string queryParameter = "/groups/" + groupId + "/sites/root";
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint + queryParameter, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ var jsonString = await response.Content.ReadAsStringAsync();
+ var teamsSPSiteResult = JsonConvert.DeserializeObject(jsonString);
+
+
+ string endpoint2 = ServiceHelper.GraphRootUri + @"/v1.0";
+ string queryParameter2 = "/groups/" + groupId;
+ HttpResponseMessage response2 = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint2 + queryParameter2, accessToken);
+ if (response2 != null && response2.IsSuccessStatusCode)
+ {
+ var jsonString2 = await response2.Content.ReadAsStringAsync();
+ dynamic teamsObject = JsonConvert.DeserializeObject(jsonString2);
+ string teamsDisplayName = teamsObject.displayName;
+
+ teamsSPSiteResult.DisplayName = teamsDisplayName;
+ }
+ return teamsSPSiteResult;
+ }
+ return null;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// Queries Graph API and returns a list of O365 Group IDs for which the given user is a member of
+ ///
+ /// Access Token
+ /// Username
+ /// A representing the result of the asynchronous operation.
+ public async Task> GetGroupMemberOf(string accessToken, string upn)
+ {
+ try
+ {
+ string endpoint = ServiceHelper.GraphRootUri + @"/v1.0";
+ string queryParameter = "/users/" + upn + "/memberOf?$select=id";
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint + queryParameter, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ var jsonString = await response.Content.ReadAsStringAsync();
+ var groupMemberOfResult = JsonConvert.DeserializeObject(jsonString);
+
+ return groupMemberOfResult.Items.Select(x => x.Id).ToList();
+ }
+
+ return null;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public async Task GetOwnedObjects(string accessToken, string upn)
+ {
+ try
+ {
+ string endpoint = ServiceHelper.GraphRootUri + @"/v1.0";
+ string queryParameter = "/users/" + upn + "/ownedObjects";
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint + queryParameter, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ var jsonString = await response.Content.ReadAsStringAsync();
+ return JsonConvert.DeserializeObject(jsonString);
+ //var deserializedResultDictionary = deserializedResult.Items.ToDictionary(x => x.id, x => x.displayName);
+ //return deserializedResultDictionary;
+ }
+ return null;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+
+ }
+
+ public async Task GetMembers(string accessToken, string groupId)
+ {
+ try
+ {
+ string endpoint = ServiceHelper.GraphRootUri + @"/v1.0";
+ string queryParameter = "/groups/" + groupId + "/members";
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint + queryParameter, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ var jsonString = await response.Content.ReadAsStringAsync();
+ var test = JsonConvert.DeserializeObject(jsonString);
+ return test;
+ //var deserializedResultDictionary = deserializedResult.Items.ToDictionary(x => x.id, x => x.displayName);
+ //return deserializedResultDictionary;
+ }
+ return null;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+
+ }
+
+
+
+
+ /*
+ public async Task> GetMyTeams(string accessToken)
+ {
+ string resourcePropId = @"ID :";
+
+ string endpoint = ServiceHelper.GraphRootUri + "me/joinedTeams";
+ string idPropertyName = "id";
+ string displayPropertyName = "displayName";
+
+ List items = new List();
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ items = await ServiceHelper.GetResultsItem(response, idPropertyName, displayPropertyName, resourcePropId);
+
+ }
+ return items;
+ }
+
+
+ public async Task> CreateNewTeamAndGroup(string accessToken, string groupName, string userPrincipalName)
+ {
+ Group group = new Group()
+ {
+ id = Guid.NewGuid().ToString(),
+ displayName = groupName,
+ description = groupName,
+ mailNickname = groupName.Replace(" ", ""),
+ };
+
+ // create group
+ string endpoint = ServiceHelper.GraphRootUri + "groups";
+ if (group != null)
+ {
+ group.groupTypes = new string[] { "Unified" };
+ group.mailEnabled = true;
+ group.securityEnabled = false;
+ group.visibility = "Private";
+ }
+
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Post, endpoint, accessToken, group);
+ if (!response.IsSuccessStatusCode)
+ {
+ return new Tuple(response, string.Empty);
+ }
+
+ string responseBody = await response.Content.ReadAsStringAsync(); ;
+ string groupId = responseBody.Deserialize().id;
+
+ // add me as member
+ //string me = await GetMyId(accessToken);
+
+ // add user as member
+ string me = await GetUserId(userPrincipalName, accessToken);
+ string payload = $"{{ '@odata.id': '{ServiceHelper.GraphRootUri}users/{me}' }}";
+ HttpResponseMessage responseRef = await ServiceHelper.SendRequest(HttpMethod.Post,
+ ServiceHelper.GraphRootUri + $"groups/{groupId}/members/$ref",
+ accessToken, payload);
+
+
+ // add user as OWNER
+ //HttpResponseMessage responseRef = await ServiceHelper.SendRequest(HttpMethod.Post,
+ // ServiceHelper.GraphRootUri + $"groups/{groupId}/owners/$ref",
+ // accessToken, payload);
+
+
+ if (!responseRef.IsSuccessStatusCode)
+ {
+ return new Tuple(responseRef, groupId);
+ }
+
+ // create team
+ var responseFinal = await AddTeamToGroup(groupId, accessToken);
+ return new Tuple(responseFinal, groupId);
+ }
+
+ public async Task GetSiteUrlFromGroup(string groupId, String accessToken)
+ {
+ string endpoint = ServiceHelper.GraphRootUri + @"groups/" + groupId + @"/sites/root";
+ String webUrl = "";
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ var json = JObject.Parse(await response.Content.ReadAsStringAsync());
+ webUrl = json.GetValue("webUrl").ToString();
+ }
+ return webUrl?.Trim();
+ }
+
+ public async Task GetUserId(string userPrincipalName, String accessToken)
+ {
+ string endpoint = ServiceHelper.GraphRootUri + @"users/";
+ string queryParameter = userPrincipalName;
+ String userId = "";
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint + queryParameter, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ var json = JObject.Parse(await response.Content.ReadAsStringAsync());
+ userId = json.GetValue("id").ToString();
+ }
+ return userId?.Trim();
+ }
+
+ public async Task GetMyId(String accessToken)
+ {
+ string endpoint = "https://graph.microsoft.com/v1.0/me";
+ string queryParameter = "?$select=id";
+ String userId = "";
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Get, endpoint + queryParameter, accessToken);
+ if (response != null && response.IsSuccessStatusCode)
+ {
+ var json = JObject.Parse(await response.Content.ReadAsStringAsync());
+ userId = json.GetValue("id").ToString();
+ }
+ return userId?.Trim();
+ }
+
+ public async Task AddTeamToGroup(string groupId, string accessToken)
+ {
+ string endpoint = ServiceHelper.GraphRootUri + "groups/" + groupId + "/team";
+ Team team = new TeamsPoC.Services.Models.Team();
+ team.guestSettings = new TeamsPoC.Services.Models.TeamGuestSettings() { allowCreateUpdateChannels = false, allowDeleteChannels = false };
+
+ HttpResponseMessage response = await ServiceHelper.SendRequest(HttpMethod.Put, endpoint, accessToken, team);
+ if (!response.IsSuccessStatusCode)
+ throw new Exception(response.ReasonPhrase);
+ return response;
+ }
+ */
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Services/HttpClientExtensions.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/HttpClientExtensions.cs
new file mode 100644
index 0000000..808815e
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/HttpClientExtensions.cs
@@ -0,0 +1,35 @@
+using Microsoft.AspNetCore.Html;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Net.Http;
+using System.Threading.Tasks;
+using System.Web;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Services
+{
+ public static class HttpClientExtensions
+ {
+ public static async Task PatchAsync(this HttpClient client, Uri requestUri, HttpContent iContent)
+ {
+ var method = new HttpMethod("PATCH");
+ var request = new HttpRequestMessage(method, requestUri)
+ {
+ Content = iContent
+ };
+
+ HttpResponseMessage response = new HttpResponseMessage();
+ try
+ {
+ response = await client.SendAsync(request);
+ }
+ catch (TaskCanceledException e)
+ {
+ Debug.WriteLine("ERROR: " + e.ToString());
+ }
+
+ return response;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Services/PredictiveQnAService.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/PredictiveQnAService.cs
new file mode 100644
index 0000000..fd077b5
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/PredictiveQnAService.cs
@@ -0,0 +1,214 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web;
+using Microsoft.Teams.Apps.QBot.Model;
+using Microsoft.Teams.Apps.QBot.Model.QnA;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Services
+{
+ ///
+ /// QnAMakerService is a wrapper over the QnA Maker REST endpoint
+ ///
+ [Serializable]
+ public class PredictiveQnAService
+ {
+ private string _predictiveQnAServiceHostName;
+ private string _predictiveKnowledgeBaseId;
+ private string _predictiveEndpointKey;
+ private string _predictiveQnAKnowledgeBaseName;
+ private string _predictiveQnAHttpEndpoint;
+ private string _predictiveQnAHttpKey;
+
+ ///
+ /// Initializes a new instance of the class.
+ /// Initialize a particular endpoint with it's details
+ ///
+ public PredictiveQnAService(int courseID)
+ {
+
+ var course = SQLService.GetCourse(courseID);
+ _predictiveQnAServiceHostName = course.PredictiveQnAServiceHost;
+ _predictiveKnowledgeBaseId = course.PredictiveQnAKnowledgeBaseId;
+ _predictiveEndpointKey = course.PredictiveQnAEndpointKey;
+ _predictiveQnAKnowledgeBaseName = course.PredictiveQnAKnowledgeBaseName;
+ _predictiveQnAHttpEndpoint = course.PredictiveQnAHttpEndpoint;
+ _predictiveQnAHttpKey = course.PredictiveQnAHttpKey;
+ }
+
+ ///
+ /// Call the QnA Maker endpoint and get a response
+ ///
+ /// User question
+ ///
+ public async Task GetAnswer(string query)
+ {
+ var qnaResponse = new QnAResponse();
+
+ using (HttpClient client = new HttpClient())
+ {
+ string requestUri = string.Format(
+ "{0}{1}{2}{3}",
+ _predictiveQnAServiceHostName,
+ @"knowledgebases/",
+ _predictiveKnowledgeBaseId,
+ @"/generateAnswer");
+
+ var httpContent = new StringContent("{\"question\": \"" + query + "\"}}", Encoding.UTF8, "application/json");
+
+ client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("EndpointKey", _predictiveEndpointKey);
+
+ var msg = await client.PostAsync(requestUri, httpContent);
+
+ if (msg.IsSuccessStatusCode)
+ {
+ var jsonDataResponse = await msg.Content.ReadAsStringAsync();
+ qnaResponse = JsonConvert.DeserializeObject(jsonDataResponse);
+ }
+ }
+
+ if (qnaResponse != null && qnaResponse.Answers != null && qnaResponse.Answers.Count > 0)
+ {
+ return qnaResponse.Answers.FirstOrDefault();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+
+ public async Task PublishQnA()
+ {
+ using (HttpClient client = new HttpClient())
+ {
+ string requestUri = string.Format(
+ "{0}{1}{2}",
+ _predictiveQnAHttpEndpoint,
+ @"knowledgebases/",
+ _predictiveKnowledgeBaseId);
+
+ var httpContent = new StringContent(string.Empty, Encoding.UTF8, "application/json");
+
+ client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", _predictiveQnAHttpKey);
+
+ var msg = await client.PostAsync(new Uri(requestUri), httpContent);
+
+ if (msg.IsSuccessStatusCode)
+ {
+ return true;
+ }
+ }
+
+ return false;
+
+ }
+
+ public async Task PatchQnA(QnAPayload payload)
+ {
+ using (HttpClient client = new HttpClient())
+ {
+ string requestUri = string.Format(
+ "{0}{1}{2}",
+ _predictiveQnAHttpEndpoint,
+ @"knowledgebases/",
+ _predictiveKnowledgeBaseId);
+
+ var httpContent = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json");
+
+ client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", _predictiveQnAHttpKey);
+
+ var msg = await client.PatchAsync(new Uri(requestUri), httpContent);
+
+ if (msg.IsSuccessStatusCode)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public async Task AddQnAPair(string question, string answer)
+ {
+ var payload = new QnAPayload()
+ {
+ Add = new AddPayLoad()
+ {
+ QnaList = new List(),
+ },
+ };
+
+ var qnaItemToAdd = new QnAItemToAdd();
+ qnaItemToAdd.Answer = answer;
+ qnaItemToAdd.Questions.Add(question);
+
+ payload.Add.QnaList.Add(qnaItemToAdd);
+
+
+ var addResult = await PatchQnA(payload);
+
+ if (addResult)
+ {
+ var publishResult = await PublishQnA();
+
+ return publishResult;
+ }
+ else
+ {
+ return addResult;
+ }
+ }
+
+ public async Task UpdateQnAPair(List questionsToAdd = null, List questionsToDelete = null, string answerToUpdate = null, int id = 0)
+ {
+ var payload = new QnAPayload()
+ {
+ Update = new UpdatePayload()
+ {
+ Name = _predictiveQnAKnowledgeBaseName,
+ QnaList = new List(),
+ },
+ };
+
+ var qnaItemToUpdate = new QnaItemToUpdate
+ {
+ Id = id,
+ };
+
+ if (questionsToAdd != null && questionsToAdd.Count > 0)
+ {
+ qnaItemToUpdate.Questions.Add.AddRange(questionsToAdd);
+ }
+
+ if (questionsToDelete != null && questionsToDelete.Count > 0)
+ {
+ qnaItemToUpdate.Questions.Delete.AddRange(questionsToDelete);
+ }
+
+ if (!string.IsNullOrEmpty(answerToUpdate))
+ {
+ qnaItemToUpdate.Answer = answerToUpdate;
+ }
+
+ payload.Update.QnaList.Add(qnaItemToUpdate);
+
+ var addResult = await PatchQnA(payload);
+ if (addResult)
+ {
+ var publishResult = await PublishQnA();
+
+ return publishResult;
+ }
+ else
+ {
+ return addResult;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Services/QnAService.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/QnAService.cs
new file mode 100644
index 0000000..7cf18ef
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/QnAService.cs
@@ -0,0 +1,78 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Threading.Tasks;
+using System.Web;
+using Microsoft.Teams.Apps.QBot.Model;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Services
+{
+ ///
+ /// QnAMakerService is a wrapper over the QnA Maker REST endpoint
+ ///
+ [Serializable]
+ public class QnAService
+ {
+ private string _qnaServiceHostName;
+ private string _knowledgeBaseId;
+ private string _endpointKey;
+
+ ///
+ /// Initialize a particular endpoint with it's details
+ ///
+ public QnAService()
+ {
+ //_qnaServiceHostName = ConfigurationManager.AppSettings["QnAServiceHostName"];
+ //_knowledgeBaseId = ConfigurationManager.AppSettings["QnAknowledgeBaseId"];
+ //_endpointKey = ConfigurationManager.AppSettings["QnAEndpointKey"];
+
+ _qnaServiceHostName = ServiceHelper.QnAHost;
+ _knowledgeBaseId = ServiceHelper.QnaKnowledgebaseId;
+ _endpointKey = ServiceHelper.QnAEndpoint;
+ }
+
+ ///
+ /// Call the QnA Maker endpoint and get a response
+ ///
+ /// User question
+ ///
+ public async Task GetAnswer(string query)
+ {
+ var qnaResponse = new QnAResponse();
+
+ using (HttpClient client = new HttpClient())
+ {
+ string requestUri = String.Format("{0}{1}{2}{3}",
+ _qnaServiceHostName,
+ @"knowledgebases/",
+ _knowledgeBaseId,
+ @"/generateAnswer");
+
+ var httpContent = new StringContent("{\"question\": \""+query+"\"}}", Encoding.UTF8, "application/json");
+
+ client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("EndpointKey", _endpointKey);
+
+ var msg = await client.PostAsync(requestUri, httpContent);
+
+ if (msg.IsSuccessStatusCode)
+ {
+ var jsonDataResponse = await msg.Content.ReadAsStringAsync();
+ qnaResponse = JsonConvert.DeserializeObject(jsonDataResponse);
+ }
+ }
+
+ if (qnaResponse != null && qnaResponse.Answers != null && qnaResponse.Answers.Count > 0)
+ {
+ return qnaResponse.Answers.FirstOrDefault();
+ } else
+ {
+ return null;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Services/ResourceService.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/ResourceService.cs
new file mode 100644
index 0000000..ebbcc5a
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/ResourceService.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+using System.Resources;
+using System.Web;
+using System.Web.Http;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Services
+{
+ [Serializable]
+ public class ResourceService
+ {
+ private const string RESOURCE_NAME = "Microsoft.Teams.Apps.QBot.Bot.Resources.strings";
+ private string suffix = string.Empty;
+ private static ResourceService instance;
+ public ResourceService()
+ {
+ }
+
+ public ResourceService(string suffix)
+ {
+ this.suffix = suffix;
+ }
+ public string GetValueFor(string key)
+ {
+ var filename = RESOURCE_NAME;
+
+ if (false == string.IsNullOrEmpty(this.suffix))
+ {
+ filename = $"{RESOURCE_NAME}.{this.suffix}";
+ }
+
+ var resoureManager = new ResourceManager(filename, Assembly.GetExecutingAssembly());
+ var value = resoureManager.GetString(key, CultureInfo.CurrentCulture);
+
+ return value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Services/SQLService.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/SQLService.cs
new file mode 100644
index 0000000..e68832e
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/SQLService.cs
@@ -0,0 +1,586 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using Microsoft.Teams.Apps.QBot.Data;
+using Microsoft.Teams.Apps.QBot.Model;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Services
+{
+ public static class SQLService
+ {
+ ///
+ /// Returns a list of O365 Group IDs where a question has been asked, which also matches the list of Group Ids passed in
+ ///
+ /// Tenant ID
+ /// List of all Group Ids to filter by
+ /// List of all O365 Group IDs
+ public static List GetTeamGroupIdsWithQuestions(string tenantId, List memberOf)
+ {
+ try
+ {
+
+ var groupIds = SQLAdapter.GetTeamGroupIdsWithQuestions(tenantId, memberOf);
+
+ return groupIds;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ #region Question
+ public static int CreateOrUpdateQuestion(QuestionModel questionModel)
+ {
+ try
+ {
+ var question = ModelMapper.MapFromQuestionModel(questionModel);
+
+ return SQLAdapter.AddOrUpdateQuestion(question);
+ }
+ catch (Exception e)
+ {
+ return -1;
+ }
+ }
+
+ public static QuestionModel GetQuestion(int questionId)
+ {
+ try
+ {
+ var question = SQLAdapter.GetQuestionById(questionId);
+
+ //if (question.QuestionUser != null)
+ //{
+ // var questionUser = SQLAdapter.GetUserById(question.QuestionUser.Id);
+ // question.QuestionUser = questionUser;
+ //}
+
+ //if (question.AnswerUser != null)
+ //{
+ // var answerUser = SQLAdapter.GetUserById(question.AnswerUser.Id);
+ // question.AnswerUser = answerUser;
+ //}
+
+ return ModelMapper.MapToQuestionModel(question);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+
+ }
+
+ public static QuestionModel GetQuestionByMessageId(string messageId)
+ {
+ try
+ {
+ var question = SQLAdapter.GetQuestionByMessageId(messageId);
+
+ //if (question.QuestionUser != null)
+ //{
+ // var questionUser = SQLAdapter.GetUserById(question.QuestionUser.Id);
+ // question.QuestionUser = questionUser;
+ //}
+
+ //if (question.AnswerUser != null)
+ //{
+ // var answerUser = SQLAdapter.GetUserById(question.AnswerUser.Id);
+ // question.AnswerUser = answerUser;
+ //}
+
+ return ModelMapper.MapToQuestionModel(question);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List GetAllQuestions(string tenantId = null)
+ {
+ try
+ {
+ var questions = SQLAdapter.GetAllQuestions(tenantId);
+
+ var questionModels = ModelMapper.MapToQuestionModels(questions);
+
+ return questionModels;
+
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List GetQuestionsByGroup(string groupId)
+ {
+ try
+ {
+ var questions = SQLAdapter.GetQuestionsByGroup(groupId);
+
+ var questionModels = ModelMapper.MapToQuestionModels(questions);
+
+ return questionModels;
+
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+
+ public static List GetAllQuestionsByTutorial(string tenantId, string code)
+ {
+ try
+ {
+ var questions = SQLAdapter.GetQuestionsByTutorialGroup(tenantId, code);
+
+ var questionModels = ModelMapper.MapToQuestionModels(questions);
+
+ return questionModels;
+
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static bool DoesConversationIdExist(string conversationId)
+ {
+ try
+ {
+
+ var question = SQLAdapter.GetQuestionByConversationId(conversationId);
+
+ return question != null;
+
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ }
+ #endregion
+
+ #region User
+
+ public static bool NoUsers()
+ {
+ return SQLAdapter.NoUsers();
+ }
+
+ public static void AddGlobalAdminUser(string upn, string firstName, string lastName, string email)
+ {
+ var user = new User
+ {
+ UserPrincipalName = upn,
+ FirstName = firstName,
+ LastName = lastName,
+ Email = email,
+ IsGlobalAdmin = true,
+ };
+
+ SQLAdapter.UpdateUser(user);
+ }
+
+ public static UserAccessModel GetUserAccess(string upn)
+ {
+ var result = new UserAccessModel();
+ var user = SQLAdapter.GetUserByUPN(upn);
+ if (user == null)
+ {
+ throw new Exception("User " + upn + " does not exist");
+ }
+
+ result.IsGlobalAdmin = user.IsGlobalAdmin == true;
+
+ var userRoleMappings = SQLAdapter.GetUsersByUPN(upn);
+ result.IsLecturer = userRoleMappings.Any(m => m.Role.Name == Constants.LECTURER_ROLE);
+ result.IsDemonstrator = userRoleMappings.Any(m => m.Role.Name == Constants.DEMONSTRATOR_ROLE);
+
+ return result;
+ }
+
+ public static UserCourseRoleMappingModel GetUser(string userPrincipleName)
+ {
+ try
+ {
+ var user = SQLAdapter.GetUserMappingsByUPN(userPrincipleName);
+ var ucrm = ModelMapper.MapToUserModel(user);
+ return ucrm;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List GetUsersByRole(string role, int courseID)
+ {
+ try
+ {
+ var users = SQLAdapter.GetUsersByRole(role, courseID);
+
+ return ModelMapper.MapToUsersModel(users);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static UserCourseRoleMappingModel GetBotUser(int courseID)
+ {
+ try
+ {
+ var user = SQLAdapter.GetBotUser(courseID);
+
+ return ModelMapper.MapToUserModel(user);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static bool IsUserAdmin(string email)
+ {
+ try
+ {
+ var users = SQLAdapter.GetUsersByUPN(email);
+ if (users == null)
+ {
+ return false;
+ }
+ else
+ {
+ foreach (UserCourseRoleMapping user in users) {
+ if (user.Role.Name != "Student") {
+ return true;
+ }
+ }
+ }
+ return false;
+
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ }
+
+ public static bool UpdateUser(UserCourseRoleMappingModel userModel)
+ {
+ try
+ {
+ var user = ModelMapper.MapFromUserModel(userModel);
+
+ return SQLAdapter.UpdateUser(user);
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ }
+
+ public static List GetDemonstrators(int courseId)
+ {
+ try
+ {
+ //var admins = new List();
+
+ //var rawUsers = SQLAdapter.GetUsersByTutorialCode(tutorialCode);
+
+ //foreach (var user in rawUsers)
+ //{
+ // var retrievedUser = SQLAdapter.GetUserById(user.Id);
+ // if (retrievedUser.Role.Name != "Student")
+ // admins.Add(retrievedUser);
+ //}
+ var demonstrators = SQLAdapter.GetDemonstrators(courseId);
+
+ var result = ModelMapper.MapToUsersModel(demonstrators);
+
+ return result;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List GetStudents(string tutorialCode)
+ {
+ try
+ {
+ var students = new List();
+
+ var rawUsers = SQLAdapter.GetUsersByTutorialCode(tutorialCode);
+
+ foreach (var user in rawUsers)
+ {
+ var retrievedUser = SQLAdapter.GetUserById(user.Id);
+ if (retrievedUser.Role.Name == "Student")
+ students.Add(retrievedUser);
+ }
+
+ var result = ModelMapper.MapToUsersModel(students);
+
+ return result;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List GetAllAdmins(int courseID)
+ {
+ try
+ {
+
+ var admins = new List();
+ var demonstrators = SQLAdapter.GetUsersByRole("Demonstrator", courseID);
+ var lecturers = SQLAdapter.GetUsersByRole("Lecturer", courseID);
+
+ admins.AddRange(ModelMapper.MapToUsersModel(demonstrators));
+ admins.AddRange(ModelMapper.MapToUsersModel(lecturers));
+
+ return admins;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+ #endregion
+
+ #region Assessment
+
+ //public static AssessmentModel GetNextTest(DateTime date)
+ //{
+ // try
+ // {
+ // var test = SQLAdapter.GetNextTest(date);
+ // return ModelMapper.MapToAssessmentModel(test);
+ // } catch (Exception e)
+ // {
+ // return null;
+ // }
+ //}
+
+ //public static List GetActivitiesThisWeek(DateTime date)
+ //{
+ // try
+ // {
+ // var activities = SQLAdapter.GetActivitiesThisWeek(date);
+
+ // return ModelMapper.MapToAssessmentModels(activities);
+ // }
+ // catch (Exception e)
+ // {
+ // return null;
+ // }
+ //}
+
+
+ #endregion
+
+
+
+ #region QR
+
+ //public static QRQuestionModel GetQRQuestion(string questionCode)
+ //{
+ // try
+ // {
+ // var qrQuestion = SQLAdapter.GetQRQuestionLookup(questionCode);
+ // return ModelMapper.MapToQRQuestionModel(qrQuestion);
+ // } catch (Exception e)
+ // {
+ // return null;
+ // }
+ //}
+
+ #endregion
+
+ #region Course
+ public static Course GetCourse(int courseID)
+ {
+ try
+ {
+ return SQLAdapter.GetCourse(courseID);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static int GetCourseIDByName(string name)
+ {
+ try
+ {
+ return SQLAdapter.GetCourseIDByName(name);
+ }
+ catch (Exception e)
+ {
+ return 0;
+ }
+ }
+
+ public static List GetCourses()
+ {
+ try
+ {
+ return SQLAdapter.GetCourses();
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List SaveCourse(Course course)
+ {
+ try
+ {
+ return SQLAdapter.SaveCourse(course);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List DeleteCourse(int id)
+ {
+ try
+ {
+ return SQLAdapter.DeleteCourse(id);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List AddStudents(List students, string coursename)
+ {
+ try
+ {
+ return SQLAdapter.AddStudents(students, coursename);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List GetUserCourseRoleMappingsByCourse(int courseId)
+ {
+ try
+ {
+ var ucrms = SQLAdapter.GetUserCourseRoleMappingsByCourse(courseId);
+ var mappedUcrms = ModelMapper.MapToUsersModel(ucrms);
+ return mappedUcrms;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+ public static List DeleteUserCourseRoleMapping(UserCourseRoleMapping ucrm)
+ {
+ try
+ {
+ var ucrms = SQLAdapter.DeleteUserCourseRoleMapping(ucrm);
+ var mappedUcrms = ModelMapper.MapToUsersModel(ucrms);
+ return mappedUcrms;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List SaveUserCourseRoleMapping(UserCourseRoleMappingModel ucrm)
+ {
+ try
+ {
+ var ucrms = SQLAdapter.SaveUserCourseRoleMapping(ModelMapper.MapFromUserModelToUserCourseMapping(ucrm), ModelMapper.GetIdsFromTutorialGroupModelList(ucrm.TutorialGroups));
+ var mappedUcrms = ModelMapper.MapToUsersModel(ucrms);
+ return mappedUcrms;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+
+ public static List GetRoles()
+ {
+ try
+ {
+
+ var roles = SQLAdapter.GetRoles();
+ return ModelMapper.MapToRoleModelList(roles);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List GetTutorialsByCourse(int courseId)
+ {
+ try
+ {
+ var tutorialGroups = SQLAdapter.GetTutorialsByCourse(courseId);
+ var tutorialGroupModels = ModelMapper.MapToTutorialGroupsModel(tutorialGroups);
+ return tutorialGroupModels;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List SaveTutorialGroup(TutorialGroup tutorial)
+ {
+ try
+ {
+ var tutorialGroups = SQLAdapter.SaveTutorialGroup(tutorial);
+ var tutorialGroupModels = ModelMapper.MapToTutorialGroupsModel(tutorialGroups);
+ return tutorialGroupModels;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List DeleteTutorialGroup(TutorialGroup tutorial)
+ {
+ try
+ {
+ var tutorialGroups = SQLAdapter.DeleteTutorialGroup(tutorial);
+ var tutorialGroupModels = ModelMapper.MapToTutorialGroupsModel(tutorialGroups);
+ return tutorialGroupModels;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Services/ServiceHelper.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/ServiceHelper.cs
new file mode 100644
index 0000000..37fa1be
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/ServiceHelper.cs
@@ -0,0 +1,235 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Security;
+using System.Text;
+using System.Threading.Tasks;
+
+using EncryptionHelper;
+
+using Microsoft.Teams.Apps.QBot.Model;
+
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Services
+{
+ public static class ServiceHelper
+ {
+ #region Config Properties
+
+ public static string BaseUrl
+ {
+ get
+ {
+ return ConfigurationManager.AppSettings[Constants.BASE_URL_KEY];
+ }
+ }
+
+ public static string ClientId
+ {
+ get
+ {
+ return ConfigurationManager.AppSettings[Constants.AAD_CLIENTID_KEY];
+ }
+ }
+
+ public static string Authority
+ {
+ get
+ {
+ return ConfigurationManager.AppSettings[Constants.AAD_AUTHORITY_KEY];
+ }
+ }
+
+ public static string GraphResource
+ {
+ get
+ {
+ return ConfigurationManager.AppSettings[Constants.AAD_GRAPHRESOURCE_KEY];
+ }
+ }
+
+ public static string ServiceAccountName
+ {
+ get
+ {
+ return ConfigurationManager.AppSettings[Constants.SERVICE_ACCOUNT_KEY];
+ }
+ }
+
+ public static SecureString ServiceAccountPassword
+ {
+ get
+ {
+ CryptoTransform cryptoTransform = new CryptoTransform(Helper.PASSPHRASE, Helper.INITVECTOR);
+ var outputString = cryptoTransform.Decrypt(ConfigurationManager.AppSettings[Constants.SERVICE_ACCOUNT_PASSWORD_KEY]);
+
+ return GetPassword(outputString);
+ }
+ }
+
+ public static string GraphRootUri
+ {
+ get
+ {
+ return ConfigurationManager.AppSettings[Constants.AAD_GRAPHROOT_KEY];
+ }
+ }
+
+ public static string AppId
+ {
+ get
+ {
+ return ConfigurationManager.AppSettings[Constants.BOT_APPID_KEY];
+ }
+ }
+
+ public static string AppSecret
+ {
+ get
+ {
+ return ConfigurationManager.AppSettings[Constants.BOT_APPPASSWORD_KEY];
+ }
+ }
+
+ public static string QnAEndpoint
+ {
+ get
+ {
+ return ConfigurationManager.AppSettings[Constants.QNA_ENDPOINT_KEY];
+ }
+ }
+
+ public static string QnAHost
+ {
+ get
+ {
+ return ConfigurationManager.AppSettings[Constants.QNA_HOST_KEY];
+ }
+ }
+
+ public static string QnaKnowledgebaseId
+ {
+ get
+ {
+ return ConfigurationManager.AppSettings[Constants.QNA_ID_KEY];
+ }
+ }
+
+ #endregion
+
+ public static async Task SendRequest(HttpMethod method, String endPoint, string accessToken, dynamic content = null)
+ {
+ HttpResponseMessage response = null;
+ using (var client = new HttpClient())
+ {
+ using (var request = new HttpRequestMessage(method, endPoint))
+ {
+ request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
+ if (content != null)
+ {
+ string c;
+ if (content is string)
+ c = content;
+ else
+ c = JsonConvert.SerializeObject(content);
+ request.Content = new StringContent(c, Encoding.UTF8, "application/json");
+ }
+
+ response = await client.SendAsync(request);
+ }
+ }
+ return response;
+
+ }
+
+ ///
+ /// Helper function to prepare the ResultsItem list from request response.
+ ///
+ /// Request response
+ /// Property name of the item Id
+ /// Property name of the item display name
+ ///
+ public static async Task> GetResultsItem(
+ HttpResponseMessage response, string idPropertyName, string displayPropertyName, string resourcePropId)
+ {
+ List items = new List();
+
+ JObject json = JObject.Parse(await response.Content.ReadAsStringAsync());
+ foreach (JProperty content in json.Children())
+ {
+ if (content.Name.Equals("value"))
+ {
+ var res = content.Value.AsJEnumerable().GetEnumerator();
+ res.MoveNext();
+
+ while (res.Current != null)
+ {
+ string display = "";
+ string id = "";
+
+ foreach (JProperty prop in res.Current.Children())
+ {
+ if (prop.Name.Equals(idPropertyName))
+ {
+ id = prop.Value.ToString();
+ }
+
+ if (prop.Name.Equals(displayPropertyName))
+ {
+ display = prop.Value.ToString();
+ }
+ }
+
+ items.Add(new ResultsItem
+ {
+ Display = display,
+ Id = id,
+ Properties = new Dictionary
+ {
+ { resourcePropId, id }
+ }
+ });
+
+ res.MoveNext();
+ }
+ }
+ }
+
+ return items;
+ }
+
+ public static SecureString GetPassword(string password)
+ {
+ SecureString sStrPwd = new SecureString();
+
+ try
+ {
+ if (!string.IsNullOrEmpty(password))
+ {
+ var secure = new SecureString();
+ foreach (char c in password)
+ {
+ secure.AppendChar(c);
+ }
+
+ return secure;
+ }
+ else
+ {
+ throw new Exception("Password cannot be empty");
+ }
+ }
+ catch (Exception e)
+ {
+ sStrPwd = null;
+ }
+
+ return sStrPwd;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Services/SharePointServices.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/SharePointServices.cs
new file mode 100644
index 0000000..9c37319
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Services/SharePointServices.cs
@@ -0,0 +1,404 @@
+using Microsoft.SharePoint.Client;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.IO;
+using System.Linq;
+using System.Web;
+using Microsoft.Teams.Apps.QBot.Data;
+using Microsoft.Teams.Apps.QBot.Model;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.Services
+{
+ public static class SharePointServices
+ {
+ private static SharePointListAdapter adapter;
+
+ private static void Init()
+ {
+ if (adapter == null)
+ adapter = new SharePointListAdapter(
+ ConfigurationManager.AppSettings["siteUrl"],
+ Convert.ToBoolean(ConfigurationManager.AppSettings["isOnPrem"]),
+ ConfigurationManager.AppSettings["username"],
+ ConfigurationManager.AppSettings["password"]
+ );
+ }
+
+ public static void Init(string tenantUrl, string username, string password)
+ {
+ if (adapter == null)
+ adapter = new SharePointListAdapter(
+ tenantUrl,
+ false,
+ username,
+ password
+ );
+ }
+
+ #region Question
+ public static int CreateOrUpdateQuestion(QuestionModel questionModel)
+ {
+ try
+ {
+ Init();
+
+ var updateProperties = new Dictionary();
+ updateProperties.Add("ID", questionModel.ID.ToString());
+ updateProperties.Add("QuestionText", questionModel.QuestionText.ToString());
+ updateProperties.Add("OriginalPosterEmail", questionModel.OriginalPosterEmail.ToString());
+ updateProperties.Add("Topic", questionModel.Topic.ToString());
+ updateProperties.Add("Status", questionModel.QuestionStatus.ToString());
+ updateProperties.Add("ConversationId", questionModel.ConversationId.ToString());
+
+ return adapter.AddOrUpdateItem("Questions", updateProperties);
+ }
+ catch (Exception e)
+ {
+ return -1;
+ }
+ }
+
+ public static QuestionModel GetQuestion(int questionId)
+ {
+ try
+ {
+ Init();
+
+ var p1 = @"";
+ var p2 = @" ";
+
+ var camlQuery = p1 + questionId + p2;
+
+ var questions = adapter.GetItems("Questions", camlQuery);
+
+ var questionList = new List();
+ foreach (var question in questions)
+ {
+ questionList.Add(new QuestionModel()
+ {
+ ID = Convert.ToInt32(question["ID"].ToString()),
+ QuestionText = question["QuestionText"].ToString(),
+ QuestionStatus = question["Status"].ToString(),
+ OriginalPosterEmail = question["OriginalPosterEmail"].ToString(),
+ Topic = question["Topic"].ToString(),
+ ConversationId = question["ConversationId"].ToString()
+ });
+ }
+
+ var foundQuestion = questionList.FirstOrDefault();
+
+ return foundQuestion;
+
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+
+
+ }
+
+ public static bool DoesConversationIdExist(string conversationId)
+ {
+ try
+ {
+ Init();
+
+ var p1 = @"";
+ var p2 = @" ";
+
+ var camlQuery = p1 + conversationId + p2;
+
+ var questions = adapter.GetItems("Questions", camlQuery);
+
+ var questionList = new List();
+ foreach (var question in questions)
+ {
+ questionList.Add(new QuestionModel()
+ {
+ ID = Convert.ToInt32(question["ID"].ToString()),
+ QuestionText = question["QuestionText"].ToString(),
+ QuestionStatus = question["Status"].ToString(),
+ OriginalPosterEmail = question["OriginalPosterEmail"].ToString(),
+ Topic = question["Topic"].ToString(),
+ ConversationId = question["ConversationId"].ToString()
+ });
+ }
+
+ return questionList.Count > 0;
+
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ }
+ #endregion
+
+ #region User
+ // What will we use to get the user? What do we have access to?
+ public static UserModel GetUser(string userPrincipleName)
+ {
+ try
+ {
+ Init();
+
+ var p1 = @"";
+
+ var p2 = @"" + userPrincipleName + @" ";
+ var p3 = @"" + userPrincipleName + @" ";
+
+ var p4 = @" ";
+
+ //var p1 = @"";
+
+ //var p2 = @" ";
+ //var camlQuery = p1 + userPrincipleName + p2;
+ var camlQuery = p1 + p2 + p3 + p4;
+
+ var users = adapter.GetItems("Users", camlQuery);
+
+ var userList = new List();
+ foreach (var user in users)
+ {
+ userList.Add(new UserModel()
+ {
+ ID = Convert.ToInt32(user["ID"].ToString()),
+ UserName = user["Username"].ToString(),
+ StudentID = user["StudentID"].ToString(),
+ LastName = user["LastName"].ToString(),
+ FirstName = user["FirstName"].ToString(),
+ Email = user["Email"].ToString(),
+ RoleName = user["Role"].ToString(),
+ TutorialGroupsString = SPUtilities.ParseLookup(user["TutorialGroup"] as FieldLookupValue[]),
+ //TeamsUserID = user["TeamsUserID"]?.ToString(),
+ });
+ }
+
+ var foundUser = userList.FirstOrDefault();
+
+ return foundUser;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List GetUsersByRole(string role)
+ {
+ try
+ {
+ Init();
+
+ var p1 = @"";
+
+ var p2 = @" ";
+
+
+ var camlQuery = p1 + role + p2;
+
+ var users = adapter.GetItems("Users", camlQuery);
+
+ var userList = new List();
+ foreach (var user in users)
+ {
+ userList.Add(new UserModel()
+ {
+ ID = Convert.ToInt32(user["ID"].ToString()),
+ UserName = user["Username"].ToString(),
+ StudentID = user["StudentID"].ToString(),
+ LastName = user["LastName"].ToString(),
+ FirstName = user["FirstName"].ToString(),
+ Email = user["Email"].ToString(),
+ RoleName = user["Role"].ToString(),
+ TutorialGroupsString = SPUtilities.ParseLookup(user["TutorialGroup"] as FieldLookupValue[]),
+ //TeamsUserID = user["TeamsUserID"]?.ToString(),
+ });
+ }
+
+ return userList;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static bool IsUserAdmin(string email)
+ {
+ try
+ {
+ Init();
+
+ var p1 = @"";
+
+ var p2 = @"" + email + @" ";
+
+ var p3 = @"Student ";
+
+ var camlQuery = p1 + p2 + p3;
+
+ var users = adapter.GetItems("Users", camlQuery);
+
+ var userList = new List();
+ foreach (var user in users)
+ {
+ userList.Add(new UserModel()
+ {
+ ID = Convert.ToInt32(user["ID"].ToString()),
+ UserName = user["Username"].ToString(),
+ StudentID = user["StudentID"].ToString(),
+ LastName = user["LastName"].ToString(),
+ FirstName = user["FirstName"].ToString(),
+ Email = user["Email"].ToString(),
+ RoleName = user["Role"].ToString(),
+ TutorialGroupsString = SPUtilities.ParseLookup(user["TutorialGroup"] as FieldLookupValue[]),
+ //TeamsUserID = user["TeamsUserID"]?.ToString(),
+ });
+ }
+
+ return userList.Count > 0;
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+
+ }
+
+ public static List GetAdmins(string tutorialCode)
+ {
+ try
+ {
+ Init();
+
+ var p1 = @"";
+
+
+ var split = tutorialCode.Split(';');
+ var conditions = new List();
+ foreach (var code in split)
+ {
+ if (!string.IsNullOrEmpty(code))
+ conditions.Add(@"" + code + @" ");
+ }
+ var p2 = MergeCAMLConditions(conditions, "OR");
+
+ var p3 = @"Student ";
+
+ var camlQuery = p1 + p2 + p3;
+
+ var users = adapter.GetItems("Users", camlQuery);
+
+ var userList = new List();
+ foreach (var user in users)
+ {
+ userList.Add(new UserModel()
+ {
+ ID = Convert.ToInt32(user["ID"].ToString()),
+ UserName = user["Username"].ToString(),
+ StudentID = user["StudentID"].ToString(),
+ LastName = user["LastName"].ToString(),
+ FirstName = user["FirstName"].ToString(),
+ Email = user["Email"].ToString(),
+ RoleName = user["Role"].ToString(),
+ TutorialGroupsString = SPUtilities.ParseLookup(user["TutorialGroup"] as FieldLookupValue[]),
+ //TeamsUserID = user["TeamsUserID"]?.ToString(),
+ });
+ }
+
+ return userList;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+
+ public static List GetAllAdmins()
+ {
+ try
+ {
+ Init();
+
+ var p1 = @"";
+
+ var p3 = @"Student ";
+
+ var camlQuery = p1 + p3;
+
+ var users = adapter.GetItems("Users", camlQuery);
+
+ var userList = new List();
+ foreach (var user in users)
+ {
+ userList.Add(new UserModel()
+ {
+ ID = Convert.ToInt32(user["ID"].ToString()),
+ UserName = user["Username"].ToString(),
+ StudentID = user["StudentID"].ToString(),
+ LastName = user["LastName"].ToString(),
+ FirstName = user["FirstName"].ToString(),
+ Email = user["Email"].ToString(),
+ RoleName = user["Role"].ToString(),
+ TutorialGroupsString = SPUtilities.ParseLookup(user["TutorialGroup"] as FieldLookupValue[]),
+ //TeamsUserID = user["TeamsUserID"]?.ToString(),
+ });
+ }
+
+ return userList;
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+ }
+ #endregion
+
+ #region QR
+ public static Stream GetImageStream(string siteUrl, string imageUrl)
+ {
+
+ try
+ {
+ return adapter.GetImageStream(siteUrl, imageUrl);
+ }
+ catch (Exception e)
+ {
+ return null;
+ }
+
+ }
+
+ #endregion
+
+ private static string MergeCAMLConditions(List conditions, string type)
+ {
+ if (conditions.Count == 0) return "";
+
+ string typeStart = (type == "AND" ? "" : "");
+ string typeEnd = (type == "AND" ? " " : "");
+
+ // Build hierarchical structure
+ while (conditions.Count >= 2)
+ {
+ List complexConditions = new List();
+
+ for (int i = 0; i < conditions.Count; i += 2)
+ {
+ if (conditions.Count == i + 1) // Only one condition left
+ complexConditions.Add(conditions[i]);
+ else // Two condotions - merge
+ complexConditions.Add(typeStart + conditions[i] + conditions[i + 1] + typeEnd);
+ }
+
+ conditions = complexConditions;
+ }
+
+ return conditions[0];
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/Web.config b/Source/Microsoft.Teams.Apps.QBot.Bot/Web.config
new file mode 100644
index 0000000..f71694a
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/Web.config
@@ -0,0 +1,250 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/default.htm b/Source/Microsoft.Teams.Apps.QBot.Bot/default.htm
new file mode 100644
index 0000000..cbc072c
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/default.htm
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+ Microsoft.Teams.Apps.QBot.Bot
+ Describe your bot here and your terms of use etc.
+ Visit Bot Framework to register your bot. When you register it, remember to set your bot's endpoint to
https://your_bots_hostname /api/messages
+
+
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/packages.config b/Source/Microsoft.Teams.Apps.QBot.Bot/packages.config
new file mode 100644
index 0000000..710336c
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/packages.config
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/utility/MicrosoftTeamsChannelHelper.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/utility/MicrosoftTeamsChannelHelper.cs
new file mode 100644
index 0000000..43d3d18
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/utility/MicrosoftTeamsChannelHelper.cs
@@ -0,0 +1,78 @@
+using Microsoft.Bot.Connector;
+using System;
+using System.Text.RegularExpressions;
+using System.Web;
+
+namespace Antares.Bot.Channels
+{
+ public static class MicrosoftTeamsChannelHelper
+ {
+ public static Activity StripAtMentionText(Activity activity)
+ {
+ if (activity == null)
+ {
+ throw new ArgumentNullException(nameof(activity));
+ }
+
+ Mention[] m = activity.GetMentions();
+ for (int i = 0; i < m.Length; i++)
+ {
+ if (m[i].Mentioned.Id == activity.Recipient.Id)
+ {
+ //Bot is in the @mention list.
+ //The below example will strip the bot name out of the message, so you can parse it as if it wasn't included. Note that the Text object will contain the full bot name, if applicable.
+ if (m[i].Text != null)
+ activity.Text = activity.Text.Replace(m[i].Text, "").Trim();
+ }
+ }
+
+ return activity;
+ }
+
+ public static string StripAtMentionText(string text)
+ {
+ if (string.IsNullOrEmpty(text))
+ {
+ return text;
+ }
+
+ var cleanText = Regex.Replace(text, "(.*?)", "", RegexOptions.IgnoreCase);
+
+ return cleanText;
+ }
+
+ public static string StripHtmlTags(string html)
+ {
+ if (String.IsNullOrEmpty(html)) return "";
+
+ HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
+ doc.LoadHtml(html);
+
+ var postHtml = HttpUtility.HtmlDecode(doc.DocumentNode.InnerText);
+ var clean = Regex.Replace(postHtml, @"\t|\n|\r", "");
+
+ return postHtml.Trim();
+ }
+
+ public static string StripMentionAndHtml(string text)
+ {
+ var firstpass = StripAtMentionText(text);
+ var secondpass = StripHtmlTags(firstpass);
+
+ return secondpass;
+ }
+
+ public static Activity ConvertActivityTextToLower(Activity activity)
+ {
+ //Convert input command in lower case for 1To1 and Channel users
+ if (activity.Text != null)
+ {
+ activity.Text = activity.Text.ToLower();
+ }
+
+ return activity;
+ }
+
+
+ }
+}
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/utility/Middleware.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/utility/Middleware.cs
new file mode 100644
index 0000000..52e20c5
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/utility/Middleware.cs
@@ -0,0 +1,44 @@
+using Microsoft.Bot.Connector;
+using System;
+using System.Configuration;
+
+namespace Microsoft.Teams.TemplateBotCSharp.Utility
+{
+ public static partial class Middleware
+ {
+ public static string TenantFilterSettingAny = "#ANY#";
+
+ ///
+ /// Here are below scenarios -
+ /// #Scenario 1 - Reject the Bot If Tenant is configured in web.config and doesn't match with Incoming request tenant
+ /// #Scenario 2 - Allow Bot for every Tenant if Tenant is not configured in web.config file and deafult value is #ANY#
+ ///
+ ///
+ ///
+ ///
+ public static bool RejectMessageBasedOnTenant(IMessageActivity activity, string currentTenant)
+ {
+ if (!String.Equals(ConfigurationManager.AppSettings["OFFICE_365_TENANT_FILTER"], TenantFilterSettingAny))
+ {
+ //#Scenario 1
+ return !string.Equals(ConfigurationManager.AppSettings["OFFICE_365_TENANT_FILTER"], currentTenant);
+ }
+ else
+ {
+ //Scenario 2
+ return false;
+ }
+ }
+
+ public static Activity ConvertActivityTextToLower(Activity activity)
+ {
+ //Convert input command in lower case for 1To1 and Channel users
+ if (activity.Text != null)
+ {
+ activity.Text = activity.Text.ToLower();
+ }
+
+ return activity;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Bot/utility/StringHelper.cs b/Source/Microsoft.Teams.Apps.QBot.Bot/utility/StringHelper.cs
new file mode 100644
index 0000000..fb9f420
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Bot/utility/StringHelper.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Web;
+
+namespace Microsoft.Teams.Apps.QBot.Bot.utility
+{
+ public static class StringHelper
+ {
+ public static string ReplaceLinksWithMarkdown(this string text)
+ {
+ var pattern = @"((http|ftp|https):\/\/)?([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?";
+ var regex = new Regex(pattern);
+
+ var replacedText = regex.Replace(text, new MatchEvaluator((match) =>
+ {
+ string link = match.ToString();
+ return $"[{link}]({link})";
+ }));
+
+ return replacedText;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Data/App.config b/Source/Microsoft.Teams.Apps.QBot.Data/App.config
new file mode 100644
index 0000000..7e1d79c
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Data/App.config
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Data/Course.cs b/Source/Microsoft.Teams.Apps.QBot.Data/Course.cs
new file mode 100644
index 0000000..43f342f
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Data/Course.cs
@@ -0,0 +1,44 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft.Teams.Apps.QBot.Data
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class Course
+ {
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
+ public Course()
+ {
+ this.Questions = new HashSet();
+ this.TutorialGroups = new HashSet();
+ this.UserCourseRoleMappings = new HashSet();
+ }
+
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public System.Guid GroupId { get; set; }
+ public string PredictiveQnAServiceHost { get; set; }
+ public string PredictiveQnAKnowledgeBaseId { get; set; }
+ public string PredictiveQnAEndpointKey { get; set; }
+ public string PredictiveQnAHttpEndpoint { get; set; }
+ public string PredictiveQnAHttpKey { get; set; }
+ public string PredictiveQnAKnowledgeBaseName { get; set; }
+ public string PredictiveQnAConfidenceThreshold { get; set; }
+ public string DeployedURL { get; set; }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+ public virtual ICollection Questions { get; set; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+ public virtual ICollection TutorialGroups { get; set; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+ public virtual ICollection UserCourseRoleMappings { get; set; }
+ }
+}
diff --git a/Source/Microsoft.Teams.Apps.QBot.Data/Microsoft.Teams.Apps.QBot.Data.csproj b/Source/Microsoft.Teams.Apps.QBot.Data/Microsoft.Teams.Apps.QBot.Data.csproj
new file mode 100644
index 0000000..3d59e64
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Data/Microsoft.Teams.Apps.QBot.Data.csproj
@@ -0,0 +1,254 @@
+
+
+
+
+
+ Debug
+ AnyCPU
+ {4E7A14CA-80CD-447C-8C3D-615B45C56939}
+ Library
+ Properties
+ Microsoft.Teams.Apps.QBot.Data
+ Microsoft.Teams.Apps.QBot.Data
+ v4.6.1
+ 512
+ SAK
+ SAK
+ SAK
+ SAK
+
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ bin\Release.CQU\
+ TRACE
+ true
+ pdbonly
+ AnyCPU
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+
+ ..\packages\EntityFramework.6.3.0\lib\net45\EntityFramework.dll
+
+
+ ..\packages\EntityFramework.6.3.0\lib\net45\EntityFramework.SqlServer.dll
+
+
+ ..\packages\SharePoint.Client.Office.Tools.15.0.4907.1002\lib\net40-full\Microsoft.BusinessData.dll
+
+
+ ..\packages\SharePoint.Client.Office.Tools.15.0.4907.1002\lib\net40-full\Microsoft.Office.Client.Education.dll
+
+
+ ..\packages\SharePoint.Client.Office.Tools.15.0.4907.1002\lib\net40-full\Microsoft.Office.Client.Policy.dll
+
+
+ ..\packages\SharePoint.Client.Office.Tools.15.0.4907.1002\lib\net40-full\Microsoft.Office.Client.TranslationServices.dll
+
+
+ ..\packages\SharePoint.Client.Office.Tools.15.0.4907.1002\lib\net40-full\Microsoft.Office.DocumentManagement.dll
+
+
+ ..\packages\SharePoint.Client.Office.Tools.15.0.4907.1002\lib\net40-full\Microsoft.Office.Policy.dll
+
+
+ ..\packages\SharePoint.Client.Office.Tools.15.0.4907.1002\lib\net40-full\Microsoft.Office.SecureStoreService.dll
+
+
+ ..\packages\SharePoint.Client.Office.Tools.15.0.4907.1002\lib\net40-full\Microsoft.Office.SecureStoreService.Server.Security.dll
+
+
+ ..\packages\SharePoint.Client.Office.Tools.15.0.4907.1002\lib\net40-full\Microsoft.Office.Server.dll
+
+
+ ..\packages\SharePoint.Client.Office.Tools.15.0.4907.1002\lib\net40-full\Microsoft.Office.Server.Search.dll
+
+
+ ..\packages\SharePoint.Client.Office.Tools.15.0.4907.1002\lib\net40-full\Microsoft.Office.Server.UserProfiles.dll
+
+
+ ..\packages\SharePoint.Client.Office.Tools.15.0.4907.1002\lib\net40-full\Microsoft.Office.SharePoint.Tools.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.Online.SharePoint.Client.Tenant.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.ApplicationPages.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.ApplicationPages.Administration.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Client.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Client.DocumentManagement.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Client.Publishing.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Client.Runtime.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Client.Search.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Client.Search.Applications.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Client.ServerRuntime.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Client.Taxonomy.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Client.UserProfiles.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Client.WorkflowServices.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.DesignTime.Activities.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Portal.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Publishing.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Security.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.SharePoint.Taxonomy.dll
+
+
+ ..\packages\Microsoft.SharePoint.Client.Online.CSOM.15.0.4919.1000\lib\net40-full\Microsoft.Sharepoint.WorkflowActions.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GlobalSuppressions.cs
+
+
+ QuestionBotModel.tt
+
+
+ QuestionBotModel.tt
+
+
+ True
+ True
+ QuestionBotModel.Context.tt
+
+
+ True
+ True
+ QuestionBotModel.tt
+
+
+ True
+ True
+ QuestionBotModel.edmx
+
+
+ QuestionBotModel.tt
+
+
+
+
+ QuestionBotModel.tt
+
+
+ QuestionBotModel.tt
+
+
+ QuestionBotModel.tt
+
+
+ QuestionBotModel.tt
+
+
+
+
+
+
+
+ stylecop.json
+
+
+
+ Designer
+
+
+ EntityModelCodeGenerator
+ QuestionBotModel.Designer.cs
+
+
+ QuestionBotModel.edmx
+
+
+
+
+ TextTemplatingFileGenerator
+ QuestionBotModel.edmx
+ QuestionBotModel.Context.cs
+
+
+ TextTemplatingFileGenerator
+ QuestionBotModel.edmx
+ QuestionBotModel.cs
+
+
+
+
+
+
+
+
+
+
+
+
+ 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}.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Microsoft.Teams.Apps.QBot.Data/Properties/AssemblyInfo.cs b/Source/Microsoft.Teams.Apps.QBot.Data/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f258acd
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Data/Properties/AssemblyInfo.cs
@@ -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("Microsoft.Teams.Apps.QBot.Data")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Microsoft.Teams.Apps.QBot.Data")]
+[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("4e7a14ca-80cd-447c-8c3d-615b45c56939")]
+
+// 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")]
diff --git a/Source/Microsoft.Teams.Apps.QBot.Data/Question.cs b/Source/Microsoft.Teams.Apps.QBot.Data/Question.cs
new file mode 100644
index 0000000..f1bde98
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Data/Question.cs
@@ -0,0 +1,41 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft.Teams.Apps.QBot.Data
+{
+ using System;
+ using System.Collections.Generic;
+
+ public partial class Question
+ {
+ public int Id { get; set; }
+ public int CourseId { get; set; }
+ public Nullable TenantId { get; set; }
+ public Nullable GroupId { get; set; }
+ public string TeamId { get; set; }
+ public string TeamName { get; set; }
+ public string ConversationId { get; set; }
+ public string MessageId { get; set; }
+ public string Topic { get; set; }
+ public string Status { get; set; }
+ public string QuestionText { get; set; }
+ public int OriginalPosterId { get; set; }
+ public System.DateTime DateSubmitted { get; set; }
+ public string Link { get; set; }
+ public string AnswerText { get; set; }
+ public string AnswerMessageId { get; set; }
+ public Nullable AnswerPosterId { get; set; }
+ public Nullable DateAnswered { get; set; }
+ public string AnswerCardActivityId { get; set; }
+
+ public virtual Course Course { get; set; }
+ public virtual User AnswerUser { get; set; }
+ public virtual User QuestionUser { get; set; }
+ }
+}
diff --git a/Source/Microsoft.Teams.Apps.QBot.Data/QuestionBotModel.Context.cs b/Source/Microsoft.Teams.Apps.QBot.Data/QuestionBotModel.Context.cs
new file mode 100644
index 0000000..880a191
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Data/QuestionBotModel.Context.cs
@@ -0,0 +1,36 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated from a template.
+//
+// Manual changes to this file may cause unexpected behavior in your application.
+// Manual changes to this file will be overwritten if the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft.Teams.Apps.QBot.Data
+{
+ using System;
+ using System.Data.Entity;
+ using System.Data.Entity.Infrastructure;
+
+ public partial class QBotEntities : DbContext
+ {
+ public QBotEntities()
+ : base("name=QBotEntities")
+ {
+ }
+
+ protected override void OnModelCreating(DbModelBuilder modelBuilder)
+ {
+ throw new UnintentionalCodeFirstException();
+ }
+
+ public virtual DbSet Courses { get; set; }
+ public virtual DbSet Questions { get; set; }
+ public virtual DbSet Roles { get; set; }
+ public virtual DbSet TutorialGroups { get; set; }
+ public virtual DbSet TutorialGroupMemberships { get; set; }
+ public virtual DbSet Users { get; set; }
+ public virtual DbSet UserCourseRoleMappings { get; set; }
+ }
+}
diff --git a/Source/Microsoft.Teams.Apps.QBot.Data/QuestionBotModel.Context.tt b/Source/Microsoft.Teams.Apps.QBot.Data/QuestionBotModel.Context.tt
new file mode 100644
index 0000000..db98cd3
--- /dev/null
+++ b/Source/Microsoft.Teams.Apps.QBot.Data/QuestionBotModel.Context.tt
@@ -0,0 +1,636 @@
+<#@ template language="C#" debug="false" hostspecific="true"#>
+<#@ include file="EF6.Utility.CS.ttinclude"#><#@
+ output extension=".cs"#><#
+
+const string inputFile = @"QuestionBotModel.edmx";
+var textTransform = DynamicTextTransformation.Create(this);
+var code = new CodeGenerationTools(this);
+var ef = new MetadataTools(this);
+var typeMapper = new TypeMapper(code, ef, textTransform.Errors);
+var loader = new EdmMetadataLoader(textTransform.Host, textTransform.Errors);
+var itemCollection = loader.CreateEdmItemCollection(inputFile);
+var modelNamespace = loader.GetModelNamespace(inputFile);
+var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef);
+
+var container = itemCollection.OfType().FirstOrDefault();
+if (container == null)
+{
+ return string.Empty;
+}
+#>
+//------------------------------------------------------------------------------
+//
+// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine1")#>
+//
+// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine2")#>
+// <#=CodeGenerationTools.GetResourceString("Template_GeneratedCodeCommentLine3")#>
+//
+//------------------------------------------------------------------------------
+
+<#
+
+var codeNamespace = code.VsNamespaceSuggestion();
+if (!String.IsNullOrEmpty(codeNamespace))
+{
+#>
+namespace <#=code.EscapeNamespace(codeNamespace)#>
+{
+<#
+ PushIndent(" ");
+}
+
+#>
+using System;
+using System.Data.Entity;
+using System.Data.Entity.Infrastructure;
+<#
+if (container.FunctionImports.Any())
+{
+#>
+using System.Data.Entity.Core.Objects;
+using System.Linq;
+<#
+}
+#>
+
+<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
+{
+ public <#=code.Escape(container)#>()
+ : base("name=<#=container.Name#>")
+ {
+<#
+if (!loader.IsLazyLoadingEnabled(container))
+{
+#>
+ this.Configuration.LazyLoadingEnabled = false;
+<#
+}
+
+foreach (var entitySet in container.BaseEntitySets.OfType())
+{
+ // Note: the DbSet members are defined below such that the getter and
+ // setter always have the same accessibility as the DbSet definition
+ if (Accessibility.ForReadOnlyProperty(entitySet) != "public")
+ {
+#>
+ <#=codeStringGenerator.DbSetInitializer(entitySet)#>
+<#
+ }
+}
+#>
+ }
+
+ protected override void OnModelCreating(DbModelBuilder modelBuilder)
+ {
+ throw new UnintentionalCodeFirstException();
+ }
+
+<#
+ foreach (var entitySet in container.BaseEntitySets.OfType())
+ {
+#>
+ <#=codeStringGenerator.DbSet(entitySet)#>
+<#
+ }
+
+ foreach (var edmFunction in container.FunctionImports)
+ {
+ WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: false);
+ }
+#>
+}
+<#
+
+if (!String.IsNullOrEmpty(codeNamespace))
+{
+ PopIndent();
+#>
+}
+<#
+}
+#>
+<#+
+
+private void WriteFunctionImport(TypeMapper typeMapper, CodeStringGenerator codeStringGenerator, EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
+{
+ if (typeMapper.IsComposable(edmFunction))
+ {
+#>
+
+ [DbFunction("<#=edmFunction.NamespaceName#>", "<#=edmFunction.Name#>")]
+ <#=codeStringGenerator.ComposableFunctionMethod(edmFunction, modelNamespace)#>
+ {
+<#+
+ codeStringGenerator.WriteFunctionParameters(edmFunction, WriteFunctionParameter);
+#>
+ <#=codeStringGenerator.ComposableCreateQuery(edmFunction, modelNamespace)#>
+ }
+<#+
+ }
+ else
+ {
+#>
+
+ <#=codeStringGenerator.FunctionMethod(edmFunction, modelNamespace, includeMergeOption)#>
+ {
+<#+
+ codeStringGenerator.WriteFunctionParameters(edmFunction, WriteFunctionParameter);
+#>
+ <#=codeStringGenerator.ExecuteFunction(edmFunction, modelNamespace, includeMergeOption)#>
+ }
+<#+
+ if (typeMapper.GenerateMergeOptionFunction(edmFunction, includeMergeOption))
+ {
+ WriteFunctionImport(typeMapper, codeStringGenerator, edmFunction, modelNamespace, includeMergeOption: true);
+ }
+ }
+}
+
+public void WriteFunctionParameter(string name, string isNotNull, string notNullInit, string nullInit)
+{
+#>
+ var <#=name#> = <#=isNotNull#> ?
+ <#=notNullInit#> :
+ <#=nullInit#>;
+
+<#+
+}
+
+public const string TemplateId = "CSharp_DbContext_Context_EF6";
+
+public class CodeStringGenerator
+{
+ private readonly CodeGenerationTools _code;
+ private readonly TypeMapper _typeMapper;
+ private readonly MetadataTools _ef;
+
+ public CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef)
+ {
+ ArgumentNotNull(code, "code");
+ ArgumentNotNull(typeMapper, "typeMapper");
+ ArgumentNotNull(ef, "ef");
+
+ _code = code;
+ _typeMapper = typeMapper;
+ _ef = ef;
+ }
+
+ public string Property(EdmProperty edmProperty)
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} {1} {2} {{ {3}get; {4}set; }}",
+ Accessibility.ForProperty(edmProperty),
+ _typeMapper.GetTypeName(edmProperty.TypeUsage),
+ _code.Escape(edmProperty),
+ _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
+ _code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
+ }
+
+ public string NavigationProperty(NavigationProperty navProp)
+ {
+ var endType = _typeMapper.GetTypeName(navProp.ToEndMember.GetEntityType());
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} {1} {2} {{ {3}get; {4}set; }}",
+ AccessibilityAndVirtual(Accessibility.ForNavigationProperty(navProp)),
+ navProp.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
+ _code.Escape(navProp),
+ _code.SpaceAfter(Accessibility.ForGetter(navProp)),
+ _code.SpaceAfter(Accessibility.ForSetter(navProp)));
+ }
+
+ public string AccessibilityAndVirtual(string accessibility)
+ {
+ return accessibility + (accessibility != "private" ? " virtual" : "");
+ }
+
+ public string EntityClassOpening(EntityType entity)
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} {1}partial class {2}{3}",
+ Accessibility.ForType(entity),
+ _code.SpaceAfter(_code.AbstractOption(entity)),
+ _code.Escape(entity),
+ _code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
+ }
+
+ public string EnumOpening(SimpleType enumType)
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} enum {1} : {2}",
+ Accessibility.ForType(enumType),
+ _code.Escape(enumType),
+ _code.Escape(_typeMapper.UnderlyingClrType(enumType)));
+ }
+
+ public void WriteFunctionParameters(EdmFunction edmFunction, Action writeParameter)
+ {
+ var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
+ foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable))
+ {
+ var isNotNull = parameter.IsNullableOfT ? parameter.FunctionParameterName + ".HasValue" : parameter.FunctionParameterName + " != null";
+ var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", " + parameter.FunctionParameterName + ")";
+ var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", typeof(" + TypeMapper.FixNamespaces(parameter.RawClrTypeName) + "))";
+ writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit);
+ }
+ }
+
+ public string ComposableFunctionMethod(EdmFunction edmFunction, string modelNamespace)
+ {
+ var parameters = _typeMapper.GetParameters(edmFunction);
+
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} IQueryable<{1}> {2}({3})",
+ AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
+ _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
+ _code.Escape(edmFunction),
+ string.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray()));
+ }
+
+ public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace)
+ {
+ var parameters = _typeMapper.GetParameters(edmFunction);
+
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "return ((IObjectContextAdapter)this).ObjectContext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});",
+ _typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
+ edmFunction.NamespaceName,
+ edmFunction.Name,
+ string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName).ToArray()),
+ _code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())));
+ }
+
+ public string FunctionMethod(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
+ {
+ var parameters = _typeMapper.GetParameters(edmFunction);
+ var returnType = _typeMapper.GetReturnType(edmFunction);
+
+ var paramList = String.Join(", ", parameters.Select(p => TypeMapper.FixNamespaces(p.FunctionParameterType) + " " + p.FunctionParameterName).ToArray());
+ if (includeMergeOption)
+ {
+ paramList = _code.StringAfter(paramList, ", ") + "MergeOption mergeOption";
+ }
+
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} {1} {2}({3})",
+ AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
+ returnType == null ? "int" : "ObjectResult<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
+ _code.Escape(edmFunction),
+ paramList);
+ }
+
+ public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
+ {
+ var parameters = _typeMapper.GetParameters(edmFunction);
+ var returnType = _typeMapper.GetReturnType(edmFunction);
+
+ var callParams = _code.StringBefore(", ", String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()));
+ if (includeMergeOption)
+ {
+ callParams = ", mergeOption" + callParams;
+ }
+
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}(\"{1}\"{2});",
+ returnType == null ? "" : "<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
+ edmFunction.Name,
+ callParams);
+ }
+
+ public string DbSet(EntitySet entitySet)
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} virtual DbSet<{1}> {2} {{ get; set; }}",
+ Accessibility.ForReadOnlyProperty(entitySet),
+ _typeMapper.GetTypeName(entitySet.ElementType),
+ _code.Escape(entitySet));
+ }
+
+ public string DbSetInitializer(EntitySet entitySet)
+ {
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} = Set<{1}>();",
+ _code.Escape(entitySet),
+ _typeMapper.GetTypeName(entitySet.ElementType));
+ }
+
+ public string UsingDirectives(bool inHeader, bool includeCollections = true)
+ {
+ return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
+ ? string.Format(
+ CultureInfo.InvariantCulture,
+ "{0}using System;{1}" +
+ "{2}",
+ inHeader ? Environment.NewLine : "",
+ includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "",
+ inHeader ? "" : Environment.NewLine)
+ : "";
+ }
+}
+
+public class TypeMapper
+{
+ private const string ExternalTypeNameAttributeName = @"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName";
+
+ private readonly System.Collections.IList _errors;
+ private readonly CodeGenerationTools _code;
+ private readonly MetadataTools _ef;
+
+ public static string FixNamespaces(string typeName)
+ {
+ return typeName.Replace("System.Data.Spatial.", "System.Data.Entity.Spatial.");
+ }
+
+ public TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors)
+ {
+ ArgumentNotNull(code, "code");
+ ArgumentNotNull(ef, "ef");
+ ArgumentNotNull(errors, "errors");
+
+ _code = code;
+ _ef = ef;
+ _errors = errors;
+ }
+
+ public string GetTypeName(TypeUsage typeUsage)
+ {
+ return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null);
+ }
+
+ public string GetTypeName(EdmType edmType)
+ {
+ return GetTypeName(edmType, isNullable: null, modelNamespace: null);
+ }
+
+ public string GetTypeName(TypeUsage typeUsage, string modelNamespace)
+ {
+ return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace);
+ }
+
+ public string GetTypeName(EdmType edmType, string modelNamespace)
+ {
+ return GetTypeName(edmType, isNullable: null, modelNamespace: modelNamespace);
+ }
+
+ public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace)
+ {
+ if (edmType == null)
+ {
+ return null;
+ }
+
+ var collectionType = edmType as CollectionType;
+ if (collectionType != null)
+ {
+ return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>", GetTypeName(collectionType.TypeUsage, modelNamespace));
+ }
+
+ var typeName = _code.Escape(edmType.MetadataProperties
+ .Where(p => p.Name == ExternalTypeNameAttributeName)
+ .Select(p => (string)p.Value)
+ .FirstOrDefault())
+ ?? (modelNamespace != null && edmType.NamespaceName != modelNamespace ?
+ _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType)) :
+ _code.Escape(edmType));
+
+ if (edmType is StructuralType)
+ {
+ return typeName;
+ }
+
+ if (edmType is SimpleType)
+ {
+ var clrType = UnderlyingClrType(edmType);
+ if (!IsEnumType(edmType))
+ {
+ typeName = _code.Escape(clrType);
+ }
+
+ typeName = FixNamespaces(typeName);
+
+ return clrType.IsValueType && isNullable == true ?
+ String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName) :
+ typeName;
+ }
+
+ throw new ArgumentException("edmType");
+ }
+
+ public Type UnderlyingClrType(EdmType edmType)
+ {
+ ArgumentNotNull(edmType, "edmType");
+
+ var primitiveType = edmType as PrimitiveType;
+ if (primitiveType != null)
+ {
+ return primitiveType.ClrEquivalentType;
+ }
+
+ if (IsEnumType(edmType))
+ {
+ return GetEnumUnderlyingType(edmType).ClrEquivalentType;
+ }
+
+ return typeof(object);
+ }
+
+ public object GetEnumMemberValue(MetadataItem enumMember)
+ {
+ ArgumentNotNull(enumMember, "enumMember");
+
+ var valueProperty = enumMember.GetType().GetProperty("Value");
+ return valueProperty == null ? null : valueProperty.GetValue(enumMember, null);
+ }
+
+ public string GetEnumMemberName(MetadataItem enumMember)
+ {
+ ArgumentNotNull(enumMember, "enumMember");
+
+ var nameProperty = enumMember.GetType().GetProperty("Name");
+ return nameProperty == null ? null : (string)nameProperty.GetValue(enumMember, null);
+ }
+
+ public System.Collections.IEnumerable GetEnumMembers(EdmType enumType)
+ {
+ ArgumentNotNull(enumType, "enumType");
+
+ var membersProperty = enumType.GetType().GetProperty("Members");
+ return membersProperty != null
+ ? (System.Collections.IEnumerable)membersProperty.GetValue(enumType, null)
+ : Enumerable.Empty();
+ }
+
+ public bool EnumIsFlags(EdmType enumType)
+ {
+ ArgumentNotNull(enumType, "enumType");
+
+ var isFlagsProperty = enumType.GetType().GetProperty("IsFlags");
+ return isFlagsProperty != null && (bool)isFlagsProperty.GetValue(enumType, null);
+ }
+
+ public bool IsEnumType(GlobalItem edmType)
+ {
+ ArgumentNotNull(edmType, "edmType");
+
+ return edmType.GetType().Name == "EnumType";
+ }
+
+ public PrimitiveType GetEnumUnderlyingType(EdmType enumType)
+ {
+ ArgumentNotNull(enumType, "enumType");
+
+ return (PrimitiveType)enumType.GetType().GetProperty("UnderlyingType").GetValue(enumType, null);
+ }
+
+ public string CreateLiteral(object value)
+ {
+ if (value == null || value.GetType() != typeof(TimeSpan))
+ {
+ return _code.CreateLiteral(value);
+ }
+
+ return string.Format(CultureInfo.InvariantCulture, "new TimeSpan({0})", ((TimeSpan)value).Ticks);
+ }
+
+ public bool VerifyCaseInsensitiveTypeUniqueness(IEnumerable types, string sourceFile)
+ {
+ ArgumentNotNull(types, "types");
+ ArgumentNotNull(sourceFile, "sourceFile");
+
+ var hash = new HashSet(StringComparer.InvariantCultureIgnoreCase);
+ if (types.Any(item => !hash.Add(item)))
+ {
+ _errors.Add(
+ new CompilerError(sourceFile, -1, -1, "6023",
+ String.Format(CultureInfo.CurrentCulture, CodeGenerationTools.GetResourceString("Template_CaseInsensitiveTypeConflict"))));
+ return false;
+ }
+ return true;
+ }
+
+ public IEnumerable GetEnumItemsToGenerate(IEnumerable itemCollection)
+ {
+ return GetItemsToGenerate(itemCollection)
+ .Where(e => IsEnumType(e));
+ }
+
+ public IEnumerable GetItemsToGenerate(IEnumerable itemCollection) where T: EdmType
+ {
+ return itemCollection
+ .OfType()
+ .Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName))
+ .OrderBy(i => i.Name);
+ }
+
+ public IEnumerable GetAllGlobalItems(IEnumerable itemCollection)
+ {
+ return itemCollection
+ .Where(i => i is EntityType || i is ComplexType || i is EntityContainer || IsEnumType(i))
+ .Select(g => GetGlobalItemName(g));
+ }
+
+ public string GetGlobalItemName(GlobalItem item)
+ {
+ if (item is EdmType)
+ {
+ return ((EdmType)item).Name;
+ }
+ else
+ {
+ return ((EntityContainer)item).Name;
+ }
+ }
+
+ public IEnumerable GetSimpleProperties(EntityType type)
+ {
+ return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
+ }
+
+ public IEnumerable GetSimpleProperties(ComplexType type)
+ {
+ return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
+ }
+
+ public IEnumerable GetComplexProperties(EntityType type)
+ {
+ return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
+ }
+
+ public IEnumerable