Merge remote-tracking branch 'contributor/feature/SPFx-SocketIO' into dev
|
@ -0,0 +1,163 @@
|
|||
[CmdletBinding()]
|
||||
Param(
|
||||
[Parameter(Mandatory=$True,Position=1)]
|
||||
[string]$SiteUrl,
|
||||
|
||||
[Parameter(Mandatory=$True)]
|
||||
[string]$UserName,
|
||||
|
||||
[Parameter(Mandatory=$True)]
|
||||
[string]$Password
|
||||
)
|
||||
|
||||
$0 = $myInvocation.MyCommand.Definition
|
||||
$CommandDirectory = [System.IO.Path]::GetDirectoryName($0)
|
||||
|
||||
Set-Location $CommandDirectory
|
||||
|
||||
# -----------------------------------------------------
|
||||
# SharePoint Configuration
|
||||
# -----------------------------------------------------
|
||||
|
||||
# Connect to the site
|
||||
$PasswordAsSecure = ConvertTo-SecureString $Password -AsPlainText -Force
|
||||
$Credentials = New-Object System.Management.Automation.PSCredential ($UserName , $PasswordAsSecure)
|
||||
Connect-SPOnline -Url $SiteUrl -Credentials $Credentials
|
||||
|
||||
Write-Host -ForegroundColor Magenta "Apply PnP template to site '$SiteUrl'..."
|
||||
|
||||
# Create the SharePoint list in the dev site
|
||||
Apply-SPOProvisioningTemplate -Path ".\template.xml"
|
||||
|
||||
Write-Host -ForegroundColor Green "Done!"
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Azure Configuration
|
||||
# -----------------------------------------------------
|
||||
|
||||
Write-Host -ForegroundColor Magenta "Login to Azure..."
|
||||
Login-AzureRmAccount
|
||||
|
||||
$GitPublishingUserName = "tempdeployuser" + [Guid]::NewGuid();
|
||||
$GitPublishingUserPassword = "socketio123!"
|
||||
$AzureSBNamespace = "ServiceBus" + [Guid]::NewGuid();
|
||||
$AzureWebAppName = "WebApp" + [Guid]::NewGuid()
|
||||
$AppServicePlanName = "ServicePlan" + [Guid]::NewGuid()
|
||||
$TemplateFilePath = ".\azure-deploy.json"
|
||||
$AzureResourceGroupLocation = "East US2"
|
||||
$AzureResourceGroupName = "SPFxSocketIODemo"
|
||||
$AzureRmResourceGroupDeploymentName = $AzureResourceGroupName
|
||||
$ServerCodeFolderLocation = ".\server"
|
||||
|
||||
# Set the publishing user and password for the local Git deployment
|
||||
$PropertiesObject = @{
|
||||
"publishingUserName" = $GitPublishingUserName;
|
||||
"publishingPassword" = $GitPublishingUserPassword;
|
||||
}
|
||||
|
||||
Try {
|
||||
|
||||
Set-AzureRmResource -PropertyObject $PropertiesObject -ResourceId /providers/Microsoft.Web/publishingUsers/web -ApiVersion 2015-08-01 -Force
|
||||
|
||||
Write-Host -ForegroundColor Magenta "Creating the Azure resource Group [$AzureResourceGroupName]..."
|
||||
New-AzureRmResourceGroup -Name $AzureResourceGroupName -Location $AzureResourceGroupLocation
|
||||
|
||||
# Deploy the Azure Resource Group using an ARM template
|
||||
# More information here: https://azure.microsoft.com/en-us/documentation/articles/resource-group-authoring-templates/#resources
|
||||
|
||||
$TemplateParameters = @{
|
||||
"ServiceBusNameSpace"=$AzureSBNamespace;
|
||||
"AppServicePlanName"= $AppServicePlanName;
|
||||
"SiteName"=$AzureWebAppName;
|
||||
"Location"=$AzureResourceGroupLocation
|
||||
}
|
||||
|
||||
Write-Host -ForegroundColor Magenta "Deploying Azure resources using ARM template..."
|
||||
Test-AzureRmResourceGroupDeployment -ResourceGroupName $AzureResourceGroupName -TemplateFile $TemplateFilePath -TemplateParameterObject $TemplateParameters
|
||||
New-AzureRmResourceGroupDeployment -Name $AzureRmResourceGroupDeploymentName -ResourceGroupName $AzureResourceGroupName -TemplateFile $TemplateFilePath -TemplateParameterObject $TemplateParameters
|
||||
Write-Host -ForegroundColor Green "Done!"
|
||||
|
||||
Write-Host -ForegroundColor Magenta "Updating Web Application settings..."
|
||||
$CurrentNamespace = Get-AzureSBNamespace -Name $AzureSBNamespace
|
||||
|
||||
# Check if the namespace already exists or needs to be created
|
||||
if ($CurrentNamespace) {
|
||||
|
||||
Write-Host -ForegroundColor Magenta "Set application settings for service bus connection..."
|
||||
|
||||
# Set the Web Application settings
|
||||
$AppSettings = New-Object Hashtable
|
||||
$AppSettings["AZURE_SERVICEBUS_ACCESS_KEY"]=$CurrentNamespace.ConnectionString
|
||||
|
||||
# Set application settings and enable WebSockets
|
||||
Set-AzureWebsite -Name $AzureWebAppName -AppSettings $AppSettings
|
||||
} else {
|
||||
|
||||
Write-Warning "Azure Service Bus namespace '$AzureSBNamespace' not found. Make sure you've selected the right Azure subscription (forgot to run the Add-AzureAccount cmdlet?)"
|
||||
}
|
||||
|
||||
Write-Host -ForegroundColor Green "Done!"
|
||||
|
||||
# Deploy the code to the Web Application using Local Git
|
||||
|
||||
# Note: the part below is only valid for this demo. In a real world situation, you may want link to your TFS/GitHub/BitBucket repository instead.
|
||||
# See https://azure.microsoft.com/en-us/documentation/articles/app-service-deploy-local-git/ for more information
|
||||
Write-Host -ForegroundColor Magenta "Deploying the Web Application Node JS code using Local Git..."
|
||||
|
||||
# Go to the location where the code for the server is located and commit/push it to the local git repository of the web application.
|
||||
Push-Location $ServerCodeFolderLocation
|
||||
|
||||
# Remove previous git config if exists
|
||||
if (Test-Path .git) {
|
||||
Remove-Item -Recurse .git -Force
|
||||
}
|
||||
|
||||
git init
|
||||
|
||||
git add -A
|
||||
|
||||
git commit -m "SPFx Socket IO Demo - Server code"
|
||||
|
||||
# Build the git clone URL with embbed password
|
||||
$GitCloneURL = "https://$GitPublishingUserName" + ":$GitPublishingUserPassword@$AzureWebAppName.scm.azurewebsites.net:443/$AzureWebAppName.git"
|
||||
|
||||
# Make sure there is no 502 error and the git URL is up and running (can take few seconds)
|
||||
$Timeout = New-TimeSpan -Minutes 1
|
||||
$sw = [Diagnostics.Stopwatch]::StartNew()
|
||||
|
||||
Write-Host -ForegroundColor Yellow "Wait for the git clone URL is up and running" -NoNewline
|
||||
while ($sw.elapsed -lt $Timeout) {
|
||||
|
||||
if ((Invoke-WebRequest -Uri $GitCloneURL).StatusCode -eq 200) {
|
||||
|
||||
Write-Host "`n"
|
||||
|
||||
git remote add azure $GitCloneURL 2>&1 | %{ "$_" }
|
||||
|
||||
# We force the push to overwrite remote with local files avoiding update conflicts (don't use this in production)
|
||||
|
||||
git push azure master --force 2>&1 | %{ "$_" }
|
||||
|
||||
# Update URLs in the client side code according to the web app name
|
||||
|
||||
Pop-Location
|
||||
|
||||
$files = @(".\client\config\config.json",".\client\src\webparts\realTimeNewsFeed\components\RealTimeNewsFeed.tsx")
|
||||
$files | ForEach-Object { (Get-Content $_) -replace 'https:\/\/(\S*)\.azurewebsites\.net', "https://$AzureWebAppName.azurewebsites.net" | Set-Content $_ }
|
||||
|
||||
Write-Host -ForegroundColor Green "Done!"
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds 5
|
||||
Write-Host -ForegroundColor Yellow "."
|
||||
}
|
||||
Write-Warning "The git clone URL timed out!"
|
||||
|
||||
} Catch {
|
||||
|
||||
$ErrorMessage = $_.Exception.Message
|
||||
Write-Error $ErrorMessage
|
||||
Exit
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
# Real Time News Feed using Microsoft Flow, Azure and socket.io #
|
||||
|
||||
## Summary
|
||||
|
||||
This sample shows you how to implement real time web parts using the SPFx, Microsoft Flow and [socket.io](http://socket.io/).
|
||||
|
||||
<p align="center">
|
||||
<img width="900" src="./assets/animated-demo.gif"/>
|
||||
</p>
|
||||
|
||||
### Solution Architecture ###
|
||||
|
||||
Here is the solution overview:
|
||||
|
||||
<p align="center">
|
||||
<img width="600" src="./assets/solution_overview.png"/>
|
||||
</p>
|
||||
|
||||
1. The SPFx Web Part first connects to the Azure web application via socket.io and subscribes to events (the web application have to be in https and allow cross domain calls (CORS)).
|
||||
2. Microsoft Flow is used to catch new item creation events in the SharPoint list.
|
||||
3. When an item is added, the flow sends its id to an Azure service bus queue using JSON format.
|
||||
4. A Node JS Azure web application listens to the queue and check for new messages every 5 ms.
|
||||
5. When a new message is available, the web application emits the data to all subscribers via socket.io.
|
||||
6. The SPFx Web Part notifies user there are new items available. Items are effectively retrieved via REST according to received ids when the user clicks on the notification.
|
||||
|
||||
## Applies to
|
||||
|
||||
* [SharePoint Framework Developer Preview](http://dev.office.com/sharepoint/docs/spfx/sharepoint-framework-overview)
|
||||
* [Office 365 developer tenant](http://dev.office.com/sharepoint/docs/spfx/set-up-your-developer-tenant)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting, you'll need to install some prerequisites:
|
||||
|
||||
- Install the [Azure PowerShell SDK](https://azure.microsoft.com/en-us/documentation/articles/powershell-install-configure/). Make sure you've installed the AzureRM module as well.
|
||||
Run the `Add-AzureAccount` cmdlet and optionaly select the correct Azure subscription to work with by running the `Select-AzureSubscription` cmdlet.
|
||||
- Install the latest release of [PnP PowerShell cmdlets 'SharePointPnPPowerShellOnline'](https://github.com/OfficeDev/PnP-PowerShell/releases) or a version compatible with the 201605 PnP schema version.
|
||||
- Install [Node.js](https://nodejs.org/en/) on your machine.
|
||||
- Install [Git for Windows](https://git-scm.com/download/win).
|
||||
- Get the [latest version](https://dev.office.com/sharepoint/docs/spfx/set-up-your-development-environment) of the SharePoint Framework yeoman generator (in this case **SPFx Drop 5**) and make sure TypeScript 2.0 is available on your machine (`npm install -g typescript@latest`).
|
||||
- Create a site collection with the developer template.
|
||||
- Go to the ".\client" folder and install all dependencies listed in the package.json file by running the `npm install` cmd.
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
react-real-time | Franck Cornu (MVP, [@franckcornu](https://twitter.com/FranckCornu))
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.0|October 25, 2016 | Initial commit
|
||||
|
||||
## Disclaimer
|
||||
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
|
||||
|
||||
---
|
||||
|
||||
## Minimal Path to Awesome
|
||||
|
||||
1. Download the source code as ZIP from GitHub and extract it to your destination folder
|
||||
2. On a remote machine (basically, where PnP & Azure cmdlets are installed), start new PowerShell session as an **administrator** an call the `Deploy-Solution.ps1` script with your parameters like this:
|
||||
|
||||
```csharp
|
||||
$UserName = "username@<your_tenant>.onmicrosoft.com"
|
||||
$Password = "<your_password>"
|
||||
$SiteUrl = "https://<your_tenant>.sharepoint.com/sites/<your_developer_site_collection>"
|
||||
|
||||
Set-Location "<extracted_solution_root_folder>\samples\react-socket-io"
|
||||
|
||||
$Script = ".\Deploy-Solution.ps1"
|
||||
& $Script -SiteUrl $SiteUrl -UserName $UserName -Password $Password
|
||||
|
||||
```
|
||||
|
||||
It will configure the targeted SharePoint site and create the Azure resource group for the server part using an Azure Resource Manager template (JSON file).
|
||||
|
||||
**IMPORTANT NOTES**
|
||||
|
||||
It is recommended to deploy this solution on a test Azure subscription because by default, the script will override the local git deployment credentials configured for your subscription (for the web application provisioning).
|
||||
If you want to set you own parameters, update the `Deploy-Solution.ps1` script and replace tokens with your desired configuration.
|
||||
Notice that some values have to be unique within the whole Azure platform (for instance the web application name, the deployment user name, etc.), that's why we use a random guid each time.
|
||||
|
||||
|
||||
```ps
|
||||
|
||||
# -----------------------------------------------------
|
||||
# Azure Configuration
|
||||
# -----------------------------------------------------
|
||||
|
||||
Write-Host -ForegroundColor Magenta "Login to Azure..."
|
||||
Login-AzureRmAccount
|
||||
|
||||
$GitPublishingUserName = "tempdeployuser" + [Guid]::NewGuid();
|
||||
$GitPublishingUserPassword = "socketio123!"
|
||||
$AzureSBNamespace = "ServiceBus" + [Guid]::NewGuid();
|
||||
$AzureWebAppName = "WebApp" + [Guid]::NewGuid()
|
||||
$AppServicePlanName = "ServicePlan" + [Guid]::NewGuid()
|
||||
$TemplateFilePath = ".\azure-deploy.json"
|
||||
$AzureResourceGroupLocation = "East US2"
|
||||
$AzureResourceGroupName = "SPFxSocketIODemo"
|
||||
$AzureRmResourceGroupDeploymentName = $AzureResourceGroupName
|
||||
$ServerCodeFolderLocation = ".\server"
|
||||
|
||||
```
|
||||
3. When prompted, enter your Azure credentials
|
||||
4. Wait for the installation to finish. It can take several minutes to complete due to the npm packages installation on the Azure web application.
|
||||
5. Go to the ".\client" folder and run the `gulp serve` cmd to launch the SharePoint Workbench on localhost. Open the network panel in developer console and make sure the Azure web application can be reached.
|
||||
|
||||
<p align="center">
|
||||
<img width="600" src="./assets/network-console.png"/>
|
||||
</p>
|
||||
|
||||
You can let the `gulp serve` cmd running.
|
||||
|
||||
6. Because there is no automated mechanism to provision new template in the Microsoft Flow application, you have to manually create the flow on the SharePoint list in your developer site.
|
||||
Go the 'NewsList' and create a new flow from scratch and add the following steps:
|
||||
|
||||
- **[Condition]** *"SharePoint - When a new item is created"*
|
||||
- **[Action]** *"Service Bus - Send Message"*
|
||||
|
||||
<p align="center">
|
||||
<img width="400" src="./assets/flow.png"/>
|
||||
</p>
|
||||
|
||||
**TIP**
|
||||
|
||||
The first time you will add the "Service bus - Send Message" action, you will asked to enter the service bus connection string:
|
||||
|
||||
<p align="center">
|
||||
<img width="400" src="./assets/service-bus-new-connection.png"/>
|
||||
</p>
|
||||
|
||||
To get it, go to your Azure portal and select the "*SPFxSocketIODemo*" resource group and click on the service bus resource.
|
||||
From here your will be able to get the primary connection string:
|
||||
|
||||
<p align="center">
|
||||
<img width="600" src="./assets/service-bus.png"/>
|
||||
</p>
|
||||
|
||||
7. Go back to your list and add initial items in the list.
|
||||
8. In your SharePoint site, [upload the workbench.aspx page](https://dev.office.com/sharepoint/docs/spfx/set-up-your-developer-tenant) in the *Documents* library and make sure the `gulp serve` cmd is running. Then, add the *"RealTimeNewsFeed"* Web Part in your page. You should see newly created items.
|
||||
|
||||
<p align="center">
|
||||
<img width="400" src="./assets/spfx-initial.png"/>
|
||||
</p>
|
||||
|
||||
9. Go back to your list and create some others items. Because of the flow is asynchronous, you should see new items appear after few seconds (between 5 and 30 seconds) on the opened Workbench page.
|
||||
|
||||
<p align="center">
|
||||
<img width="400" src="./assets/spfx-newitem.png"/>
|
||||
</p>
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
This Web Part illustrates the following concepts on top of the SharePoint Framework:
|
||||
|
||||
- Using web sockets through the socket.io library to implement real time communications between SharePoint Web Parts and an Azure back end server.
|
||||
- Using PnP JS library (1.0.5) to get items from a list.
|
||||
- Using Office UI Fabric React components to build a beautiful design in minutes.
|
||||
|
||||
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-socket-io" />
|
After Width: | Height: | Size: 499 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 152 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 40 KiB |
|
@ -0,0 +1,152 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"ServiceBusNameSpace": {
|
||||
"defaultValue": "",
|
||||
"type": "string"
|
||||
},
|
||||
"AppServicePlanName": {
|
||||
"defaultValue": "",
|
||||
"type": "string"
|
||||
},
|
||||
"SiteName": {
|
||||
"defaultValue": "",
|
||||
"type": "string"
|
||||
},
|
||||
"AuthorizationRules_RootManageSharedAccessKey_name": {
|
||||
"defaultValue": "[concat(parameters('ServiceBusNameSpace'),'/RootManageSharedAccessKey')]",
|
||||
"type": "string"
|
||||
},
|
||||
"Location": {
|
||||
"defaultValue": "East US2",
|
||||
"type": "string"
|
||||
},
|
||||
"ServiceBusQueueName": {
|
||||
"defaultValue": "news",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"variables": {},
|
||||
"resources": [
|
||||
{
|
||||
"comments": "",
|
||||
"type": "Microsoft.ServiceBus/namespaces",
|
||||
"sku": {
|
||||
"name": "Basic",
|
||||
"tier": "Basic"
|
||||
},
|
||||
"kind": "Messaging",
|
||||
"name": "[parameters('ServiceBusNameSpace')]",
|
||||
"apiVersion": "2015-08-01",
|
||||
"location": "[parameters('Location')]",
|
||||
"tags": {},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2015-08-01",
|
||||
"name": "[parameters('ServiceBusQueueName')]",
|
||||
"type": "queues",
|
||||
"location": "[parameters('Location')]",
|
||||
"dependsOn": [
|
||||
"[concat('Microsoft.ServiceBus/namespaces/', parameters('ServiceBusNameSpace'))]"
|
||||
],
|
||||
"properties": {
|
||||
"path": "[parameters('ServiceBusQueueName')]",
|
||||
"defaultMessageTimeToLive": "14.00:00:00"
|
||||
}
|
||||
}
|
||||
],
|
||||
"dependsOn": []
|
||||
},
|
||||
{
|
||||
"comments": "",
|
||||
"type": "Microsoft.Web/serverfarms",
|
||||
"sku": {
|
||||
"name": "B1",
|
||||
"tier": "Basic",
|
||||
"size": "B1",
|
||||
"family": "B",
|
||||
"capacity": 1
|
||||
},
|
||||
"name": "[parameters('AppServicePlanName')]",
|
||||
"apiVersion": "2015-08-01",
|
||||
"location": "[parameters('Location')]",
|
||||
"properties": {
|
||||
"name": "[parameters('AppServicePlanName')]",
|
||||
"numberOfWorkers": 1
|
||||
},
|
||||
"resources": [],
|
||||
"dependsOn": []
|
||||
},
|
||||
{
|
||||
"comments": "",
|
||||
"type": "Microsoft.Web/sites",
|
||||
"name": "[parameters('SiteName')]",
|
||||
"apiVersion": "2015-08-01",
|
||||
"location": "[parameters('Location')]",
|
||||
"tags": {
|
||||
},
|
||||
"properties": {
|
||||
"name": "[parameters('SiteName')]",
|
||||
"hostNames": [
|
||||
"[concat(parameters('SiteName'),'.azurewebsites.net')]"
|
||||
],
|
||||
"enabledHostNames": [
|
||||
"[concat(parameters('SiteName'),'.azurewebsites.net')]",
|
||||
"[concat(parameters('SiteName'),'.scm.azurewebsites.net')]"
|
||||
],
|
||||
"hostNameSslStates": [
|
||||
{
|
||||
"name": "[concat(parameters('SiteName'),'.azurewebsites.net')]",
|
||||
"sslState": 0,
|
||||
"thumbprint": null,
|
||||
"ipBasedSslState": 0
|
||||
},
|
||||
{
|
||||
"name": "[concat(parameters('SiteName'),'.scm.azurewebsites.net')]",
|
||||
"sslState": 0,
|
||||
"thumbprint": null,
|
||||
"ipBasedSslState": 0
|
||||
}
|
||||
],
|
||||
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('AppServicePlanName'))]"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2015-08-01",
|
||||
"location": "[parameters('Location')]",
|
||||
"name": "web",
|
||||
"type": "config",
|
||||
"properties": {
|
||||
"scmType": "LocalGit",
|
||||
"webSocketsEnabled": true,
|
||||
"phpVersion": " "
|
||||
},
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Web/sites', parameters('SiteName'))]"
|
||||
]
|
||||
}
|
||||
],
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Web/serverfarms', parameters('AppServicePlanName'))]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"comments": "",
|
||||
"type": "Microsoft.ServiceBus/namespaces/AuthorizationRules",
|
||||
"name": "[parameters('AuthorizationRules_RootManageSharedAccessKey_name')]",
|
||||
"apiVersion": "2015-08-01",
|
||||
"properties": {
|
||||
"rights": [
|
||||
"Listen",
|
||||
"Manage",
|
||||
"Send"
|
||||
]
|
||||
},
|
||||
"resources": [],
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.ServiceBus/namespaces', parameters('ServiceBusNameSpace'))]"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
|
||||
[*]
|
||||
|
||||
# change these settings to your own preference
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# we recommend you to keep these unchanged
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[{package,bower}.json]
|
||||
indent_style = space
|
||||
indent_size = 2
|
|
@ -0,0 +1 @@
|
|||
* text=auto
|
|
@ -0,0 +1,32 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules
|
||||
|
||||
# Build generated files
|
||||
dist
|
||||
lib
|
||||
solution
|
||||
temp
|
||||
*.spapp
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# OSX
|
||||
.DS_Store
|
||||
|
||||
# Visual Studio files
|
||||
.ntvs_analysis.dat
|
||||
.vs
|
||||
bin
|
||||
obj
|
||||
|
||||
# Resx Generated Code
|
||||
*.resx.ts
|
||||
|
||||
# Styles Generated Code
|
||||
*.scss.ts
|
|
@ -0,0 +1,14 @@
|
|||
# Folders
|
||||
.vscode
|
||||
coverage
|
||||
node_modules
|
||||
sharepoint
|
||||
src
|
||||
temp
|
||||
|
||||
# Files
|
||||
*.csproj
|
||||
.git*
|
||||
.yo-rc.json
|
||||
gulpfile.js
|
||||
tsconfig.json
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"libraryName": "spfx-socket-io",
|
||||
"libraryId": "a89569d5-e511-4f93-8cba-eabdd0567ee5",
|
||||
"framework": "react"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"entries": [
|
||||
{
|
||||
"entry": "./lib/webparts/realTimeNewsFeed/RealTimeNewsFeedWebPart.js",
|
||||
"manifest": "./src/webparts/realTimeNewsFeed/RealTimeNewsFeedWebPart.manifest.json",
|
||||
"outputPath": "./dist/real-time-news-feed.bundle.js"
|
||||
}
|
||||
],
|
||||
"externals": {
|
||||
"@microsoft/sp-client-base": "node_modules/@microsoft/sp-client-base/dist/sp-client-base.js",
|
||||
"@microsoft/sp-client-preview": "node_modules/@microsoft/sp-client-preview/dist/sp-client-preview.js",
|
||||
"@microsoft/sp-lodash-subset": "node_modules/@microsoft/sp-lodash-subset/dist/sp-lodash-subset.js",
|
||||
"office-ui-fabric-react": "node_modules/office-ui-fabric-react/dist/office-ui-fabric-react.js",
|
||||
"react": "node_modules/react/dist/react.min.js",
|
||||
"react-dom": "node_modules/react-dom/dist/react-dom.min.js",
|
||||
"react-dom/server": "node_modules/react-dom/dist/react-dom-server.min.js",
|
||||
"socket.io-client": "https://SPFxSocketIOWebAppdde17113-805a-4806-b5e6-43dbb5f61b9f.azurewebsites.net/socket.io/socket.io.js"
|
||||
},
|
||||
"localizedResources": {
|
||||
"realTimeNewsFeedStrings": "webparts/realTimeNewsFeed/loc/{locale}.js"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"workingDir": "./temp/deploy/",
|
||||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "spfx-socket-io",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"solution": {
|
||||
"name": "spfx-socket-io-client-side-solution",
|
||||
"id": "a89569d5-e511-4f93-8cba-eabdd0567ee5",
|
||||
"version": "1.0.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/spfx-socket-io.spapp"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"deployCdnPath": "temp/deploy"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"port": 4321,
|
||||
"initialPage": "https://localhost:5432/workbench",
|
||||
"https": true,
|
||||
"api": {
|
||||
"port": 5432,
|
||||
"entryPath": "node_modules/@microsoft/sp-webpart-workbench/lib/api/"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
// Display errors as warnings
|
||||
"displayAsWarning": true,
|
||||
// The TSLint task may have been configured with several custom lint rules
|
||||
// before this config file is read (for example lint rules from the tslint-microsoft-contrib
|
||||
// project). If true, this flag will deactivate any of these rules.
|
||||
"removeExistingRules": true,
|
||||
// When true, the TSLint task is configured with some default TSLint "rules.":
|
||||
"useDefaultConfigAsBase": false,
|
||||
// Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules
|
||||
// which are active, other than the list of rules below.
|
||||
"lintConfig": {
|
||||
// Opt-in to Lint rules which help to eliminate bugs in JavaScript
|
||||
"rules": {
|
||||
"class-name": false,
|
||||
"export-name": false,
|
||||
"forin": false,
|
||||
"label-position": false,
|
||||
"label-undefined": false,
|
||||
"member-access": true,
|
||||
"no-arg": false,
|
||||
"no-console": false,
|
||||
"no-construct": false,
|
||||
"no-duplicate-case": true,
|
||||
"no-duplicate-key": false,
|
||||
"no-duplicate-variable": true,
|
||||
"no-eval": false,
|
||||
"no-function-expression": true,
|
||||
"no-internal-module": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-unnecessary-semicolons": true,
|
||||
"no-unused-expression": true,
|
||||
"no-unused-imports": true,
|
||||
"no-unused-variable": true,
|
||||
"no-unreachable": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-with-statement": true,
|
||||
"semicolon": true,
|
||||
"trailing-comma": false,
|
||||
"typedef": false,
|
||||
"typedef-whitespace": false,
|
||||
"use-named-parameter": true,
|
||||
"valid-typeof": true,
|
||||
"variable-name": false,
|
||||
"whitespace": false,
|
||||
"prefer-const": true,
|
||||
"a11y-role": true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const gulp = require('gulp');
|
||||
const build = require('@microsoft/sp-build-web');
|
||||
|
||||
build.initialize(gulp);
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "spfx-socket-io",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"author": {
|
||||
"name": "Franck Cornu @FranckCornu (http://thecollaborationcorner.com)"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-client-base": "~0.4.0",
|
||||
"@microsoft/sp-client-preview": "~0.5.0",
|
||||
"@types/pluralize": "0.0.27",
|
||||
"@types/socket.io-client": "^1.4.27",
|
||||
"office-ui-fabric-react": "0.36.0",
|
||||
"pluralize": "^3.0.0",
|
||||
"react": "0.14.8",
|
||||
"react-addons-update": "^15.3.2",
|
||||
"react-dom": "0.14.8",
|
||||
"socket.io-client": "^1.5.0",
|
||||
"sp-pnp-js": "^1.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "~0.7.0",
|
||||
"@microsoft/sp-module-interfaces": "~0.4.0",
|
||||
"@microsoft/sp-webpart-workbench": "~0.5.0",
|
||||
"gulp": "~3.9.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp nuke",
|
||||
"test": "gulp test"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Gulp" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{a89569d5-e511-4f93-8cba-eabdd0567ee5}</ProjectGuid>
|
||||
<ProjectHome />
|
||||
<ProjectView>ProjectFiles</ProjectView>
|
||||
<StartupFile>node_modules\gulp\bin\gulp.js</StartupFile>
|
||||
<WorkingDirectory>.</WorkingDirectory>
|
||||
<OutputPath>.</OutputPath>
|
||||
<ProjectTypeGuids>{3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}</ProjectTypeGuids>
|
||||
<TypeScriptSourceMap>true</TypeScriptSourceMap>
|
||||
<TypeScriptModuleKind>CommonJS</TypeScriptModuleKind>
|
||||
<EnableTypeScript>false</EnableTypeScript>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
<ScriptArguments>serve</ScriptArguments>
|
||||
<StartWebBrowser>True</StartWebBrowser>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'" />
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'" />
|
||||
<Target Name="Gulp">
|
||||
<Message Text="Running gulp2vs.js" Importance="normal" />
|
||||
<Exec Command="node.exe "$(MSBuildThisFileDirectory)\node_modules\@microsoft\npmx-lib\lib\gulp2vs.js"" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<Content Include="*.js" />
|
||||
<Content Include="*.json" />
|
||||
<Content Include="*.md" />
|
||||
<Content Include="config\**\*.json" />
|
||||
<Content Include="docs\*.md" />
|
||||
<Content Include="sharepoint\feature_xml\**\*.*" />
|
||||
<Content Include="src\**\*.html" />
|
||||
<Content Include="src\**\*.js" />
|
||||
<Content Include="src\**\*.json" />
|
||||
<Content Include="src\**\*.less" />
|
||||
<Content Include="src\**\*.resx" />
|
||||
<Content Include="src\**\*.scss" />
|
||||
<Content Include="src\**\*.ts" />
|
||||
<Content Include="src\**\*.tsx" />
|
||||
<Content Include="typings\**\*.ts" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<!--Do not delete the following Import Project. While this appears to do nothing it is a marker for setting TypeScript properties before our import that depends on them.-->
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets" Condition="False" />
|
||||
<Import Project="$(VSToolsPath)\Node.js Tools\Microsoft.NodejsTools.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
|
||||
<WebProjectProperties>
|
||||
<UseIIS>False</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>0</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:48022/</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>True</UseCustomServer>
|
||||
<CustomServerUrl>http://localhost:1337</CustomServerUrl>
|
||||
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
|
||||
</WebProjectProperties>
|
||||
</FlavorProperties>
|
||||
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}" User="">
|
||||
<WebProjectProperties>
|
||||
<StartPageUrl>
|
||||
</StartPageUrl>
|
||||
<StartAction>CurrentPage</StartAction>
|
||||
<AspNetDebugging>True</AspNetDebugging>
|
||||
<SilverlightDebugging>False</SilverlightDebugging>
|
||||
<NativeDebugging>False</NativeDebugging>
|
||||
<SQLDebugging>False</SQLDebugging>
|
||||
<ExternalProgram>
|
||||
</ExternalProgram>
|
||||
<StartExternalURL>
|
||||
</StartExternalURL>
|
||||
<StartCmdLineArguments>
|
||||
</StartCmdLineArguments>
|
||||
<StartWorkingDirectory>
|
||||
</StartWorkingDirectory>
|
||||
<EnableENC>False</EnableENC>
|
||||
<AlwaysStartWebServerOnDebug>False</AlwaysStartWebServerOnDebug>
|
||||
</WebProjectProperties>
|
||||
</FlavorProperties>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
|
@ -0,0 +1,5 @@
|
|||
var context = require.context('.', true, /.+\.test\.js?$/);
|
||||
|
||||
context.keys().forEach(context);
|
||||
|
||||
module.exports = context;
|
|
@ -0,0 +1,3 @@
|
|||
export interface IRealTimeNewsFeedWebPartProps {
|
||||
listTitle: string;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
import { INewsItem } from './RealTimeNewsFeedWebPart';
|
||||
|
||||
export default class MockHttpClient {
|
||||
|
||||
private static _items: INewsItem[] = [
|
||||
{ Title: 'News Item 1',
|
||||
Id: 1,
|
||||
Description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||
PreviewImageUrl: { Url:'http://placehold.it/50x50', Description: "Dummy placeholder" }
|
||||
},
|
||||
{ Title: 'News Item 2',
|
||||
Id: 1,
|
||||
Description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||
PreviewImageUrl: { Url:'http://placehold.it/50x50', Description: "Dummy placeholder" }
|
||||
},
|
||||
{ Title: 'News Item 2',
|
||||
Id: 1,
|
||||
Description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
||||
PreviewImageUrl: { Url:'http://placehold.it/50x50', Description: "Dummy placeholder" }
|
||||
}
|
||||
];
|
||||
|
||||
public static get(restUrl: string): Promise<INewsItem[]> {
|
||||
return new Promise<INewsItem[]>((resolve) => {
|
||||
setTimeout(()=> {
|
||||
resolve(MockHttpClient._items);
|
||||
}, 3000);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
.ms-newsFeed-itemCell {
|
||||
min-height: 54px;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid #eaeaea;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
outline: transparent;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ms-Fabric.is-focusVisible .ms-newsFeed-itemCell:focus:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
border: 1px solid #666666;
|
||||
}
|
||||
|
||||
.ms-newsFeed-itemCell:hover {
|
||||
background: #EEE;
|
||||
}
|
||||
|
||||
.ms-newsFeed-itemImage {
|
||||
-ms-flex-negative: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ms-newsFeed-itemContent {
|
||||
overflow: hidden;
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex-positive: 1;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
html {
|
||||
&[dir=ltr] .ms-newsFeed-itemContent {
|
||||
margin-left: 10px;
|
||||
}
|
||||
&[dir=rtl] .ms-newsFeed-itemContent {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.ms-newsFeed-itemName {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ms-newsFeed-itemIndex {
|
||||
font-size: 12px;
|
||||
color: #a6a6a6;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ms-newsFeed-chevron {
|
||||
-ms-flex-item-align: center;
|
||||
align-self: center;
|
||||
color: #a6a6a6;
|
||||
font-size: 17px;
|
||||
-ms-flex-negative: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
&[dir=ltr] .ms-newsFeed-chevron {
|
||||
margin-left: 10px;
|
||||
}
|
||||
&[dir=rtl] .ms-newsFeed-chevron {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.ms-notificationCallout-callout {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.ms-notificationCallout-inner {
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.ms-notificationCallout-subText {
|
||||
margin: 0;
|
||||
font-family: "Segoe UI WestEuropean","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: table;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
|
||||
|
||||
"id": "bd6bb470-57d5-4061-88f9-58d25d095f73",
|
||||
"componentType": "WebPart",
|
||||
"version": "0.0.1",
|
||||
"manifestVersion": 2,
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "bd6bb470-57d5-4061-88f9-58d25d095f73",
|
||||
"group": { "default": "SPFx Demo" },
|
||||
"title": { "default": "RealTimeNewsFeed" },
|
||||
"description": { "default": "A real time SharePoint news feed using Socket IO, Azure Service Bus and Microsoft Flow" },
|
||||
"officeFabricIconFontName": "Page",
|
||||
"properties": {
|
||||
"listTitle": "NewsList"
|
||||
}
|
||||
}]
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDom from 'react-dom';
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneSettings,
|
||||
IWebPartContext,
|
||||
PropertyPaneTextField
|
||||
} from '@microsoft/sp-client-preview';
|
||||
|
||||
import * as strings from 'realTimeNewsFeedStrings';
|
||||
import RealTimeNewsFeed, { IRealTimeNewsFeedProps } from './components/RealTimeNewsFeed';
|
||||
import { IRealTimeNewsFeedWebPartProps } from './IRealTimeNewsFeedWebPartProps';
|
||||
|
||||
// Corresponds to the SharePoint site column internal names for a news item
|
||||
export interface INewsItem {
|
||||
Title: string;
|
||||
Id: number;
|
||||
Description: string,
|
||||
PreviewImageUrl: any
|
||||
}
|
||||
|
||||
export interface IList {
|
||||
Title: string;
|
||||
}
|
||||
|
||||
export default class RealTimeNewsFeedWebPart extends BaseClientSideWebPart<IRealTimeNewsFeedWebPartProps> {
|
||||
|
||||
public constructor(context: IWebPartContext) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public render(): void {
|
||||
const element: React.ReactElement<IRealTimeNewsFeedProps> = React.createElement(RealTimeNewsFeed, {
|
||||
listTitle: this.properties.listTitle,
|
||||
environmentType: this.context.environment.type,
|
||||
siteUrl: this.context.pageContext.web.absoluteUrl,
|
||||
});
|
||||
|
||||
ReactDom.render(element, this.domElement);
|
||||
}
|
||||
|
||||
protected get propertyPaneSettings(): IPropertyPaneSettings {
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
header: {
|
||||
description: strings.PropertyPaneDescription
|
||||
},
|
||||
groups: [
|
||||
{
|
||||
groupName: strings.BasicGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneTextField('listTitle', {
|
||||
label: strings.ListTitleFieldLabel
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,260 @@
|
|||
import * as React from 'react';
|
||||
import styles from '../RealTimeNewsFeed.module.scss';
|
||||
import { IRealTimeNewsFeedWebPartProps } from '../IRealTimeNewsFeedWebPartProps';
|
||||
import { INewsItem } from '../RealTimeNewsFeedWebPart';
|
||||
import {
|
||||
Spinner,
|
||||
Link,
|
||||
MessageBar,
|
||||
MessageBarType,
|
||||
FocusZone,
|
||||
FocusZoneDirection,
|
||||
Image,
|
||||
ImageFit,
|
||||
List,
|
||||
Callout,
|
||||
DirectionalHint, } from 'office-ui-fabric-react';
|
||||
import MockHttpClient from '../MockHttpClient';
|
||||
import { EnvironmentType } from '@microsoft/sp-client-base';
|
||||
import { Web } from 'sp-pnp-js';
|
||||
import * as io from 'socket.io-client';
|
||||
import * as _ from 'lodash';
|
||||
import * as pluralize from 'pluralize';
|
||||
|
||||
const update = require("react-addons-update");
|
||||
|
||||
export interface IRealTimeNewsFeedProps extends IRealTimeNewsFeedWebPartProps {
|
||||
environmentType: EnvironmentType;
|
||||
siteUrl: string;
|
||||
listTitle: string;
|
||||
}
|
||||
|
||||
export interface IRealTimeNewsFeedState {
|
||||
items?: INewsItem[];
|
||||
addedItems?: string[];
|
||||
error?: boolean;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
export default class RealTimeNewsFeed extends React.Component<IRealTimeNewsFeedProps, IRealTimeNewsFeedState> {
|
||||
|
||||
private _listElement: HTMLElement;
|
||||
|
||||
constructor(props: IRealTimeNewsFeedProps) {
|
||||
super(props);
|
||||
|
||||
// Equals to getInitialState
|
||||
this.state = {
|
||||
items: [],
|
||||
addedItems: [],
|
||||
error: false,
|
||||
loading: true
|
||||
};
|
||||
|
||||
// Define event handlers
|
||||
this._onItemAdded = this._onItemAdded.bind(this);
|
||||
this._getAvailableItemsAsync = this._getAvailableItemsAsync.bind(this);
|
||||
}
|
||||
|
||||
public componentDidMount(): void {
|
||||
|
||||
// Connect to the server
|
||||
const socket = io("https://SPFxSocketIOWebAppdde17113-805a-4806-b5e6-43dbb5f61b9f.azurewebsites.net");
|
||||
|
||||
// Add the socket io listeners
|
||||
socket.on('item:added', (data) => {
|
||||
this._onItemAdded(data.customProperties.id);
|
||||
});
|
||||
|
||||
// Fetch initial data
|
||||
this._getItemsAsync();
|
||||
}
|
||||
|
||||
public componentWillReceiveProps(): void {
|
||||
|
||||
// Invoked when a property is updated is the Web Part property panel
|
||||
this._getItemsAsync();
|
||||
}
|
||||
|
||||
public render(): JSX.Element {
|
||||
|
||||
let newItemNotification: JSX.Element = null;
|
||||
|
||||
if (this.state.addedItems.length > 0 ) {
|
||||
|
||||
newItemNotification =
|
||||
<Callout
|
||||
className={ styles['ms-notificationCallout-callout'] + ' ms-u-fadeIn500' }
|
||||
targetElement={ this._listElement }
|
||||
isBeakVisible = { false }
|
||||
directionalHint={ DirectionalHint.bottomCenter }>
|
||||
<div className={ styles['ms-notificationCallout-inner'] }>
|
||||
<div className={ styles['ms-notificationCallout-content'] }>
|
||||
<p className={ styles['ms-notificationCallout-subText'] }>
|
||||
<Link onClick={ this._getAvailableItemsAsync }>
|
||||
{ this.state.addedItems.length } new { pluralize("item", this.state.addedItems.length)} available </Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Callout>;
|
||||
}
|
||||
|
||||
const loading: JSX.Element = this.state.loading ? <Spinner label='Loading items...' /> : <div/>;
|
||||
|
||||
const newsList: JSX.Element =
|
||||
|
||||
<FocusZone direction={ FocusZoneDirection.vertical }>
|
||||
<div ref={ (listElementAnchor) => this._listElement = listElementAnchor } ></div>
|
||||
<List
|
||||
items={ this.state.items }
|
||||
renderCount={ 10 }
|
||||
onRenderCell={ (item, index) => (
|
||||
<div className={ styles['ms-newsFeed-itemCell'] + ' ms-u-fadeIn500' } data-is-focusable={ true }>
|
||||
<Image
|
||||
className='ms-newsFeed-itemImage'
|
||||
src= { item.PreviewImageUrl ? item.PreviewImageUrl.Url : 'http://placehold.it/50x50' }
|
||||
width={ 50 }
|
||||
height={ 50 }
|
||||
imageFit={ ImageFit.cover }
|
||||
/>
|
||||
<div className={ styles['ms-newsFeed-itemContent'] }>
|
||||
<div className={ styles['ms-newsFeed-itemName ms-font-xl']} >{ item.Title }</div>
|
||||
<div className={ styles['ms-newsFeed-itemIndex'] }>{ `Item ${ index }` }</div>
|
||||
<div className={ styles['ms-newsFeed-itemDesc ms-font-s']}>{ item.Description }</div>
|
||||
</div>
|
||||
</div>
|
||||
) }
|
||||
/>
|
||||
</FocusZone>;
|
||||
|
||||
const error: JSX.Element = this.state.error ?
|
||||
<MessageBar messageBarType={ MessageBarType.error }>{ this.state.error }</MessageBar> : <div/>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{error}
|
||||
{newItemNotification}
|
||||
<div className={styles.center}>
|
||||
{loading}
|
||||
</div>
|
||||
{newsList}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/* Event Handlers */
|
||||
private _onItemAdded(id: string): void {
|
||||
|
||||
// Check if the id is not present in current displayed items
|
||||
if(!_(this.state.items).find((e) => {return e.Id === parseInt(id);})) {
|
||||
|
||||
let updatedItems = this.state.addedItems;
|
||||
updatedItems.push(id);
|
||||
|
||||
this.setState({
|
||||
addedItems: updatedItems
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* Async functions */
|
||||
private _getItemsAsync(): void {
|
||||
|
||||
// Local environment
|
||||
if (this.props.environmentType === EnvironmentType.Local) {
|
||||
this._getMockedNewsItems().then((response) => {
|
||||
this.setState({
|
||||
items: response,
|
||||
error: null,
|
||||
loading: false
|
||||
});
|
||||
});
|
||||
} else {
|
||||
|
||||
// SharePoint environment (Classic or Modern Page experience)
|
||||
this._getNewsItems()
|
||||
.then((response) => {
|
||||
this.setState({
|
||||
items: response,
|
||||
error: null,
|
||||
loading: false
|
||||
});
|
||||
}).catch((errorMsg) => {
|
||||
this.setState({
|
||||
items: [],
|
||||
error: errorMsg,
|
||||
loading: false
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _getAvailableItemsAsync(): void {
|
||||
|
||||
// Local environment
|
||||
if (this.props.environmentType !== EnvironmentType.Local) {
|
||||
|
||||
this.setState({
|
||||
addedItems: [],
|
||||
loading: true
|
||||
});
|
||||
|
||||
const { addedItems } = this.state;
|
||||
let filters: string[] = [];
|
||||
|
||||
// Build the request to get all new items by their ids.
|
||||
_.map(addedItems, (itemId) => {
|
||||
|
||||
filters.push("(Id eq " + itemId + ")");
|
||||
});
|
||||
|
||||
const query = _.join(filters, " or ");
|
||||
|
||||
this._getNewsItems(query).then((items) => {
|
||||
|
||||
// Add items to the state
|
||||
let updatedItems = update(this.state.items, {$unshift: items.reverse()});
|
||||
|
||||
this.setState({
|
||||
items: updatedItems,
|
||||
loading: false
|
||||
});
|
||||
|
||||
}).catch((errorMsg) => {
|
||||
|
||||
this.setState({
|
||||
error: errorMsg,
|
||||
loading: false
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _getMockedNewsItems(): Promise<INewsItem[]> {
|
||||
return MockHttpClient.get(this.props.siteUrl)
|
||||
.then((data: INewsItem[]) => {
|
||||
return data;
|
||||
}) as Promise<INewsItem[]>;
|
||||
}
|
||||
|
||||
private _getNewsItems(filterQuery: string = ""): Promise<INewsItem[]> {
|
||||
|
||||
const p = new Promise<INewsItem[]>((resolve, reject) => {
|
||||
|
||||
let web = new Web(this.props.siteUrl);
|
||||
|
||||
web.lists.getByTitle(this.props.listTitle).items.filter(filterQuery).orderBy("Created", false).get().then((items)=> {
|
||||
|
||||
resolve(items as INewsItem[]);
|
||||
|
||||
}).catch((errorMsg) => {
|
||||
|
||||
reject(errorMsg);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return p;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Web Part configuration",
|
||||
"BasicGroupName": "Miscellaneous",
|
||||
"ListTitleFieldLabel": "List Title"
|
||||
}
|
||||
});
|
10
samples/react-real-time/client/src/webparts/realTimeNewsFeed/loc/mystrings.d.ts
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
declare interface IRealTimeNewsFeedStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
ListTitleFieldLabel: string;
|
||||
}
|
||||
|
||||
declare module 'realTimeNewsFeedStrings' {
|
||||
const strings: IRealTimeNewsFeedStrings;
|
||||
export = strings;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import * as assert from 'assert';
|
||||
|
||||
describe('RealTimeNewsFeedWebPart', () => {
|
||||
it('should do something', () => {
|
||||
assert.ok(true);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"jsx": "react",
|
||||
"declaration": true,
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Type definitions for webpack in Microsoft ODSP projects
|
||||
// Project: ODSP-WEBPACK
|
||||
|
||||
/*
|
||||
* This definition of webpack require overrides all other definitions of require in our toolchain
|
||||
* Make sure all other definitions of require are commented out e.g. in node.d.ts
|
||||
*/
|
||||
declare var require: {
|
||||
(path: string): any;
|
||||
(paths: string[], callback: (...modules: any[]) => void): void;
|
||||
resolve: (id: string) => string;
|
||||
ensure: (paths: string[], callback: (require: <T>(path: string) => T) => void, path: string) => void;
|
||||
};
|
|
@ -0,0 +1,10 @@
|
|||
// Type definitions for Microsoft ODSP projects
|
||||
// Project: ODSP
|
||||
|
||||
/// <reference path="odsp-webpack.d.ts" />
|
||||
|
||||
/* Global definition for DEBUG builds */
|
||||
declare const DEBUG: boolean;
|
||||
|
||||
/* Global definition for UNIT_TEST builds */
|
||||
declare const UNIT_TEST: boolean;
|
|
@ -0,0 +1,15 @@
|
|||
// Type definitions for assertion-error 1.0.0
|
||||
// Project: https://github.com/chaijs/assertion-error
|
||||
// Definitions by: Bart van der Schoor <https://github.com/Bartvds>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
declare module 'assertion-error' {
|
||||
class AssertionError implements Error {
|
||||
constructor(message: string, props?: any, ssf?: Function);
|
||||
name: string;
|
||||
message: string;
|
||||
showDiff: boolean;
|
||||
stack: string;
|
||||
}
|
||||
export = AssertionError;
|
||||
}
|
|
@ -0,0 +1,388 @@
|
|||
// Type definitions for chai 3.2.0
|
||||
// Project: http://chaijs.com/
|
||||
// Definitions by: Jed Mao <https://github.com/jedmao/>,
|
||||
// Bart van der Schoor <https://github.com/Bartvds>,
|
||||
// Andrew Brown <https://github.com/AGBrown>,
|
||||
// Olivier Chevet <https://github.com/olivr70>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
// <reference path="../assertion-error/assertion-error.d.ts"/>
|
||||
|
||||
declare module Chai {
|
||||
|
||||
interface ChaiStatic {
|
||||
expect: ExpectStatic;
|
||||
should(): Should;
|
||||
/**
|
||||
* Provides a way to extend the internals of Chai
|
||||
*/
|
||||
use(fn: (chai: any, utils: any) => void): any;
|
||||
assert: AssertStatic;
|
||||
config: Config;
|
||||
AssertionError: AssertionError;
|
||||
}
|
||||
|
||||
export interface ExpectStatic extends AssertionStatic {
|
||||
fail(actual?: any, expected?: any, message?: string, operator?: string): void;
|
||||
}
|
||||
|
||||
export interface AssertStatic extends Assert {
|
||||
}
|
||||
|
||||
export interface AssertionStatic {
|
||||
(target: any, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface ShouldAssertion {
|
||||
equal(value1: any, value2: any, message?: string): void;
|
||||
Throw: ShouldThrow;
|
||||
throw: ShouldThrow;
|
||||
exist(value: any, message?: string): void;
|
||||
}
|
||||
|
||||
interface Should extends ShouldAssertion {
|
||||
not: ShouldAssertion;
|
||||
fail(actual: any, expected: any, message?: string, operator?: string): void;
|
||||
}
|
||||
|
||||
interface ShouldThrow {
|
||||
(actual: Function): void;
|
||||
(actual: Function, expected: string|RegExp, message?: string): void;
|
||||
(actual: Function, constructor: Error|Function, expected?: string|RegExp, message?: string): void;
|
||||
}
|
||||
|
||||
interface Assertion extends LanguageChains, NumericComparison, TypeComparison {
|
||||
not: Assertion;
|
||||
deep: Deep;
|
||||
any: KeyFilter;
|
||||
all: KeyFilter;
|
||||
a: TypeComparison;
|
||||
an: TypeComparison;
|
||||
include: Include;
|
||||
includes: Include;
|
||||
contain: Include;
|
||||
contains: Include;
|
||||
ok: Assertion;
|
||||
true: Assertion;
|
||||
false: Assertion;
|
||||
null: Assertion;
|
||||
undefined: Assertion;
|
||||
NaN: Assertion;
|
||||
exist: Assertion;
|
||||
empty: Assertion;
|
||||
arguments: Assertion;
|
||||
Arguments: Assertion;
|
||||
equal: Equal;
|
||||
equals: Equal;
|
||||
eq: Equal;
|
||||
eql: Equal;
|
||||
eqls: Equal;
|
||||
property: Property;
|
||||
ownProperty: OwnProperty;
|
||||
haveOwnProperty: OwnProperty;
|
||||
ownPropertyDescriptor: OwnPropertyDescriptor;
|
||||
haveOwnPropertyDescriptor: OwnPropertyDescriptor;
|
||||
length: Length;
|
||||
lengthOf: Length;
|
||||
match: Match;
|
||||
matches: Match;
|
||||
string(string: string, message?: string): Assertion;
|
||||
keys: Keys;
|
||||
key(string: string): Assertion;
|
||||
throw: Throw;
|
||||
throws: Throw;
|
||||
Throw: Throw;
|
||||
respondTo: RespondTo;
|
||||
respondsTo: RespondTo;
|
||||
itself: Assertion;
|
||||
satisfy: Satisfy;
|
||||
satisfies: Satisfy;
|
||||
closeTo(expected: number, delta: number, message?: string): Assertion;
|
||||
members: Members;
|
||||
increase: PropertyChange;
|
||||
increases: PropertyChange;
|
||||
decrease: PropertyChange;
|
||||
decreases: PropertyChange;
|
||||
change: PropertyChange;
|
||||
changes: PropertyChange;
|
||||
extensible: Assertion;
|
||||
sealed: Assertion;
|
||||
frozen: Assertion;
|
||||
|
||||
}
|
||||
|
||||
interface LanguageChains {
|
||||
to: Assertion;
|
||||
be: Assertion;
|
||||
been: Assertion;
|
||||
is: Assertion;
|
||||
that: Assertion;
|
||||
which: Assertion;
|
||||
and: Assertion;
|
||||
has: Assertion;
|
||||
have: Assertion;
|
||||
with: Assertion;
|
||||
at: Assertion;
|
||||
of: Assertion;
|
||||
same: Assertion;
|
||||
}
|
||||
|
||||
interface NumericComparison {
|
||||
above: NumberComparer;
|
||||
gt: NumberComparer;
|
||||
greaterThan: NumberComparer;
|
||||
least: NumberComparer;
|
||||
gte: NumberComparer;
|
||||
below: NumberComparer;
|
||||
lt: NumberComparer;
|
||||
lessThan: NumberComparer;
|
||||
most: NumberComparer;
|
||||
lte: NumberComparer;
|
||||
within(start: number, finish: number, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface NumberComparer {
|
||||
(value: number, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface TypeComparison {
|
||||
(type: string, message?: string): Assertion;
|
||||
instanceof: InstanceOf;
|
||||
instanceOf: InstanceOf;
|
||||
}
|
||||
|
||||
interface InstanceOf {
|
||||
(constructor: Object, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Deep {
|
||||
equal: Equal;
|
||||
include: Include;
|
||||
property: Property;
|
||||
members: Members;
|
||||
}
|
||||
|
||||
interface KeyFilter {
|
||||
keys: Keys;
|
||||
}
|
||||
|
||||
interface Equal {
|
||||
(value: any, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Property {
|
||||
(name: string, value?: any, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface OwnProperty {
|
||||
(name: string, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface OwnPropertyDescriptor {
|
||||
(name: string, descriptor: PropertyDescriptor, message?: string): Assertion;
|
||||
(name: string, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Length extends LanguageChains, NumericComparison {
|
||||
(length: number, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Include {
|
||||
(value: Object, message?: string): Assertion;
|
||||
(value: string, message?: string): Assertion;
|
||||
(value: number, message?: string): Assertion;
|
||||
keys: Keys;
|
||||
members: Members;
|
||||
any: KeyFilter;
|
||||
all: KeyFilter;
|
||||
}
|
||||
|
||||
interface Match {
|
||||
(regexp: RegExp|string, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Keys {
|
||||
(...keys: string[]): Assertion;
|
||||
(keys: any[]): Assertion;
|
||||
(keys: Object): Assertion;
|
||||
}
|
||||
|
||||
interface Throw {
|
||||
(): Assertion;
|
||||
(expected: string, message?: string): Assertion;
|
||||
(expected: RegExp, message?: string): Assertion;
|
||||
(constructor: Error, expected?: string, message?: string): Assertion;
|
||||
(constructor: Error, expected?: RegExp, message?: string): Assertion;
|
||||
(constructor: Function, expected?: string, message?: string): Assertion;
|
||||
(constructor: Function, expected?: RegExp, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface RespondTo {
|
||||
(method: string, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Satisfy {
|
||||
(matcher: Function, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Members {
|
||||
(set: any[], message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface PropertyChange {
|
||||
(object: Object, prop: string, msg?: string): Assertion;
|
||||
}
|
||||
|
||||
export interface Assert {
|
||||
/**
|
||||
* @param expression Expression to test for truthiness.
|
||||
* @param message Message to display on error.
|
||||
*/
|
||||
(expression: any, message?: string): void;
|
||||
|
||||
fail(actual?: any, expected?: any, msg?: string, operator?: string): void;
|
||||
|
||||
ok(val: any, msg?: string): void;
|
||||
isOk(val: any, msg?: string): void;
|
||||
notOk(val: any, msg?: string): void;
|
||||
isNotOk(val: any, msg?: string): void;
|
||||
|
||||
equal(act: any, exp: any, msg?: string): void;
|
||||
notEqual(act: any, exp: any, msg?: string): void;
|
||||
|
||||
strictEqual(act: any, exp: any, msg?: string): void;
|
||||
notStrictEqual(act: any, exp: any, msg?: string): void;
|
||||
|
||||
deepEqual(act: any, exp: any, msg?: string): void;
|
||||
notDeepEqual(act: any, exp: any, msg?: string): void;
|
||||
|
||||
isTrue(val: any, msg?: string): void;
|
||||
isFalse(val: any, msg?: string): void;
|
||||
|
||||
isNull(val: any, msg?: string): void;
|
||||
isNotNull(val: any, msg?: string): void;
|
||||
|
||||
isUndefined(val: any, msg?: string): void;
|
||||
isDefined(val: any, msg?: string): void;
|
||||
|
||||
isNaN(val: any, msg?: string): void;
|
||||
isNotNaN(val: any, msg?: string): void;
|
||||
|
||||
isAbove(val: number, abv: number, msg?: string): void;
|
||||
isBelow(val: number, blw: number, msg?: string): void;
|
||||
|
||||
isFunction(val: any, msg?: string): void;
|
||||
isNotFunction(val: any, msg?: string): void;
|
||||
|
||||
isObject(val: any, msg?: string): void;
|
||||
isNotObject(val: any, msg?: string): void;
|
||||
|
||||
isArray(val: any, msg?: string): void;
|
||||
isNotArray(val: any, msg?: string): void;
|
||||
|
||||
isString(val: any, msg?: string): void;
|
||||
isNotString(val: any, msg?: string): void;
|
||||
|
||||
isNumber(val: any, msg?: string): void;
|
||||
isNotNumber(val: any, msg?: string): void;
|
||||
|
||||
isBoolean(val: any, msg?: string): void;
|
||||
isNotBoolean(val: any, msg?: string): void;
|
||||
|
||||
typeOf(val: any, type: string, msg?: string): void;
|
||||
notTypeOf(val: any, type: string, msg?: string): void;
|
||||
|
||||
instanceOf(val: any, type: Function, msg?: string): void;
|
||||
notInstanceOf(val: any, type: Function, msg?: string): void;
|
||||
|
||||
include(exp: string, inc: any, msg?: string): void;
|
||||
include(exp: any[], inc: any, msg?: string): void;
|
||||
|
||||
notInclude(exp: string, inc: any, msg?: string): void;
|
||||
notInclude(exp: any[], inc: any, msg?: string): void;
|
||||
|
||||
match(exp: any, re: RegExp, msg?: string): void;
|
||||
notMatch(exp: any, re: RegExp, msg?: string): void;
|
||||
|
||||
property(obj: Object, prop: string, msg?: string): void;
|
||||
notProperty(obj: Object, prop: string, msg?: string): void;
|
||||
deepProperty(obj: Object, prop: string, msg?: string): void;
|
||||
notDeepProperty(obj: Object, prop: string, msg?: string): void;
|
||||
|
||||
propertyVal(obj: Object, prop: string, val: any, msg?: string): void;
|
||||
propertyNotVal(obj: Object, prop: string, val: any, msg?: string): void;
|
||||
|
||||
deepPropertyVal(obj: Object, prop: string, val: any, msg?: string): void;
|
||||
deepPropertyNotVal(obj: Object, prop: string, val: any, msg?: string): void;
|
||||
|
||||
lengthOf(exp: any, len: number, msg?: string): void;
|
||||
//alias frenzy
|
||||
throw(fn: Function, msg?: string): void;
|
||||
throw(fn: Function, regExp: RegExp): void;
|
||||
throw(fn: Function, errType: Function, msg?: string): void;
|
||||
throw(fn: Function, errType: Function, regExp: RegExp): void;
|
||||
|
||||
throws(fn: Function, msg?: string): void;
|
||||
throws(fn: Function, regExp: RegExp): void;
|
||||
throws(fn: Function, errType: Function, msg?: string): void;
|
||||
throws(fn: Function, errType: Function, regExp: RegExp): void;
|
||||
|
||||
Throw(fn: Function, msg?: string): void;
|
||||
Throw(fn: Function, regExp: RegExp): void;
|
||||
Throw(fn: Function, errType: Function, msg?: string): void;
|
||||
Throw(fn: Function, errType: Function, regExp: RegExp): void;
|
||||
|
||||
doesNotThrow(fn: Function, msg?: string): void;
|
||||
doesNotThrow(fn: Function, regExp: RegExp): void;
|
||||
doesNotThrow(fn: Function, errType: Function, msg?: string): void;
|
||||
doesNotThrow(fn: Function, errType: Function, regExp: RegExp): void;
|
||||
|
||||
operator(val: any, operator: string, val2: any, msg?: string): void;
|
||||
closeTo(act: number, exp: number, delta: number, msg?: string): void;
|
||||
|
||||
sameMembers(set1: any[], set2: any[], msg?: string): void;
|
||||
sameDeepMembers(set1: any[], set2: any[], msg?: string): void;
|
||||
includeMembers(superset: any[], subset: any[], msg?: string): void;
|
||||
|
||||
ifError(val: any, msg?: string): void;
|
||||
|
||||
isExtensible(obj: {}, msg?: string): void;
|
||||
extensible(obj: {}, msg?: string): void;
|
||||
isNotExtensible(obj: {}, msg?: string): void;
|
||||
notExtensible(obj: {}, msg?: string): void;
|
||||
|
||||
isSealed(obj: {}, msg?: string): void;
|
||||
sealed(obj: {}, msg?: string): void;
|
||||
isNotSealed(obj: {}, msg?: string): void;
|
||||
notSealed(obj: {}, msg?: string): void;
|
||||
|
||||
isFrozen(obj: Object, msg?: string): void;
|
||||
frozen(obj: Object, msg?: string): void;
|
||||
isNotFrozen(obj: Object, msg?: string): void;
|
||||
notFrozen(obj: Object, msg?: string): void;
|
||||
|
||||
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
includeStack: boolean;
|
||||
}
|
||||
|
||||
export class AssertionError {
|
||||
constructor(message: string, _props?: any, ssf?: Function);
|
||||
name: string;
|
||||
message: string;
|
||||
showDiff: boolean;
|
||||
stack: string;
|
||||
}
|
||||
}
|
||||
|
||||
declare var chai: Chai.ChaiStatic;
|
||||
|
||||
declare module "chai" {
|
||||
export = chai;
|
||||
}
|
||||
|
||||
interface Object {
|
||||
should: Chai.Assertion;
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
// Type definitions for Combokeys v2.4.6
|
||||
// Project: https://github.com/PolicyStat/combokeys
|
||||
// Definitions by: Ian Clanton-Thuon <https://github.com/iclanton>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
|
||||
declare namespace Combokeys {
|
||||
interface CombokeysStatic {
|
||||
new (element: Element): Combokeys;
|
||||
|
||||
/**
|
||||
* all instances of Combokeys
|
||||
*/
|
||||
instances: Combokeys[];
|
||||
|
||||
/**
|
||||
* reset all instances
|
||||
*/
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
interface Combokeys {
|
||||
element: Element;
|
||||
|
||||
/**
|
||||
* binds an event to Combokeys
|
||||
*
|
||||
* can be a single key, a combination of keys separated with +,
|
||||
* an array of keys, or a sequence of keys separated by spaces
|
||||
*
|
||||
* be sure to list the modifier keys first to make sure that the
|
||||
* correct key ends up getting bound (the last key in the pattern)
|
||||
*
|
||||
* @param {keys} key combination or combinations
|
||||
* @param {callback} callback function
|
||||
* @param {handler} optional - one of "keypress", "keydown", or "keyup"
|
||||
* @returns void
|
||||
*/
|
||||
bind(keys: string | string[], callback: () => void, action?: string): void;
|
||||
|
||||
|
||||
/**
|
||||
* binds multiple combinations to the same callback
|
||||
*
|
||||
* @param {keys} key combinations
|
||||
* @param {callback} callback function
|
||||
* @param {handler} optional - one of "keypress", "keydown", or "keyup"
|
||||
* @returns void
|
||||
*/
|
||||
bindMultiple(keys: string[], callback: () => void, action?: string): void;
|
||||
|
||||
/**
|
||||
* unbinds an event to Combokeys
|
||||
*
|
||||
* the unbinding sets the callback function of the specified key combo
|
||||
* to an empty function and deletes the corresponding key in the
|
||||
* directMap dict.
|
||||
*
|
||||
* the keycombo+action has to be exactly the same as
|
||||
* it was defined in the bind method
|
||||
*
|
||||
* @param {keys} key combination or combinations
|
||||
* @param {action} optional - one of "keypress", "keydown", or "keyup"
|
||||
* @returns void
|
||||
*/
|
||||
unbind(keys: string | string[], action?: string): void;
|
||||
|
||||
/**
|
||||
* triggers an event that has already been bound
|
||||
*
|
||||
* @param {keys} key combination
|
||||
* @param {action} optional - one of "keypress", "keydown", or "keyup"
|
||||
* @returns void
|
||||
*/
|
||||
trigger(keys: string, action?: string): void;
|
||||
|
||||
/**
|
||||
* resets the library back to its initial state. This is useful
|
||||
* if you want to clear out the current keyboard shortcuts and bind
|
||||
* new ones - for example if you switch to another page
|
||||
*
|
||||
* @returns void
|
||||
*/
|
||||
reset(): void;
|
||||
|
||||
/**
|
||||
* should we stop this event before firing off callbacks
|
||||
*
|
||||
* @param {e} event
|
||||
* @param {element} bound element
|
||||
* @return {boolean}
|
||||
*/
|
||||
stopCallback(e: Event, element: Element): boolean;
|
||||
|
||||
/**
|
||||
* detach all listners from the bound element
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
detach(): void;
|
||||
}
|
||||
}
|
||||
|
||||
declare var combokeys: Combokeys.CombokeysStatic;
|
||||
|
||||
declare module "combokeys" {
|
||||
export = combokeys;
|
||||
}
|
113
samples/react-real-time/client/typings/es6-collections/es6-collections.d.ts
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
// Type definitions for es6-collections v0.5.1
|
||||
// Project: https://github.com/WebReflection/es6-collections/
|
||||
// Definitions by: Ron Buckton <http://github.com/rbuckton>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
/* *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
interface IteratorResult<T> {
|
||||
done: boolean;
|
||||
value?: T;
|
||||
}
|
||||
|
||||
interface Iterator<T> {
|
||||
next(value?: any): IteratorResult<T>;
|
||||
return?(value?: any): IteratorResult<T>;
|
||||
throw?(e?: any): IteratorResult<T>;
|
||||
}
|
||||
|
||||
interface ForEachable<T> {
|
||||
forEach(callbackfn: (value: T) => void): void;
|
||||
}
|
||||
|
||||
interface Map<K, V> {
|
||||
clear(): void;
|
||||
delete(key: K): boolean;
|
||||
forEach(callbackfn: (value: V, index: K, map: Map<K, V>) => void, thisArg?: any): void;
|
||||
get(key: K): V;
|
||||
has(key: K): boolean;
|
||||
set(key: K, value?: V): Map<K, V>;
|
||||
entries(): Iterator<[K, V]>;
|
||||
keys(): Iterator<K>;
|
||||
values(): Iterator<V>;
|
||||
size: number;
|
||||
}
|
||||
|
||||
interface MapConstructor {
|
||||
new <K, V>(): Map<K, V>;
|
||||
new <K, V>(iterable: ForEachable<[K, V]>): Map<K, V>;
|
||||
prototype: Map<any, any>;
|
||||
}
|
||||
|
||||
declare var Map: MapConstructor;
|
||||
|
||||
interface Set<T> {
|
||||
add(value: T): Set<T>;
|
||||
clear(): void;
|
||||
delete(value: T): boolean;
|
||||
forEach(callbackfn: (value: T, index: T, set: Set<T>) => void, thisArg?: any): void;
|
||||
has(value: T): boolean;
|
||||
entries(): Iterator<[T, T]>;
|
||||
keys(): Iterator<T>;
|
||||
values(): Iterator<T>;
|
||||
size: number;
|
||||
}
|
||||
|
||||
interface SetConstructor {
|
||||
new <T>(): Set<T>;
|
||||
new <T>(iterable: ForEachable<T>): Set<T>;
|
||||
prototype: Set<any>;
|
||||
}
|
||||
|
||||
declare var Set: SetConstructor;
|
||||
|
||||
interface WeakMap<K, V> {
|
||||
delete(key: K): boolean;
|
||||
clear(): void;
|
||||
get(key: K): V;
|
||||
has(key: K): boolean;
|
||||
set(key: K, value?: V): WeakMap<K, V>;
|
||||
}
|
||||
|
||||
interface WeakMapConstructor {
|
||||
new <K, V>(): WeakMap<K, V>;
|
||||
new <K, V>(iterable: ForEachable<[K, V]>): WeakMap<K, V>;
|
||||
prototype: WeakMap<any, any>;
|
||||
}
|
||||
|
||||
declare var WeakMap: WeakMapConstructor;
|
||||
|
||||
interface WeakSet<T> {
|
||||
delete(value: T): boolean;
|
||||
clear(): void;
|
||||
add(value: T): WeakSet<T>;
|
||||
has(value: T): boolean;
|
||||
}
|
||||
|
||||
interface WeakSetConstructor {
|
||||
new <T>(): WeakSet<T>;
|
||||
new <T>(iterable: ForEachable<T>): WeakSet<T>;
|
||||
prototype: WeakSet<any>;
|
||||
}
|
||||
|
||||
declare var WeakSet: WeakSetConstructor;
|
||||
|
||||
declare module "es6-collections" {
|
||||
var Map: MapConstructor;
|
||||
var Set: SetConstructor;
|
||||
var WeakMap: WeakMapConstructor;
|
||||
var WeakSet: WeakSetConstructor;
|
||||
}
|
|
@ -0,0 +1,631 @@
|
|||
// Type definitions for Knockout v3.2.0
|
||||
// Project: http://knockoutjs.com
|
||||
// Definitions by: Boris Yankov <https://github.com/borisyankov/>, Igor Oleinikov <https://github.com/Igorbek/>, Clément Bourgeois <https://github.com/moonpyk/>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
|
||||
interface KnockoutSubscribableFunctions<T> {
|
||||
[key: string]: KnockoutBindingHandler;
|
||||
|
||||
notifySubscribers(valueToWrite?: T, event?: string): void;
|
||||
}
|
||||
|
||||
interface KnockoutComputedFunctions<T> {
|
||||
[key: string]: KnockoutBindingHandler;
|
||||
}
|
||||
|
||||
interface KnockoutObservableFunctions<T> {
|
||||
[key: string]: KnockoutBindingHandler;
|
||||
|
||||
equalityComparer(a: any, b: any): boolean;
|
||||
}
|
||||
|
||||
interface KnockoutObservableArrayFunctions<T> {
|
||||
// General Array functions
|
||||
indexOf(searchElement: T, fromIndex?: number): number;
|
||||
slice(start: number, end?: number): T[];
|
||||
splice(start: number): T[];
|
||||
splice(start: number, deleteCount: number, ...items: T[]): T[];
|
||||
pop(): T;
|
||||
push(...items: T[]): void;
|
||||
shift(): T;
|
||||
unshift(...items: T[]): number;
|
||||
reverse(): KnockoutObservableArray<T>;
|
||||
sort(): KnockoutObservableArray<T>;
|
||||
sort(compareFunction: (left: T, right: T) => number): KnockoutObservableArray<T>;
|
||||
|
||||
// Ko specific
|
||||
[key: string]: KnockoutBindingHandler;
|
||||
|
||||
replace(oldItem: T, newItem: T): void;
|
||||
|
||||
remove(item: T): T[];
|
||||
remove(removeFunction: (item: T) => boolean): T[];
|
||||
removeAll(items: T[]): T[];
|
||||
removeAll(): T[];
|
||||
|
||||
destroy(item: T): void;
|
||||
destroy(destroyFunction: (item: T) => boolean): void;
|
||||
destroyAll(items: T[]): void;
|
||||
destroyAll(): void;
|
||||
}
|
||||
|
||||
interface KnockoutSubscribableStatic {
|
||||
fn: KnockoutSubscribableFunctions<any>;
|
||||
|
||||
new <T>(): KnockoutSubscribable<T>;
|
||||
}
|
||||
|
||||
interface KnockoutSubscription {
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
interface KnockoutSubscribable<T> extends KnockoutSubscribableFunctions<T> {
|
||||
subscribe(callback: (newValue: T) => void, target?: any, event?: string): KnockoutSubscription;
|
||||
subscribe<TEvent>(callback: (newValue: TEvent) => void, target: any, event: string): KnockoutSubscription;
|
||||
extend(requestedExtenders: { [key: string]: any; }): KnockoutSubscribable<T>;
|
||||
getSubscriptionsCount(): number;
|
||||
}
|
||||
|
||||
interface KnockoutComputedStatic {
|
||||
fn: KnockoutComputedFunctions<any>;
|
||||
|
||||
<T>(): KnockoutComputed<T>;
|
||||
<T>(func: () => T, context?: any, options?: any): KnockoutComputed<T>;
|
||||
<T>(def: KnockoutComputedDefine<T>, context?: any): KnockoutComputed<T>;
|
||||
}
|
||||
|
||||
interface KnockoutComputed<T> extends KnockoutObservable<T>, KnockoutComputedFunctions<T> {
|
||||
fn: KnockoutComputedFunctions<any>;
|
||||
|
||||
dispose(): void;
|
||||
isActive(): boolean;
|
||||
getDependenciesCount(): number;
|
||||
extend(requestedExtenders: { [key: string]: any; }): KnockoutComputed<T>;
|
||||
}
|
||||
|
||||
interface KnockoutObservableArrayStatic {
|
||||
fn: KnockoutObservableArrayFunctions<any>;
|
||||
|
||||
<T>(value?: T[]): KnockoutObservableArray<T>;
|
||||
}
|
||||
|
||||
interface KnockoutObservableArray<T> extends KnockoutObservable<T[]>, KnockoutObservableArrayFunctions<T> {
|
||||
extend(requestedExtenders: { [key: string]: any; }): KnockoutObservableArray<T>;
|
||||
}
|
||||
|
||||
interface KnockoutObservableStatic {
|
||||
fn: KnockoutObservableFunctions<any>;
|
||||
|
||||
<T>(value?: T): KnockoutObservable<T>;
|
||||
}
|
||||
|
||||
interface KnockoutObservable<T> extends KnockoutSubscribable<T>, KnockoutObservableFunctions<T> {
|
||||
(): T;
|
||||
(value: T): void;
|
||||
|
||||
peek(): T;
|
||||
valueHasMutated?:{(): void;};
|
||||
valueWillMutate?:{(): void;};
|
||||
extend(requestedExtenders: { [key: string]: any; }): KnockoutObservable<T>;
|
||||
}
|
||||
|
||||
interface KnockoutComputedDefine<T> {
|
||||
read(): T;
|
||||
write? (value: T): void;
|
||||
disposeWhenNodeIsRemoved?: Node;
|
||||
disposeWhen? (): boolean;
|
||||
owner?: any;
|
||||
deferEvaluation?: boolean;
|
||||
pure?: boolean;
|
||||
}
|
||||
|
||||
interface KnockoutBindingContext {
|
||||
$parent: any;
|
||||
$parents: any[];
|
||||
$root: any;
|
||||
$data: any;
|
||||
$rawData: any | KnockoutObservable<any>;
|
||||
$index?: KnockoutObservable<number>;
|
||||
$parentContext?: KnockoutBindingContext;
|
||||
$component: any;
|
||||
$componentTemplateNodes: Node[];
|
||||
|
||||
extend(properties: any): any;
|
||||
createChildContext(dataItemOrAccessor: any, dataItemAlias?: any, extendCallback?: Function): any;
|
||||
}
|
||||
|
||||
interface KnockoutAllBindingsAccessor {
|
||||
(): any;
|
||||
get(name: string): any;
|
||||
has(name: string): boolean;
|
||||
}
|
||||
|
||||
interface KnockoutBindingHandler {
|
||||
after?: Array<string>;
|
||||
init?: (element: any, valueAccessor: () => any, allBindingsAccessor?: KnockoutAllBindingsAccessor, viewModel?: any, bindingContext?: KnockoutBindingContext) => void | { controlsDescendantBindings: boolean; };
|
||||
update?: (element: any, valueAccessor: () => any, allBindingsAccessor?: KnockoutAllBindingsAccessor, viewModel?: any, bindingContext?: KnockoutBindingContext) => void;
|
||||
options?: any;
|
||||
preprocess?: (value: string, name: string, addBindingCallback?: (name: string, value: string) => void) => string;
|
||||
}
|
||||
|
||||
interface KnockoutBindingHandlers {
|
||||
[bindingHandler: string]: KnockoutBindingHandler;
|
||||
|
||||
// Controlling text and appearance
|
||||
visible: KnockoutBindingHandler;
|
||||
text: KnockoutBindingHandler;
|
||||
html: KnockoutBindingHandler;
|
||||
css: KnockoutBindingHandler;
|
||||
style: KnockoutBindingHandler;
|
||||
attr: KnockoutBindingHandler;
|
||||
|
||||
// Control Flow
|
||||
foreach: KnockoutBindingHandler;
|
||||
if: KnockoutBindingHandler;
|
||||
ifnot: KnockoutBindingHandler;
|
||||
with: KnockoutBindingHandler;
|
||||
|
||||
// Working with form fields
|
||||
click: KnockoutBindingHandler;
|
||||
event: KnockoutBindingHandler;
|
||||
submit: KnockoutBindingHandler;
|
||||
enable: KnockoutBindingHandler;
|
||||
disable: KnockoutBindingHandler;
|
||||
value: KnockoutBindingHandler;
|
||||
textInput: KnockoutBindingHandler;
|
||||
hasfocus: KnockoutBindingHandler;
|
||||
checked: KnockoutBindingHandler;
|
||||
options: KnockoutBindingHandler;
|
||||
selectedOptions: KnockoutBindingHandler;
|
||||
uniqueName: KnockoutBindingHandler;
|
||||
|
||||
// Rendering templates
|
||||
template: KnockoutBindingHandler;
|
||||
|
||||
// Components (new for v3.2)
|
||||
component: KnockoutBindingHandler;
|
||||
}
|
||||
|
||||
interface KnockoutMemoization {
|
||||
memoize(callback: () => string): string;
|
||||
unmemoize(memoId: string, callbackParams: any[]): boolean;
|
||||
unmemoizeDomNodeAndDescendants(domNode: any, extraCallbackParamsArray: any[]): boolean;
|
||||
parseMemoText(memoText: string): string;
|
||||
}
|
||||
|
||||
interface KnockoutVirtualElement {}
|
||||
|
||||
interface KnockoutVirtualElements {
|
||||
allowedBindings: { [bindingName: string]: boolean; };
|
||||
emptyNode(node: KnockoutVirtualElement ): void;
|
||||
firstChild(node: KnockoutVirtualElement ): KnockoutVirtualElement;
|
||||
insertAfter( container: KnockoutVirtualElement, nodeToInsert: Node, insertAfter: Node ): void;
|
||||
nextSibling(node: KnockoutVirtualElement): Node;
|
||||
prepend(node: KnockoutVirtualElement, toInsert: Node ): void;
|
||||
setDomNodeChildren(node: KnockoutVirtualElement, newChildren: { length: number;[index: number]: Node; } ): void;
|
||||
childNodes(node: KnockoutVirtualElement ): Node[];
|
||||
}
|
||||
|
||||
interface KnockoutExtenders {
|
||||
throttle(target: any, timeout: number): KnockoutComputed<any>;
|
||||
notify(target: any, notifyWhen: string): any;
|
||||
|
||||
rateLimit(target: any, timeout: number): any;
|
||||
rateLimit(target: any, options: { timeout: number; method?: string; }): any;
|
||||
|
||||
trackArrayChanges(target: any): any;
|
||||
}
|
||||
|
||||
//
|
||||
// NOTE TO MAINTAINERS AND CONTRIBUTORS : pay attention to only include symbols that are
|
||||
// publicly exported in the minified version of ko, without that you can give the false
|
||||
// impression that some functions will be available in production builds.
|
||||
//
|
||||
interface KnockoutUtils {
|
||||
//////////////////////////////////
|
||||
// utils.domData.js
|
||||
//////////////////////////////////
|
||||
|
||||
domData: {
|
||||
get (node: Element, key: string): any;
|
||||
|
||||
set (node: Element, key: string, value: any): void;
|
||||
|
||||
getAll(node: Element, createIfNotFound: boolean): any;
|
||||
|
||||
clear(node: Element): boolean;
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
// utils.domNodeDisposal.js
|
||||
//////////////////////////////////
|
||||
|
||||
domNodeDisposal: {
|
||||
addDisposeCallback(node: Element, callback: Function): void;
|
||||
|
||||
removeDisposeCallback(node: Element, callback: Function): void;
|
||||
|
||||
cleanNode(node: Node): Element;
|
||||
|
||||
removeNode(node: Node): void;
|
||||
};
|
||||
|
||||
addOrRemoveItem<T>(array: T[] | KnockoutObservable<T>, value: T, included: T): void;
|
||||
|
||||
arrayFilter<T>(array: T[], predicate: (item: T) => boolean): T[];
|
||||
|
||||
arrayFirst<T>(array: T[], predicate: (item: T) => boolean, predicateOwner?: any): T;
|
||||
|
||||
arrayForEach<T>(array: T[], action: (item: T, index: number) => void): void;
|
||||
|
||||
arrayGetDistinctValues<T>(array: T[]): T[];
|
||||
|
||||
arrayIndexOf<T>(array: T[], item: T): number;
|
||||
|
||||
arrayMap<T, U>(array: T[], mapping: (item: T) => U): U[];
|
||||
|
||||
arrayPushAll<T>(array: T[] | KnockoutObservableArray<T>, valuesToPush: T[]): T[];
|
||||
|
||||
arrayRemoveItem(array: any[], itemToRemove: any): void;
|
||||
|
||||
compareArrays<T>(a: T[], b: T[]): Array<KnockoutArrayChange<T>>;
|
||||
|
||||
extend(target: Object, source: Object): Object;
|
||||
|
||||
fieldsIncludedWithJsonPost: any[];
|
||||
|
||||
getFormFields(form: any, fieldName: string): any[];
|
||||
|
||||
objectForEach(obj: any, action: (key: any, value: any) => void): void;
|
||||
|
||||
parseHtmlFragment(html: string): any[];
|
||||
|
||||
parseJson(jsonString: string): any;
|
||||
|
||||
postJson(urlOrForm: any, data: any, options: any): void;
|
||||
|
||||
peekObservable<T>(value: KnockoutObservable<T>): T;
|
||||
|
||||
range(min: any, max: any): any;
|
||||
|
||||
registerEventHandler(element: any, eventType: any, handler: Function): void;
|
||||
|
||||
setHtml(node: Element, html: () => string): void;
|
||||
|
||||
setHtml(node: Element, html: string): void;
|
||||
|
||||
setTextContent(element: any, textContent: string | KnockoutObservable<string>): void;
|
||||
|
||||
stringifyJson(data: any, replacer?: Function, space?: string): string;
|
||||
|
||||
toggleDomNodeCssClass(node: any, className: string, shouldHaveClass: boolean): void;
|
||||
|
||||
triggerEvent(element: any, eventType: any): void;
|
||||
|
||||
unwrapObservable<T>(value: KnockoutObservable<T> | T): T;
|
||||
|
||||
// NOT PART OF THE MINIFIED API SURFACE (ONLY IN knockout-{version}.debug.js) https://github.com/SteveSanderson/knockout/issues/670
|
||||
// forceRefresh(node: any): void;
|
||||
// ieVersion: number;
|
||||
// isIe6: boolean;
|
||||
// isIe7: boolean;
|
||||
// jQueryHtmlParse(html: string): any[];
|
||||
// makeArray(arrayLikeObject: any): any[];
|
||||
// moveCleanedNodesToContainerElement(nodes: any[]): HTMLElement;
|
||||
// replaceDomNodes(nodeToReplaceOrNodeArray: any, newNodesArray: any[]): void;
|
||||
// setDomNodeChildren(domNode: any, childNodes: any[]): void;
|
||||
// setElementName(element: any, name: string): void;
|
||||
// setOptionNodeSelectionState(optionNode: any, isSelected: boolean): void;
|
||||
// simpleHtmlParse(html: string): any[];
|
||||
// stringStartsWith(str: string, startsWith: string): boolean;
|
||||
// stringTokenize(str: string, delimiter: string): string[];
|
||||
// stringTrim(str: string): string;
|
||||
// tagNameLower(element: any): string;
|
||||
}
|
||||
|
||||
interface KnockoutArrayChange<T> {
|
||||
status: string;
|
||||
value: T;
|
||||
index: number;
|
||||
moved?: number;
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// templateSources.js
|
||||
//////////////////////////////////
|
||||
|
||||
interface KnockoutTemplateSourcesDomElement {
|
||||
text(): any;
|
||||
text(value: any): void;
|
||||
|
||||
data(key: string): any;
|
||||
data(key: string, value: any): any;
|
||||
}
|
||||
|
||||
interface KnockoutTemplateAnonymous extends KnockoutTemplateSourcesDomElement {
|
||||
nodes(): any;
|
||||
nodes(value: any): void;
|
||||
}
|
||||
|
||||
interface KnockoutTemplateSources {
|
||||
|
||||
domElement: {
|
||||
prototype: KnockoutTemplateSourcesDomElement
|
||||
new (element: Element): KnockoutTemplateSourcesDomElement
|
||||
};
|
||||
|
||||
anonymousTemplate: {
|
||||
prototype: KnockoutTemplateAnonymous;
|
||||
new (element: Element): KnockoutTemplateAnonymous;
|
||||
};
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// nativeTemplateEngine.js
|
||||
//////////////////////////////////
|
||||
|
||||
interface KnockoutNativeTemplateEngine {
|
||||
|
||||
renderTemplateSource(templateSource: Object, bindingContext?: KnockoutBindingContext, options?: Object): any[];
|
||||
}
|
||||
|
||||
//////////////////////////////////
|
||||
// templateEngine.js
|
||||
//////////////////////////////////
|
||||
|
||||
interface KnockoutTemplateEngine extends KnockoutNativeTemplateEngine {
|
||||
|
||||
createJavaScriptEvaluatorBlock(script: string): string;
|
||||
|
||||
makeTemplateSource(template: any, templateDocument?: Document): any;
|
||||
|
||||
renderTemplate(template: any, bindingContext: KnockoutBindingContext, options: Object, templateDocument: Document): any;
|
||||
|
||||
isTemplateRewritten(template: any, templateDocument: Document): boolean;
|
||||
|
||||
rewriteTemplate(template: any, rewriterCallback: Function, templateDocument: Document): void;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
|
||||
interface KnockoutStatic {
|
||||
utils: KnockoutUtils;
|
||||
memoization: KnockoutMemoization;
|
||||
|
||||
bindingHandlers: KnockoutBindingHandlers;
|
||||
getBindingHandler(handler: string): KnockoutBindingHandler;
|
||||
|
||||
virtualElements: KnockoutVirtualElements;
|
||||
extenders: KnockoutExtenders;
|
||||
|
||||
applyBindings(viewModelOrBindingContext?: any, rootNode?: any): void;
|
||||
applyBindingsToDescendants(viewModelOrBindingContext: any, rootNode: any): void;
|
||||
applyBindingAccessorsToNode(node: Node, bindings: (bindingContext: KnockoutBindingContext, node: Node) => {}, bindingContext: KnockoutBindingContext): void;
|
||||
applyBindingAccessorsToNode(node: Node, bindings: {}, bindingContext: KnockoutBindingContext): void;
|
||||
applyBindingAccessorsToNode(node: Node, bindings: (bindingContext: KnockoutBindingContext, node: Node) => {}, viewModel: any): void;
|
||||
applyBindingAccessorsToNode(node: Node, bindings: {}, viewModel: any): void;
|
||||
applyBindingsToNode(node: Node, bindings: any, viewModelOrBindingContext?: any): any;
|
||||
|
||||
subscribable: KnockoutSubscribableStatic;
|
||||
observable: KnockoutObservableStatic;
|
||||
|
||||
computed: KnockoutComputedStatic;
|
||||
pureComputed<T>(evaluatorFunction: () => T, context?: any): KnockoutComputed<T>;
|
||||
pureComputed<T>(options: KnockoutComputedDefine<T>, context?: any): KnockoutComputed<T>;
|
||||
|
||||
observableArray: KnockoutObservableArrayStatic;
|
||||
|
||||
contextFor(node: any): any;
|
||||
isSubscribable(instance: any): boolean;
|
||||
toJSON(viewModel: any, replacer?: Function, space?: any): string;
|
||||
toJS(viewModel: any): any;
|
||||
isObservable(instance: any): boolean;
|
||||
isWriteableObservable(instance: any): boolean;
|
||||
isComputed(instance: any): boolean;
|
||||
dataFor(node: any): any;
|
||||
removeNode(node: Element): void;
|
||||
cleanNode(node: Element): Element;
|
||||
renderTemplate(template: Function, viewModel: any, options?: any, target?: any, renderMode?: any): any;
|
||||
renderTemplate(template: string, viewModel: any, options?: any, target?: any, renderMode?: any): any;
|
||||
unwrap<T>(value: KnockoutObservable<T> | T): T;
|
||||
|
||||
computedContext: KnockoutComputedContext;
|
||||
|
||||
//////////////////////////////////
|
||||
// templateSources.js
|
||||
//////////////////////////////////
|
||||
|
||||
templateSources: KnockoutTemplateSources;
|
||||
|
||||
//////////////////////////////////
|
||||
// templateEngine.js
|
||||
//////////////////////////////////
|
||||
|
||||
templateEngine: {
|
||||
|
||||
prototype: KnockoutTemplateEngine;
|
||||
|
||||
new (): KnockoutTemplateEngine;
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
// templateRewriting.js
|
||||
//////////////////////////////////
|
||||
|
||||
templateRewriting: {
|
||||
|
||||
ensureTemplateIsRewritten(template: Node, templateEngine: KnockoutTemplateEngine, templateDocument: Document): any;
|
||||
ensureTemplateIsRewritten(template: string, templateEngine: KnockoutTemplateEngine, templateDocument: Document): any;
|
||||
|
||||
memoizeBindingAttributeSyntax(htmlString: string, templateEngine: KnockoutTemplateEngine): any;
|
||||
|
||||
applyMemoizedBindingsToNextSibling(bindings: any, nodeName: string): string;
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
// nativeTemplateEngine.js
|
||||
//////////////////////////////////
|
||||
|
||||
nativeTemplateEngine: {
|
||||
|
||||
prototype: KnockoutNativeTemplateEngine;
|
||||
|
||||
new (): KnockoutNativeTemplateEngine;
|
||||
|
||||
instance: KnockoutNativeTemplateEngine;
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
// jqueryTmplTemplateEngine.js
|
||||
//////////////////////////////////
|
||||
|
||||
jqueryTmplTemplateEngine: {
|
||||
|
||||
prototype: KnockoutTemplateEngine;
|
||||
|
||||
renderTemplateSource(templateSource: Object, bindingContext: KnockoutBindingContext, options: Object): Node[];
|
||||
|
||||
createJavaScriptEvaluatorBlock(script: string): string;
|
||||
|
||||
addTemplate(templateName: string, templateMarkup: string): void;
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
// templating.js
|
||||
//////////////////////////////////
|
||||
|
||||
setTemplateEngine(templateEngine: KnockoutNativeTemplateEngine): void;
|
||||
|
||||
renderTemplate(template: Function, dataOrBindingContext: KnockoutBindingContext, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
|
||||
renderTemplate(template: any, dataOrBindingContext: KnockoutBindingContext, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
|
||||
renderTemplate(template: Function, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
|
||||
renderTemplate(template: any, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node, renderMode: string): any;
|
||||
renderTemplate(template: Function, dataOrBindingContext: KnockoutBindingContext, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
|
||||
renderTemplate(template: any, dataOrBindingContext: KnockoutBindingContext, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
|
||||
renderTemplate(template: Function, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
|
||||
renderTemplate(template: any, dataOrBindingContext: any, options: Object, targetNodeOrNodeArray: Node[], renderMode: string): any;
|
||||
|
||||
renderTemplateForEach(template: Function, arrayOrObservableArray: any[], options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any;
|
||||
renderTemplateForEach(template: any, arrayOrObservableArray: any[], options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any;
|
||||
renderTemplateForEach(template: Function, arrayOrObservableArray: KnockoutObservable<any>, options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any;
|
||||
renderTemplateForEach(template: any, arrayOrObservableArray: KnockoutObservable<any>, options: Object, targetNode: Node, parentBindingContext: KnockoutBindingContext): any;
|
||||
|
||||
expressionRewriting: {
|
||||
bindingRewriteValidators: any;
|
||||
parseObjectLiteral: { (objectLiteralString: string): any[] }
|
||||
};
|
||||
|
||||
/////////////////////////////////
|
||||
|
||||
bindingProvider: {
|
||||
instance: KnockoutBindingProvider;
|
||||
new (): KnockoutBindingProvider;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// selectExtensions.js
|
||||
/////////////////////////////////
|
||||
|
||||
selectExtensions: {
|
||||
|
||||
readValue(element: HTMLElement): any;
|
||||
|
||||
writeValue(element: HTMLElement, value: any): void;
|
||||
};
|
||||
|
||||
components: KnockoutComponents;
|
||||
}
|
||||
|
||||
interface KnockoutBindingProvider {
|
||||
nodeHasBindings(node: Node): boolean;
|
||||
getBindings(node: Node, bindingContext: KnockoutBindingContext): {};
|
||||
getBindingAccessors?(node: Node, bindingContext: KnockoutBindingContext): { [key: string]: string; };
|
||||
}
|
||||
|
||||
interface KnockoutComputedContext {
|
||||
getDependenciesCount(): number;
|
||||
isInitial: () => boolean;
|
||||
isSleeping: boolean;
|
||||
}
|
||||
|
||||
//
|
||||
// refactored types into a namespace to reduce global pollution
|
||||
// and used Union Types to simplify overloads (requires TypeScript 1.4)
|
||||
//
|
||||
declare module KnockoutComponentTypes {
|
||||
|
||||
interface Config {
|
||||
viewModel?: ViewModelFunction | ViewModelSharedInstance | ViewModelFactoryFunction | AMDModule;
|
||||
template: string | Node[]| DocumentFragment | TemplateElement | AMDModule;
|
||||
synchronous?: boolean;
|
||||
}
|
||||
|
||||
interface ComponentConfig {
|
||||
viewModel?: ViewModelFunction | ViewModelSharedInstance | ViewModelFactoryFunction | AMDModule;
|
||||
template: any;
|
||||
createViewModel?: any;
|
||||
}
|
||||
|
||||
interface EmptyConfig {
|
||||
}
|
||||
|
||||
// common AMD type
|
||||
interface AMDModule {
|
||||
require: string;
|
||||
}
|
||||
|
||||
// viewmodel types
|
||||
interface ViewModelFunction {
|
||||
(params?: any): any;
|
||||
}
|
||||
|
||||
interface ViewModelSharedInstance {
|
||||
instance: any;
|
||||
}
|
||||
|
||||
interface ViewModelFactoryFunction {
|
||||
createViewModel: (params?: any, componentInfo?: ComponentInfo) => any;
|
||||
}
|
||||
|
||||
interface ComponentInfo {
|
||||
element: Node;
|
||||
templateNodes: Node[];
|
||||
}
|
||||
|
||||
interface TemplateElement {
|
||||
element: string | Node;
|
||||
}
|
||||
|
||||
interface Loader {
|
||||
getConfig? (componentName: string, callback: (result: ComponentConfig) => void): void;
|
||||
loadComponent? (componentName: string, config: ComponentConfig, callback: (result: Definition) => void): void;
|
||||
loadTemplate? (componentName: string, templateConfig: any, callback: (result: Node[]) => void): void;
|
||||
loadViewModel? (componentName: string, viewModelConfig: any, callback: (result: any) => void): void;
|
||||
suppressLoaderExceptions?: boolean;
|
||||
}
|
||||
|
||||
interface Definition {
|
||||
template: Node[];
|
||||
createViewModel? (params: any, options: { element: Node; }): any;
|
||||
}
|
||||
}
|
||||
|
||||
interface KnockoutComponents {
|
||||
// overloads for register method:
|
||||
register(componentName: string, config: KnockoutComponentTypes.Config | KnockoutComponentTypes.EmptyConfig): void;
|
||||
|
||||
isRegistered(componentName: string): boolean;
|
||||
unregister(componentName: string): void;
|
||||
get(componentName: string, callback: (definition: KnockoutComponentTypes.Definition) => void): void;
|
||||
clearCachedDefinition(componentName: string): void
|
||||
defaultLoader: KnockoutComponentTypes.Loader;
|
||||
loaders: KnockoutComponentTypes.Loader[];
|
||||
getComponentNameForNode(node: Node): string;
|
||||
}
|
||||
|
||||
declare var ko: KnockoutStatic;
|
||||
|
||||
declare module "knockout" {
|
||||
export = ko;
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
// Type definitions for mocha 2.2.5
|
||||
// Project: http://mochajs.org/
|
||||
// Definitions by: Kazi Manzur Rashid <https://github.com/kazimanzurrashid/>, otiai10 <https://github.com/otiai10>, jt000 <https://github.com/jt000>, Vadim Macagon <https://github.com/enlight>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
interface MochaSetupOptions {
|
||||
//milliseconds to wait before considering a test slow
|
||||
slow?: number;
|
||||
|
||||
// timeout in milliseconds
|
||||
timeout?: number;
|
||||
|
||||
// ui name "bdd", "tdd", "exports" etc
|
||||
ui?: string;
|
||||
|
||||
//array of accepted globals
|
||||
globals?: any[];
|
||||
|
||||
// reporter instance (function or string), defaults to `mocha.reporters.Spec`
|
||||
reporter?: any;
|
||||
|
||||
// bail on the first test failure
|
||||
bail?: boolean;
|
||||
|
||||
// ignore global leaks
|
||||
ignoreLeaks?: boolean;
|
||||
|
||||
// grep string or regexp to filter tests with
|
||||
grep?: any;
|
||||
}
|
||||
|
||||
interface MochaDone {
|
||||
(error?: Error): void;
|
||||
}
|
||||
|
||||
declare var mocha: Mocha;
|
||||
declare var describe: Mocha.IContextDefinition;
|
||||
declare var xdescribe: Mocha.IContextDefinition;
|
||||
// alias for `describe`
|
||||
declare var context: Mocha.IContextDefinition;
|
||||
// alias for `describe`
|
||||
declare var suite: Mocha.IContextDefinition;
|
||||
declare var it: Mocha.ITestDefinition;
|
||||
declare var xit: Mocha.ITestDefinition;
|
||||
// alias for `it`
|
||||
declare var test: Mocha.ITestDefinition;
|
||||
|
||||
declare function before(action: () => void): void;
|
||||
|
||||
declare function before(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function setup(action: () => void): void;
|
||||
|
||||
declare function setup(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function after(action: () => void): void;
|
||||
|
||||
declare function after(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function teardown(action: () => void): void;
|
||||
|
||||
declare function teardown(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function beforeEach(action: () => void): void;
|
||||
|
||||
declare function beforeEach(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function suiteSetup(action: () => void): void;
|
||||
|
||||
declare function suiteSetup(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function afterEach(action: () => void): void;
|
||||
|
||||
declare function afterEach(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function suiteTeardown(action: () => void): void;
|
||||
|
||||
declare function suiteTeardown(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare class Mocha {
|
||||
constructor(options?: {
|
||||
grep?: RegExp;
|
||||
ui?: string;
|
||||
reporter?: string;
|
||||
timeout?: number;
|
||||
bail?: boolean;
|
||||
});
|
||||
|
||||
/** Setup mocha with the given options. */
|
||||
setup(options: MochaSetupOptions): Mocha;
|
||||
bail(value?: boolean): Mocha;
|
||||
addFile(file: string): Mocha;
|
||||
/** Sets reporter by name, defaults to "spec". */
|
||||
reporter(name: string): Mocha;
|
||||
/** Sets reporter constructor, defaults to mocha.reporters.Spec. */
|
||||
reporter(reporter: (runner: Mocha.IRunner, options: any) => any): Mocha;
|
||||
ui(value: string): Mocha;
|
||||
grep(value: string): Mocha;
|
||||
grep(value: RegExp): Mocha;
|
||||
invert(): Mocha;
|
||||
ignoreLeaks(value: boolean): Mocha;
|
||||
checkLeaks(): Mocha;
|
||||
/** Enables growl support. */
|
||||
growl(): Mocha;
|
||||
globals(value: string): Mocha;
|
||||
globals(values: string[]): Mocha;
|
||||
useColors(value: boolean): Mocha;
|
||||
useInlineDiffs(value: boolean): Mocha;
|
||||
timeout(value: number): Mocha;
|
||||
slow(value: number): Mocha;
|
||||
enableTimeouts(value: boolean): Mocha;
|
||||
asyncOnly(value: boolean): Mocha;
|
||||
noHighlighting(value: boolean): Mocha;
|
||||
/** Runs tests and invokes `onComplete()` when finished. */
|
||||
run(onComplete?: (failures: number) => void): Mocha.IRunner;
|
||||
}
|
||||
|
||||
// merge the Mocha class declaration with a module
|
||||
declare module Mocha {
|
||||
/** Partial interface for Mocha's `Runnable` class. */
|
||||
interface IRunnable {
|
||||
title: string;
|
||||
fn: Function;
|
||||
async: boolean;
|
||||
sync: boolean;
|
||||
timedOut: boolean;
|
||||
}
|
||||
|
||||
/** Partial interface for Mocha's `Suite` class. */
|
||||
interface ISuite {
|
||||
parent: ISuite;
|
||||
title: string;
|
||||
|
||||
fullTitle(): string;
|
||||
}
|
||||
|
||||
/** Partial interface for Mocha's `Test` class. */
|
||||
interface ITest extends IRunnable {
|
||||
parent: ISuite;
|
||||
pending: boolean;
|
||||
|
||||
fullTitle(): string;
|
||||
}
|
||||
|
||||
/** Partial interface for Mocha's `Runner` class. */
|
||||
interface IRunner {}
|
||||
|
||||
interface IContextDefinition {
|
||||
(description: string, spec: () => void): ISuite;
|
||||
only(description: string, spec: () => void): ISuite;
|
||||
skip(description: string, spec: () => void): void;
|
||||
timeout(ms: number): void;
|
||||
}
|
||||
|
||||
interface ITestDefinition {
|
||||
(expectation: string, assertion?: () => void): ITest;
|
||||
(expectation: string, assertion?: (done: MochaDone) => void): ITest;
|
||||
only(expectation: string, assertion?: () => void): ITest;
|
||||
only(expectation: string, assertion?: (done: MochaDone) => void): ITest;
|
||||
skip(expectation: string, assertion?: () => void): void;
|
||||
skip(expectation: string, assertion?: (done: MochaDone) => void): void;
|
||||
timeout(ms: number): void;
|
||||
}
|
||||
|
||||
export module reporters {
|
||||
export class Base {
|
||||
stats: {
|
||||
suites: number;
|
||||
tests: number;
|
||||
passes: number;
|
||||
pending: number;
|
||||
failures: number;
|
||||
};
|
||||
|
||||
constructor(runner: IRunner);
|
||||
}
|
||||
|
||||
export class Doc extends Base {}
|
||||
export class Dot extends Base {}
|
||||
export class HTML extends Base {}
|
||||
export class HTMLCov extends Base {}
|
||||
export class JSON extends Base {}
|
||||
export class JSONCov extends Base {}
|
||||
export class JSONStream extends Base {}
|
||||
export class Landing extends Base {}
|
||||
export class List extends Base {}
|
||||
export class Markdown extends Base {}
|
||||
export class Min extends Base {}
|
||||
export class Nyan extends Base {}
|
||||
export class Progress extends Base {
|
||||
/**
|
||||
* @param options.open String used to indicate the start of the progress bar.
|
||||
* @param options.complete String used to indicate a complete test on the progress bar.
|
||||
* @param options.incomplete String used to indicate an incomplete test on the progress bar.
|
||||
* @param options.close String used to indicate the end of the progress bar.
|
||||
*/
|
||||
constructor(runner: IRunner, options?: {
|
||||
open?: string;
|
||||
complete?: string;
|
||||
incomplete?: string;
|
||||
close?: string;
|
||||
});
|
||||
}
|
||||
export class Spec extends Base {}
|
||||
export class TAP extends Base {}
|
||||
export class XUnit extends Base {
|
||||
constructor(runner: IRunner, options?: any);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare module "mocha" {
|
||||
export = Mocha;
|
||||
}
|
19
samples/react-real-time/client/typings/react/react-addons-shallow-compare.d.ts
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Type definitions for React v0.14 (react-addons-css-transition-group)
|
||||
// Project: http://facebook.github.io/react/
|
||||
// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
|
||||
/// <reference path="react.d.ts" />
|
||||
|
||||
declare namespace __React {
|
||||
namespace __Addons {
|
||||
export function shallowCompare<P, S>(
|
||||
component: __React.Component<P, S>,
|
||||
nextProps: P,
|
||||
nextState: S): boolean;
|
||||
}
|
||||
}
|
||||
|
||||
declare module "react-addons-shallow-compare" {
|
||||
export = __React.__Addons.shallowCompare;
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
// Type definitions for React v0.14 (react-addons-test-utils)
|
||||
// Project: http://facebook.github.io/react/
|
||||
// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
/// <reference path="react.d.ts" />
|
||||
|
||||
declare namespace __React {
|
||||
interface SyntheticEventData {
|
||||
altKey?: boolean;
|
||||
button?: number;
|
||||
buttons?: number;
|
||||
clientX?: number;
|
||||
clientY?: number;
|
||||
changedTouches?: TouchList;
|
||||
charCode?: boolean;
|
||||
clipboardData?: DataTransfer;
|
||||
ctrlKey?: boolean;
|
||||
deltaMode?: number;
|
||||
deltaX?: number;
|
||||
deltaY?: number;
|
||||
deltaZ?: number;
|
||||
detail?: number;
|
||||
getModifierState?(key: string): boolean;
|
||||
key?: string;
|
||||
keyCode?: number;
|
||||
locale?: string;
|
||||
location?: number;
|
||||
metaKey?: boolean;
|
||||
pageX?: number;
|
||||
pageY?: number;
|
||||
relatedTarget?: EventTarget;
|
||||
repeat?: boolean;
|
||||
screenX?: number;
|
||||
screenY?: number;
|
||||
shiftKey?: boolean;
|
||||
targetTouches?: TouchList;
|
||||
touches?: TouchList;
|
||||
view?: AbstractView;
|
||||
which?: number;
|
||||
}
|
||||
|
||||
interface EventSimulator {
|
||||
(element: Element, eventData?: SyntheticEventData): void;
|
||||
(component: Component<any, any>, eventData?: SyntheticEventData): void;
|
||||
}
|
||||
|
||||
interface MockedComponentClass {
|
||||
new(): any;
|
||||
}
|
||||
|
||||
class ShallowRenderer {
|
||||
getRenderOutput<E extends ReactElement<any>>(): E;
|
||||
getRenderOutput(): ReactElement<any>;
|
||||
render(element: ReactElement<any>, context?: any): void;
|
||||
unmount(): void;
|
||||
}
|
||||
|
||||
namespace __Addons {
|
||||
namespace TestUtils {
|
||||
namespace Simulate {
|
||||
export var blur: EventSimulator;
|
||||
export var change: EventSimulator;
|
||||
export var click: EventSimulator;
|
||||
export var cut: EventSimulator;
|
||||
export var doubleClick: EventSimulator;
|
||||
export var drag: EventSimulator;
|
||||
export var dragEnd: EventSimulator;
|
||||
export var dragEnter: EventSimulator;
|
||||
export var dragExit: EventSimulator;
|
||||
export var dragLeave: EventSimulator;
|
||||
export var dragOver: EventSimulator;
|
||||
export var dragStart: EventSimulator;
|
||||
export var drop: EventSimulator;
|
||||
export var focus: EventSimulator;
|
||||
export var input: EventSimulator;
|
||||
export var keyDown: EventSimulator;
|
||||
export var keyPress: EventSimulator;
|
||||
export var keyUp: EventSimulator;
|
||||
export var mouseDown: EventSimulator;
|
||||
export var mouseEnter: EventSimulator;
|
||||
export var mouseLeave: EventSimulator;
|
||||
export var mouseMove: EventSimulator;
|
||||
export var mouseOut: EventSimulator;
|
||||
export var mouseOver: EventSimulator;
|
||||
export var mouseUp: EventSimulator;
|
||||
export var paste: EventSimulator;
|
||||
export var scroll: EventSimulator;
|
||||
export var submit: EventSimulator;
|
||||
export var touchCancel: EventSimulator;
|
||||
export var touchEnd: EventSimulator;
|
||||
export var touchMove: EventSimulator;
|
||||
export var touchStart: EventSimulator;
|
||||
export var wheel: EventSimulator;
|
||||
}
|
||||
|
||||
export function renderIntoDocument(
|
||||
element: DOMElement<any>): Element;
|
||||
export function renderIntoDocument<P>(
|
||||
element: ReactElement<P>): Component<P, any>;
|
||||
export function renderIntoDocument<C extends Component<any, any>>(
|
||||
element: ReactElement<any>): C;
|
||||
|
||||
export function mockComponent(
|
||||
mocked: MockedComponentClass, mockTagName?: string): typeof TestUtils;
|
||||
|
||||
export function isElementOfType(
|
||||
element: ReactElement<any>, type: ReactType): boolean;
|
||||
export function isDOMComponent(instance: ReactInstance): boolean;
|
||||
export function isCompositeComponent(instance: ReactInstance): boolean;
|
||||
export function isCompositeComponentWithType(
|
||||
instance: ReactInstance,
|
||||
type: ComponentClass<any>): boolean;
|
||||
|
||||
export function findAllInRenderedTree(
|
||||
root: Component<any, any>,
|
||||
fn: (i: ReactInstance) => boolean): ReactInstance[];
|
||||
|
||||
export function scryRenderedDOMComponentsWithClass(
|
||||
root: Component<any, any>,
|
||||
className: string): Element[];
|
||||
export function findRenderedDOMComponentWithClass(
|
||||
root: Component<any, any>,
|
||||
className: string): Element;
|
||||
|
||||
export function scryRenderedDOMComponentsWithTag(
|
||||
root: Component<any, any>,
|
||||
tagName: string): Element[];
|
||||
export function findRenderedDOMComponentWithTag(
|
||||
root: Component<any, any>,
|
||||
tagName: string): Element;
|
||||
|
||||
export function scryRenderedComponentsWithType<P>(
|
||||
root: Component<any, any>,
|
||||
type: ComponentClass<P>): Component<P, {}>[];
|
||||
export function scryRenderedComponentsWithType<C extends Component<any, any>>(
|
||||
root: Component<any, any>,
|
||||
type: ComponentClass<any>): C[];
|
||||
|
||||
export function findRenderedComponentWithType<P>(
|
||||
root: Component<any, any>,
|
||||
type: ComponentClass<P>): Component<P, {}>;
|
||||
export function findRenderedComponentWithType<C extends Component<any, any>>(
|
||||
root: Component<any, any>,
|
||||
type: ComponentClass<any>): C;
|
||||
|
||||
export function createRenderer(): ShallowRenderer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare module "react-addons-test-utils" {
|
||||
import TestUtils = __React.__Addons.TestUtils;
|
||||
export = TestUtils;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
// Type definitions for React v0.14 (react-addons-update)
|
||||
// Project: http://facebook.github.io/react/
|
||||
// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
|
||||
/// <reference path="react.d.ts" />
|
||||
|
||||
declare namespace __React {
|
||||
interface UpdateSpecCommand {
|
||||
$set?: any;
|
||||
$merge?: {};
|
||||
$apply?(value: any): any;
|
||||
}
|
||||
|
||||
interface UpdateSpecPath {
|
||||
[key: string]: UpdateSpec;
|
||||
}
|
||||
|
||||
type UpdateSpec = UpdateSpecCommand | UpdateSpecPath;
|
||||
|
||||
interface UpdateArraySpec extends UpdateSpecCommand {
|
||||
$push?: any[];
|
||||
$unshift?: any[];
|
||||
$splice?: any[][];
|
||||
}
|
||||
|
||||
namespace __Addons {
|
||||
export function update(value: any[], spec: UpdateArraySpec): any[];
|
||||
export function update(value: {}, spec: UpdateSpec): any;
|
||||
}
|
||||
}
|
||||
|
||||
declare module "react-addons-update" {
|
||||
export = __React.__Addons.update;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
// Type definitions for React v0.14 (react-dom)
|
||||
// Project: http://facebook.github.io/react/
|
||||
// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
/// <reference path="react.d.ts" />
|
||||
|
||||
declare namespace __React {
|
||||
namespace __DOM {
|
||||
function findDOMNode<E extends Element>(instance: ReactInstance): E;
|
||||
function findDOMNode(instance: ReactInstance): Element;
|
||||
|
||||
function render<P>(
|
||||
element: DOMElement<P>,
|
||||
container: Element,
|
||||
callback?: (element: Element) => any): Element;
|
||||
function render<P, S>(
|
||||
element: ClassicElement<P>,
|
||||
container: Element,
|
||||
callback?: (component: ClassicComponent<P, S>) => any): ClassicComponent<P, S>;
|
||||
function render<P, S>(
|
||||
element: ReactElement<P>,
|
||||
container: Element,
|
||||
callback?: (component: Component<P, S>) => any): Component<P, S>;
|
||||
|
||||
function unmountComponentAtNode(container: Element): boolean;
|
||||
|
||||
var version: string;
|
||||
|
||||
function unstable_batchedUpdates<A, B>(callback: (a: A, b: B) => any, a: A, b: B): void;
|
||||
function unstable_batchedUpdates<A>(callback: (a: A) => any, a: A): void;
|
||||
function unstable_batchedUpdates(callback: () => any): void;
|
||||
|
||||
function unstable_renderSubtreeIntoContainer<P>(
|
||||
parentComponent: Component<any, any>,
|
||||
nextElement: DOMElement<P>,
|
||||
container: Element,
|
||||
callback?: (element: Element) => any): Element;
|
||||
function unstable_renderSubtreeIntoContainer<P, S>(
|
||||
parentComponent: Component<any, any>,
|
||||
nextElement: ClassicElement<P>,
|
||||
container: Element,
|
||||
callback?: (component: ClassicComponent<P, S>) => any): ClassicComponent<P, S>;
|
||||
function unstable_renderSubtreeIntoContainer<P, S>(
|
||||
parentComponent: Component<any, any>,
|
||||
nextElement: ReactElement<P>,
|
||||
container: Element,
|
||||
callback?: (component: Component<P, S>) => any): Component<P, S>;
|
||||
}
|
||||
|
||||
namespace __DOMServer {
|
||||
function renderToString(element: ReactElement<any>): string;
|
||||
function renderToStaticMarkup(element: ReactElement<any>): string;
|
||||
var version: string;
|
||||
}
|
||||
}
|
||||
|
||||
declare module "react-dom" {
|
||||
import DOM = __React.__DOM;
|
||||
export = DOM;
|
||||
}
|
||||
|
||||
declare module "react-dom/server" {
|
||||
import DOMServer = __React.__DOMServer;
|
||||
export = DOMServer;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Type definitions for System.js 0.18.4
|
||||
// Project: https://github.com/systemjs/systemjs
|
||||
// Definitions by: Ludovic HENIN <https://github.com/ludohenin/>, Nathan Walker <https://github.com/NathanWalker/>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
interface System {
|
||||
import(name: string): any;
|
||||
defined: any;
|
||||
amdDefine: () => void;
|
||||
amdRequire: () => void;
|
||||
baseURL: string;
|
||||
paths: { [key: string]: string };
|
||||
meta: { [key: string]: Object };
|
||||
config: any;
|
||||
}
|
||||
|
||||
declare var System: System;
|
||||
|
||||
declare module "systemjs" {
|
||||
export = System;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/// <reference path="@ms/odsp.d.ts" />
|
||||
/// <reference path="@ms/odsp-webpack.d.ts" />
|
||||
/// <reference path="assertion-error/assertion-error.d.ts" />
|
||||
/// <reference path="chai/chai.d.ts" />
|
||||
/// <reference path="es6-collections/es6-collections.d.ts" />
|
||||
/// <reference path="lodash/lodash.d.ts" />
|
||||
/// <reference path="mocha/mocha.d.ts" />
|
||||
/// <reference path="node/node.d.ts" />
|
||||
/// <reference path="react/react.d.ts" />
|
||||
/// <reference path="react/react-addons-shallow-compare.d.ts" />
|
||||
/// <reference path="react/react-addons-test-utils.d.ts" />
|
||||
/// <reference path="react/react-addons-update.d.ts" />
|
||||
/// <reference path="react/react-dom.d.ts" />
|
||||
/// <reference path="systemjs/systemjs.d.ts" />
|
||||
/// <reference path="knockout/knockout.d.ts" />
|
||||
/// <reference path="combokeys/combokeys.d.ts" />
|
|
@ -0,0 +1,3 @@
|
|||
debuggingEnabled: true
|
||||
loggingEnabled: true
|
||||
devErrorsEnabled: true
|
|
@ -0,0 +1 @@
|
|||
<h1>SPFx with Socket IO demo</h1>
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "spfx-socket.io",
|
||||
"author": {
|
||||
"name": "Franck Cornu @FranckCornu (http://thecollaborationcorner.com)"
|
||||
},
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node server"
|
||||
},
|
||||
"engines": {
|
||||
"node": "6.9.0"
|
||||
},
|
||||
"license": "Apache",
|
||||
"dependencies": {
|
||||
"azure": "^1.2.0-preview",
|
||||
"express": "^4.14.0",
|
||||
"socket.io": "^1.4.8"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// Port will be assigned automatically by the Azure Web App (rocess.env.port ). For localhost debugging, we use 8080.
|
||||
// You can use the built-in Visual Studio Code debugger to test the solution locally.
|
||||
var port = process.env.port || 8080;
|
||||
var app = require('express')();
|
||||
var server = require('http').Server(app);
|
||||
var io = require('socket.io')(server);
|
||||
var azure = require('azure');
|
||||
|
||||
server.listen(port);
|
||||
|
||||
app.get('/', function (req, res) {
|
||||
res.sendfile(__dirname + '/index.html');
|
||||
});
|
||||
|
||||
// Service Bus Connection string is retrieved from the app env app settings
|
||||
var serviceBusService = azure.createServiceBusService(process.env.AZURE_SERVICEBUS_ACCESS_KEY);
|
||||
|
||||
// Listener function to pull the Azure service bus and see if new messages are available
|
||||
setInterval(function() {
|
||||
|
||||
serviceBusService.receiveQueueMessage('news', function(error, message){
|
||||
if(!error) {
|
||||
|
||||
// Message received and deleted (default behavior of the service bus)
|
||||
console.log(message);
|
||||
|
||||
// Broadcast to all connected clients
|
||||
io.emit('item:added', message );
|
||||
}
|
||||
});
|
||||
|
||||
}, 5 );
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0"?>
|
||||
<pnp:Provisioning xmlns:pnp="http://schemas.dev.office.com/PnP/2016/05/ProvisioningSchema">
|
||||
<pnp:Preferences Generator="OfficeDevPnP.Core, Version=2.7.1609.3, Culture=neutral, PublicKeyToken=3751622786b357c2" />
|
||||
<pnp:Templates ID="CONTAINER-TEMPLATE-SOCKETIO-SPFX-DEMO">
|
||||
<pnp:ProvisioningTemplate ID="TEMPLATE-SOCKETIO-SPFX-DEMO" Version="1" BaseSiteTemplate="STS#0">
|
||||
<pnp:Lists>
|
||||
<pnp:ListInstance Title="NewsList" Description="" DocumentTemplate="" OnQuickLaunch="true" TemplateType="100" Url="Lists/NewsList" MinorVersionLimit="0" MaxVersionLimit="0" DraftVersionVisibility="0" TemplateFeatureID="00bfea71-de22-43b2-a848-c05709900100" ContentTypesEnabled="true" EnableFolderCreation="false">
|
||||
<pnp:ContentTypeBindings>
|
||||
<pnp:ContentTypeBinding ContentTypeID="0x01" Default="true" />
|
||||
<pnp:ContentTypeBinding ContentTypeID="0x0120" />
|
||||
</pnp:ContentTypeBindings>
|
||||
<pnp:Views>
|
||||
<View Name="{DE788C87-CF02-47BF-A0F1-F0C9991102BC}" DefaultView="TRUE" MobileView="TRUE" MobileDefaultView="TRUE" Type="HTML" DisplayName="All Items" Url="/sites/dev/Lists/NewsList/AllItems.aspx" Level="1" BaseViewID="1" ContentTypeID="0x" ImageUrl="/_layouts/15/images/generic.png?rev=44">
|
||||
<Query>
|
||||
<OrderBy>
|
||||
<FieldRef Name="ID" />
|
||||
</OrderBy>
|
||||
</Query>
|
||||
<ViewFields>
|
||||
<FieldRef Name="LinkTitle" />
|
||||
<FieldRef Name="Description" />
|
||||
<FieldRef Name="PreviewImageUrl" />
|
||||
</ViewFields>
|
||||
<RowLimit Paged="TRUE">30</RowLimit>
|
||||
<JSLink>clienttemplates.js</JSLink>
|
||||
</View>
|
||||
</pnp:Views>
|
||||
<pnp:Fields>
|
||||
<Field Type="Note" Title="Description" DisplayName="Description" Required="FALSE" ID="{d36bc9f3-9330-43cf-b8de-414abf9596f5}" SourceID="{{listid:NewsList}}" StaticName="Description" Name="Description" ColName="ntext2" RowOrdinal="0" Version="1" />
|
||||
<Field Type="URL" DisplayName="PreviewImageUrl" Required="FALSE" EnforceUniqueValues="FALSE" Indexed="FALSE" Format="Image" ID="{53bc2547-9c8e-4b0b-b1ab-9c686d07ac1e}" SourceID="{{listid:NewsList}}" StaticName="PreviewImageUrl" Name="PreviewImageUrl" ColName="nvarchar3" RowOrdinal="0" ColName2="nvarchar4" RowOrdinal2="0" Version="1" />
|
||||
</pnp:Fields>
|
||||
</pnp:ListInstance>
|
||||
</pnp:Lists>
|
||||
</pnp:ProvisioningTemplate>
|
||||
</pnp:Templates>
|
||||
</pnp:Provisioning>
|